使用 IDA Pro 进行静态分析

  • IDA Pro:目前功能最强大的静态反编译分析工具,具备可交互、可编程、可扩展、多处理器支持等特点,软件逆向分析必备工具

IDA Pro 对 Android 的支持

  • 从 6.1 版本开始提供对 Android 的静态分析与动态调试的支持,包括 Dalvik 指令集的反汇编、原生库(ARM/Thumb 代码)的反汇编、原生库(ARM/Thumb 代码)的动态调试等
  • IDA Pro 6.95 对 Android 的静态分析与动态调试的支持已非常完善
  • 本笔记用的是 7.0 版本

分析 DEX 文件

  • 实例:Crackme0502
  • 解压 APK 取得 classes.dex,打开 IDA Pro,将 DEX 拖入 IDA Pro(或用 IDA Pro 打开 DEX),选择默认选项,等待分析完成
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • IDA Pro 支持以结构化形式显示数据结构。单击“IDA View-A”选项卡,来到反汇编代码界面(其实默认进入的就是此界面),然后单击菜单项“Jump”->“jump to address”,或按“G”键,会弹出地址跳转对话框,输入 0,跳转到 DEX 文件的开头(一开始一般就在开头)。可看到, IDA Pro 已自动解释了结构体信息并加上了注释
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 单击菜单项“Jump”->“Jump to segment”,或按组合键“Ctrl+S”,会弹出段选择对话框。如下图,IDA Pro 将 DEX 分成了 11 个段,每个段所对应的偏移量与 DexHeader 结构体相对应,最后两个段的偏移量可通过计算得出
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • DEX 中所有方法的详细信息可在“Exports”选项卡中查看,方法的命名规则为“类名.方法名@方法声明”
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 在“Exports”中任选一项,如 [email protected],双击,跳转到对应的反汇编代码处
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • IDA Pro 的反汇编代码用 ref 关键字表示非 Java 标准类型的引用。方法第一行中 invoke-super 指令的前半部分如下:
    invoke-super {this, p0}, <ref ResourceCursorAdapter.swapCursor(ref)
  • 前面的 ref 是 swapCursor() 的返回类型,后面括号里的 ref 是参数类型
  • 后半部分的代码是 IDA Pro 智能识别出来的。IDA Pro 能智能识别 Android SDK 的 API 函数,并用 imp 关键字将其标识出来。如第一行中的 invoke-super 指令的后半部分如下:
    imp. @ [email protected]>
  • imp 表示该方法为 Android SDK 中的 API,“@”后的部分为 API 的声明,类名和方法名间用下划线分隔
  • IDA Pro 能识别隐式传递过来的 this 引用。在 smali 语法中用 p0 寄存器传递 this 指针。此处,由于 this 取代了 p0,后面的寄存器命名值都要依次减一
  • IDA Pro 能识别代码中的循环、switch 分支、try/catch 结构,并能将它们用类似高级语言的结构形式显示出来,这对分析大型程序时了解代码结构帮助很大

定位关键代码

  • 用 IDA Pro 定位关键代码的方法整体上与定位 smali 关键代码类似。方法有三种:
  • 一、搜索特征字符串。按组合键“Ctrl+S”,打开段选择对话框,双击“STRINGS”,跳转到字符串段,然后单击菜单项“Search”->“text”,或按组合键“Alt+T”,打开文本搜索对话框,在“String”旁输入要搜索的字符串,单击“OK”,等待片刻即可
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 二、搜索关键 API。按组合键“Ctrl+S”,打开段选择对话框,双击第一个“CODE”,跳转到数据起始段,然后单击菜单项“Search”->“text”,或按组合键“Alt+T”,输入要搜索的 API 名称。若 API 被多次调用,可按组合键“Ctrl+T”搜索下一项
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 三、通过方法名判断方法的功能。此方法较笨拙,因为对混淆过的代码,定位其关键代码是较困难的。如,知道 Crackme0502 程序的主 Activity 类为 MainActivity,在“Exports”中输入“Main”,会自动定位以“Main”开头的行(由此可粗略判断每个方法的作用)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)

**思路一

  • 现在尝试** Crackme0502
  • 先安装 APK,运行后,会出现两个按钮,点击“获取注解”,会以 Toast 弹出三条信息
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 在文本框输入任意字符串,点击“检测***”,会弹出***错误的提示信息
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 以按钮点击事件为突破口查找关键代码
  • 搜索字符串“Main”,发现有两个“onClick()”
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 分别点进去看看
  • 第一个 onClick() 调用了 MainActivity.access$000(),在反汇编界面双击 MainActivity.access,可看到其调用了 MainActivity 的 getAnnotations()。可看出,MainActivity$1.onClick() 是“获取注解”按钮的事件响应代码
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 双击第二个 onClick() ,来到其对应的反汇编代码,按“空格”键切换到 IDA Pro 的流程视图,代码的“分水岭”就是 if-eqz p0, loc_116518,如下图二所示,在第一个方框下,左边的箭头表示条件不满足时程序执行的路线,右边的箭头表示条件满足时执行的路线。可看出,MainActivity$2.onClick() 是“检测***”按钮的事件响应代码
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 经过上面的分析,可知只要修改 if-eqz 指令为 if-nez 即可**程序。修改的过程见第四章的“classes.dex”小节,这里只以截图展示:
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)

**思路二

  • 通过前面的分析可知,MainActivity$SNChecker.isRegistered() 实际上返回了一个 boolean 值,通过判断它的返回值可确定***是否正确
  • 但有个问题:若该程序是个大型 Android 程序,调用***判断的地方可能不止一处
  • 通常有两个解决办法:一、使用 IDA Pro 的交叉引用功能找到所有的方法被调用的地方,然后修改所有的判断结果;二、直接修改 isRegistered(),让它的返回结果永远为 true
  • 现在使用更为“一劳永逸”的第二种办法
  • 下图是对 isRegistered() 方法的分析
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 分析后发现,return v1 为方法返回处,v1 为存储返回值的寄存器,而其值在第二行设为 0(即 false),之后的每次判断若满足条件,就会将 v1 设为 1(即 true),否则,v1 仍为 0。那么,修改就很简单了,只要将第二行的 v1 赋值为 1 即可(Opcode 为 12 11)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 但是出现了问题,安装之后运行会闪退
  • 这时就要检查修改是否正确。用 IDA Pro 重新打开 DEX,发现没改错,推测是程序采取了某种保护措施
  • 之前学过两种退出程序的办法:Context 的 finish() 和 android.os.Process 的 killProcess()。按组合键“Ctrl+S”并双击第一个 CODE,来到代码段,再按组合键“Alt+T”,搜索“finish”和“killProcess”,最后在 MyApp 类的 onCreate() 中找到相应的调用。查看此方法的反汇编代码,发现这段代码使用了 Java 的反射机制,手工调用了 isRegistered() 来检查字符串“11111”是否为合法***。若是合法***或调用 isRegistered() 失败,都说明程序被修改了,会调用 killProcess() 杀死进程。那么,只要把搜到的两处 killProcess() 的调用 NOP(将两处调用的 Opcode 全改成 0)即可
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)
  • 重新安装后运行,输入任意字符串,发现**成功
    第五章 静态分析 Android 程序(五)(使用 IDA Pro 进行静态分析)

相关文章: