阅读更多
引用
本文来自:阿里聚安全博客

作者:蒸米@阿里聚安全


0x00 序

随着移动安全越来越火,各种调试工具也都层出不穷,但因为环境和需求的不同,并没有工具是万能的。另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中(共7篇)分享一些自己经常用或原创的调试工具以及手段,希望能对国内移动安全的研究起到一些催化剂的作用。

0x01 长生剑

长生剑是把神奇的剑,为白玉京所配,剑名取意来自于李白的诗:“仙人抚我 顶,结发受长生。”长生剑是七种武器系列的第一种武器,而笔者接下来所要介绍的调试方法也是我最早学习的调试方法,并且这种方法就像长生剑一样,简单并一直都有很好的效果。这种方法就是Smali Instrumentation,又称Smali 插桩。使用这种方法最大的好处就是不需要对手机进行root,不需要指定android的版本,如果结合一些tricks的话还会有意想不到的效果。

0x02 Smali/baksmali

做安卓逆向最先接触到的东西肯定就是smali语言了,smali最早是由Jasmin提出,随后jesusfreke开发了最有名的smali和baksmali工具将其发扬光大,几乎dex上所有的静态分析工具都是在这个项目的基础上建立的。什么?你没听说过smali和baksmali?你只用过Apktool?如果你仔细阅读了Apktool官网的说明你就会发现,Apktool其实只是一个将各种工具结合起来的懒人工具而已。并且笔者建议从现在起就抛弃Apktool吧。原因如下:首先,Apktool更新并没有smali/baksmali频繁,smali/baksmali更新后要过非长久的时间才会合并到Apktool中,在这之前你可能需要忍受很多诡异的bug。其次,Apktool在反编译或者重打包dex的时候,如果发生错误,仅仅只会提供错误的exception信息而已,但如果你使用smali/baksmali,工具会告诉你具体的出错原因,会对重打包后的调试有巨大的帮助。最后,很多apk为了对付反调试会在资源文件中加入很多junk code从而使得Apktool的解析崩溃掉,造成反编译失败或者无法重打包。但如果你仅对classes.dex操作就不会有这些问题了。
学习smali最好的方法就是自己先用java写好程序,再用baksmali转换成smali语句,然后对照学习。比如下面就是java代码和用baksmali反编译过后的smali文件的对照分析。
MZLog类主要是用Log.d()输出调试信息,Java代码如下:



对应的smali代码如下:



最后简单介绍一下smali常用的数据类型:



0x03 Smali插桩

如果仅仅用Smali来分析代码,效果其实不如用dex2jar和jd-gui更直观,毕竟看反编译的java代码要更容易一些。但Smali强大之处就是可以随心所欲的进行插桩操作。何为插桩,引用一下wiki的解释:程序插桩,最早是由J.C. Huang 教授提出的,它是在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针(又称为“探测仪”),通过探针的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息,从而实现测试目的的方法。下面我就来结合一个例子来讲解一下何如进行smali插桩。

测试程序是一个简单的crackme (图1)。输入密码,然后点击check,如果密码正确会输出yes,否则输出no。



图1 Crackme1的界面


首先我们对crackme这个apk进行解压,然后反编译。我们会在MainActivity中看到一个getkey(String,int)函数。这个函数貌似非常复杂,我们暂时不管。我们首先分析一下点下button后的逻辑。我们发现程序会通过getkey("mrkxqcroxqtskx",42)来计算出真正的密码,然后与我们输人的密码进行比较,java代码如下:



这时候就是smali插桩大显身手的时候了,我们可以通过插桩直接获取getkey("mrkxqcroxqtskx",42)这个函数的返回值,然后Log出来。这样我们就不需要研究getkey这个函数的实现了。具体过程如下:
1 首先解压apk然后用baksmali进行反编译。



2 将上一节MZLog类的MZLog.smali文件拷贝到com/mzheng目录下,这个文件有3个LOG函数,分别可以输出String的值,Object的值和Object数组的值。注意,如果原程序中没有com/mzheng这个目录,你需要自己用mkdir创建一下。拷贝完后,目录结构如下:



3 用文本编辑器打开MainActivity$1.smali文件进行插桩。为什么是MainActivity$1.smali而不是MainActivity.smali呢?因为主要的判断逻辑是在OnClickListener这个类里,而这个类是MainActivity的一个内部类,同时我们在实现的时候也没有给这个类声明具体的名字,所以这个类用$1表示。加入MZLog.smali这个文件后,我们只需要在MainActivity$1.smali的第71行后面加上一行代码,invoke-static {v1}, Lcom/mzheng/MZLog;->Log(Ljava/lang/Object;)V,就可以输出getkey的值了。Invoke是方法调用的指令,因为我们要调用的类是静态方法,所以使用invoke-static。如果是非静态方法的话,第一个参数应该是该方法的实例,然后依次是各个参数。具体插入情况如下:



4 用smali.jar重新编译修改后的smali文件,把新编译的classes.dex覆盖老的classes.dex,然后再用signapk.jar对apk进行签名。几条关键指令如下:



5 安装程序到android,随便输入点啥,然后点击check按钮,随后在logcat中就可以看到getkey("mrkxqcroxqtskx",42)这个函数的返回值了(图2)。



图2 通过logcat获取getkey的返回值

0x03 Smali修改

通过Smali/baksmali工具,我们不光可以插桩,还可以修改apk的逻辑。几个需要注意点如下:

1. if条件判断以及跳转语句
在smali中最常见的就是if这个条件判断跳转语句了,这个判断一共有12条指令:



比如我们在crackme1里判断密码是否正确的smali代码段:



如果我们不关心密码内容,只是希望程序输出”yes”的话。我们可以把if-eqz v1, :cond_25改成if-nez v1, :cond_25。这样逻辑就变为:当输错密码的时候,程序反而会输出”yes”。

2. 寄存器问题
修改Smali时有一件很重要的事情就是要注意寄存器。如果乱用寄存器的话可能会导致程序崩溃。每个方法开头声明了registers的数量,这个数量是参数和本地变量总和。参数统一用P表示。如果是非静态方法p0代表this,p1-pN代表各个参数。如果是静态方法的话,p0-pN代表各个参数。本地变量统一用v表示。如果想要增加的新的本地变量,需要在方法开头的registers数量上增加相应的数值。
比如下面这个方法:



因为这不是静态方法,所以p0代表this。如果想要增加一个新的本地变量,比如v0。就需要把.registers 1改为.registers 2。

3. 给原程序增加大量逻辑的办法
我非常不建议在程序原有的方法上增加大量逻辑,这样可能会出现很多寄存器方面的错误导致编译失败。比较好的方法是:把想要增加的逻辑先用java写成一个apk,然后把这个apk反编译成smali文件,随后把反编译后的这部分逻辑的smali文件插入到目标程序的smali文件夹中,然后再在原来的方法上采用invoke的方式调用新加入的逻辑。这样的话不管加入再多的逻辑,也只是修改了原程序的几行代码而已。这个思路也是很多重打包病毒惯用的伎俩,确实非常方便好用。

0x04 APK签名Tricks

当我们在实战中,有时会碰到某些apk在内部实现了自己的签名检查。这次我们介绍的Smali Instrumentation方法因为需要重打包,所以会改变原有的签名。当然,你可以通过修改apk把签名检查的逻辑删掉,但这又费时又费力。笔者在这里简单介绍两种非常方便的方法来解决签名检查问题。

1. Masterkey
Masterkey漏洞一共有三个,可以影响android 4.4以下版本。利用这个漏洞,我们可以插入新的classes.dex替换掉原有的classes.dex而不需要对apk本身进行重新签名。如果apk本身有签名校验逻辑的话,利用这个漏洞来进行Smali Instrumentation简直再好不过了。首先,你需要一个android 4.4以下版本的虚拟机或者真机,然后再使用一个masterkey利用工具对apk进行exploit即可。工具下载地址在文章最后,使用的命令如下:



orig.apk是原本的apk文件,moddedClassesDex.zip是修改后的classes.dex并压缩成zip文件,out.apk就是利用Masterkey漏洞生成的新的apk文件。如果成功的话用rar打开文件会看到两个classes.dex。



图3 Masterkey生成的apk文件有两个classes.dex文件
通过masterkey打包后的apk文件签名并不会有任何变化,这样也就不用担心签名校验问题了。

2. 自定义ROM
签名的判断其实是调用了android系统密码库的函数,如果我们可以自己定制ROM的话,只需要修改AOSP源码路径下的libcore\luni\src\main\java\java\security\MessageDigest.java文件。将isEqual函数中的判断语句注释掉:



这样的话,如果在你自定义的ROM上运行apk,无论你怎么修改classes.dex文件,都不需要关心签名问题了,系统会永远返回签名正确的。

0x05 小结

虽然现在越来越多的apk开始使用so文件进行逻辑处理和加固,android 4.4也加入art运行环境,但dalvik永远是android最经典的东西。如果想要学好android逆向,一定要把这部分知识学好。并且把smali研究透彻以后,会对我们以后要讲的自定义dalvik虚拟机有很大帮助。另外文章中所有提到的代码和工具都可以在我的github下载到,地址是: https://github.com/zhengmin1989/TheSevenWeapons

0x06 参考文章

Way of the AndroidCracker http://androidcracking.blogspot.hk/p/way-of-android-cracker-lessons.html
Android Master Key Exploit – Uncovering Android Master Key
https://bluebox.com/technical/uncovering-android-master-key-that-makes-99-of-devices-vulnerable/
https://github.com/Fuzion24/AndroidZipArbitrage
Min Zheng, Patrick P. C. Lee, John C. S. Lui. "ADAM: An Automatic and Extensible Platform to Stress Test Android Anti-Virus Systems", DIMVA 2012
  • 大小: 32 KB
  • 大小: 92.7 KB
  • 大小: 11.5 KB
  • 大小: 34 KB
  • 大小: 28.4 KB
  • 大小: 7.2 KB
  • 大小: 25.3 KB
  • 大小: 63.7 KB
  • 大小: 11.6 KB
  • 大小: 3.9 KB
  • 大小: 74.7 KB
  • 大小: 84.7 KB
  • 大小: 15.7 KB
  • 大小: 8.7 KB
  • 大小: 15.3 KB
  • 大小: 24 KB
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • android动态调试七种武器,安卓动态调试七种武器之长生剑 - Smali Instrumentation

    安卓动态调试七种武器之长生剑 - Smali Instrumentation0x00 序随着移动安全越来越火,各种调试工具也都层出不穷,但因为环境和需求的不同,并没有工具是万能的。另外工具是死的,人是活的,如果能搞懂工具的原理再...

  • 阿里聚安全 博客 ------安卓动态调试七种武器之长生剑

    http://www.cnblogs.com/alisecurity/p/5526811.html https://jaq.alibaba.com/community/category?spm=a313e.7916648.21000000.2.HJ9Tsr&catid=4 转载于:https://www.cnblogs.com/zengkefu/p/5535328.html

  • 1 长生剑 - Smali Instrumentation

    ”长生剑是七种武器系列的第一种武器,而笔者接下来所要介绍的调试方法也是我最早学习的调试方法,并且这种方法就像长生剑一样,简单并一直都有很好的效果。这种方法就是Smali Instrumentation,又称Smali 插桩。...

  • 安卓动态调试七种武器之离别钩 – Hooking(上)

    ...随着移动安全越来越火,各种调试工具也都层出不穷,但...另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中分享一些

  • 安卓动态调试七种武器之孔雀翎 – Ida Pro

    作者:蒸米 ...另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中分享一些自己经常用或原创的调试工具以及手

  • 安卓动态调试七种武器之离别钩 – Hooking(下)

    另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中分享一些自己经常用或原创的调试工具以及手段,希望能

  • 安卓动态调试七种武器之孔雀翎 – Ida Pro – 蒸米

    另外工具是死的,人是活的,如果能搞懂工具的原理再结合上自身的经验,你也可以创造出属于自己的调试武器。因此,笔者将会在这一系列文章中分享一些自己经常用或原创的调试工具以及手段,希望能对国内移动安全的研究...

  • 基于java+springboot+mysql+微信小程序的流浪动物救助小程序 源码+数据库+论文(高分毕业设计).zip

    项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea、微信开发者工具 数据库:MySql5.7以上 部署环境:maven 数据库工具:navicat

  • 基于springboot的体质测试数据分析及可视化设计源码(java毕业设计完整源码+LW).zip

    项目均经过测试,可正常运行! 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea

  • python 3.8.20 windows install 安装包

    编译的 python 3.8.20 windows install 安装包

  • 基于go-zero的用户管理系统全部资料+详细文档.zip

    【资源说明】 基于go-zero的用户管理系统全部资料+详细文档.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

  • 基于springboot的时间管理系统源码(java毕业设计完整源码+LW).zip

    时间管理系统采用java技术,基于springboot框架,mysql数据库进行开发,实现了首页,个人中心,系统公告管理,用户管理,时间分类管理,事件数据管理,目标数据管理,用户日记管理等内容进行管理。 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea

  • 基于springboot的火车订票管理系统源码(java毕业设计完整源码+LW).zip

    项目均经过测试,可正常运行! 环境说明: 开发语言:java JDK版本:jdk1.8 框架:springboot 数据库:mysql 5.7/8 数据库工具:navicat 开发软件:eclipse/idea

  • 收到防护服快快快啊啊啊啊啊

    收到防护服快快快啊啊啊啊啊

  • 葡萄城手册,快速上手,灵活报表

    制作报表

  • simulink相位调制器PM

    simulink相位调制器PM

  • 2023-04-06-项目笔记 - 第三百六十阶段 - 4.4.2.358全局变量的作用域-358 -2025.12.27

    2023-04-06-项目笔记-第三百六十阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.358局变量的作用域_358- 2024-12-27

  • (59423620)指纹识别基于matlab GUI指纹识别【含Matlab源码 1353期】.zip

    【指纹识别】基于matlab GUI指纹识别是一种生物特征识别技术,它利用了人类指纹的唯一性和稳定性进行身份验证。在本项目中,我们探讨的是如何使用MATLAB图形用户界面(GUI)来实现这一过程,包括图像采集、预处理、特征提取和匹配等多个步骤。 指纹图像的采集是整个系统的基础。这通常通过专用的指纹传感器完成,它们可以捕获高质量的指纹图像。在MATLAB中,我们可以使用摄像头或其他图像输入设备模拟这一过程,将捕获的图像导入到GUI中。 接下来是预处理阶段。指纹图像往往含有噪声和不清晰的部分,因此需要进行图像增强,以突出指纹的细节特征,如脊线和谷线。这可能包括二值化、直方图均衡化、滤波等操作。MATLAB的图像处理工具箱提供了丰富的函数支持这些预处理步骤。 特征提取是识别的核心环节。指纹的特征通常包括核心点、三角点、终结点以及脊线的方向和纹路模式。MATLAB中可以使用方向图像和细化算法来检测这些特征点,并生成特征描述符。例如,使用Gabor滤波器可以提取脊线方向信息,而细化算法可以帮助找到特征点。 GUI设计是用户交互的关键。在这里,用户可以上传指纹图像,系统会实时显示预处理和特征提取的

  • 基于Go后端的外挂式评论系统全部资料+详细文档.zip

    【资源说明】 基于Go后端的外挂式评论系统全部资料+详细文档.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

  • nosql分布式数据库期末考试题a.docx

    ### NoSQL分布式数据库知识点解析 #### 一、选择题知识点详解 **1. 关系数据库与非关系数据库** - **关系数据库**: MySQL、SQL Server 和 Oracle 均属于关系数据库,它们采用 SQL 作为标准查询语言,支持 ACID 特性(原子性、一致性、隔离性和持久性)。 - **非关系数据库**: 指的是不采用表格形式来组织数据的数据库类型,通常用于处理大量非结构化或半结构化数据。 **2. 数据库语言分类** - **数据定义语言 (DDL)**: 用于定义数据库结构的语言,如创建、修改和删除表等操作。 - **数据操纵语言 (DML)**: 用于添加、修改和删除数据的语言,如 INSERT、UPDATE 和 DELETE 等命令。 - **数据查询语言 (DQL)**: 用于查询数据的语言,主要是 SELECT 语句。 - **数据控制语言 (DCL)**: 用于管理权限和安全性的语言,如 GRANT 和 REVOKE 命令。 **3. 关系数据库优点** - **易于理解**: 使用表格形式组织数据,符合人类直观认知习惯。 - **易于维护**: 支持事务处理,确保数据一致性。 - **支持 SQL**: 使用标准查询语言,便于数据查询和处理。 **4. MongoDB 编程语言** - **JavaScript**: MongoDB 是用 C++ 开发的,但其 Shell 环境使用 JavaScript,使得数据查询和管理更加便捷。 **5. NoSQL 数据库特点** - **分布式**: 能够在多台计算机上分布存储数据,适用于大数据量的处理。 - **不基于 ACID**: 相对于传统的关系数据库,NoSQL 数据库往往牺牲了部分 ACID 特性以换取更高的性能和可扩展性。 **6. CAP 理论** - **一致性 (C)**: 所有节点在同一时间具有相同的数据。 - **可用性 (A)**: 每个请求都能得到一个合理的时间内非错误的响应,但不保证是最新的数据。 - **分区容错性 (P)**: 系统中任意信息丢失的子网故障都不会导致整个系统不可用。 - **CAP 定理**: 在一个分布式系统中,只能同时满足一致性、可用性和分区容错性中的两个。 **7. 知识图谱与 NoSQL 数据库** - **MongoDB**: 适合用于构建知识图谱,因为它支持灵活的数据模型和高效的查询能力。 - **Redis**: 一种键值存储数据库,适用于缓存和实时数据分析。 - **HBase**: 一种列族存储数据库,适合大规模随机读写访问。 **8. HBase 特点** - **容量巨大**: 可以存储非常大量的数据。 - **列存储**: 数据按列族存储,方便进行列级别的访问。 - **稀疏性**: 允许某些列未填充,即某些单元格为空。 **9. HBase 核心组件** - **HMaster**: 负责协调客户端请求、分配 Region 以及负载均衡等工作。 - **RegionServer**: 存储数据的实际服务器。 - **Zookeeper**: 用于协调分布式环境中的服务,例如选举 HMaster。 **10. MongoDB 集合命名规则** - **system.**: 系统保留前缀,用于系统集合。 - **保留字符 $**: 用于特殊目的,如聚合管道。 - **空字符串**: 不允许作为集合名称。 **11. MongoDB 主键** - **UUID**: 通用唯一识别码,常用于作为主键。 - **Sequence**: 序列,也可以作为主键生成方式之一。 - **Auto-increment**: 自动递增,MongoDB 默认为主键使用 BSON 类型的 ObjectId。 **12. MongoDB 逻辑结构** - **数据库 (db)**: MongoDB 中的最高层级,可以包含多个集合。 - **集合 (collection)**: 数据库内的数据容器,类似于关系数据库中的表。 - **文档 (document)**: 数据的基本单位,由键值对组成。 **13. 内存数据库** - **Redis**: 键值存储数据库,常作为内存数据库使用。 - **MongoDB**: 非内存数据库,但可以通过配置将常用数据驻留在内存中。 - **Bigtable**: 谷歌的分布式数据存储系统,并非专门设计为内存数据库。 **14. Neo4j 图形数据库应用场景** - **快递物流数据管理**: 适用于关系较为复杂的数据管理场景。 - **家庭用电数据管理**: 更偏向于使用时序数据库。 - **企业考勤数

Global site tag (gtag.js) - Google Analytics