分析一个android应用时,核心算法代码大部分都在so库中,除了使用IDA静态分析,还需要通过动态调试来获取执行流程以及中间数据。这里记录的是使用IDA进行调试的方法,相比而言,IDA动态调试时不能看到浮点寄存器的数值,只能分析流程,但是可以利用IDC脚本快捷的获取中间数据。
1、使用adb的push命令,把IDA安装目录下的android_server拷贝到手机目录/data/local/tmp/,然后对此目录提权并运行android_server,其Python代码如下:
# 本程序执行android手机的android_server以便IDA附加到进程进行调试
import os
os.system("adb shell chmod 755 /data/local/tmp/android_server")
os.system("adb shell /data/local/tmp/android_server")
2、监听端口23946,Python代码:
# 监听23946端口
import os
os.system("adb forward tcp:23946 tcp:23946")
(以上代码可以写成一个Python文件,这样每次需要调试时直接运行脚本就可以,不需要一次次手动输入命令运行)
4、选择需要调试的进程,如果需要定位到某个so库,可Alt+F7使用IDA Python代码,输入so库名称即可跳转到库基址:
# -*- coding: cp936 -*-
# 本程序用于在Android动态调试时定位并跳转到特定的so模块
import idc
import os
somodule = AskStr('input the name of so module', 'locat the module')
modulebase = GetFirstModule()
while (modulebase != None) and (GetModuleName(modulebase).find(somodule) == -1):
modulebase = GetNextModule(modulebase)
if modulebase == None:
print 'failed to find module:' , somodule
else:
Jump(modulebase);
print 'module of' , somodule , 'base address is :' , hex(modulebase)
之后就可以根据静态分析的结果,跳转到具体的函数下断并调试。
很多时候需要在某处汇编代码截取中间数据,而此处代码在一个循环中,这时可以下一个断点,然后编辑断点条件,把以下dump数据的Python写上去,之后每次执行到这个位置都会执行一次代码,缺点是执行速度比较慢:
# -*- coding: cp936 -*-
# 本程序作为IDA条件断点的expression使用,用于执行到某一句代码时dump下R0指向的R1*R2大小的内存,写文件方式为追加到文件末尾
import idc
import os
R0 = GetRegValue("R0");
R1 = GetRegValue("R1");
R2 = GetRegValue("R2");
R3 = GetRegValue("R3");
R4 = GetRegValue("R4");
R7 = GetRegValue("R7");
if os.path.isfile("filepath"):
size = os.path.getsize("filepath");
else:
size = 0;
savefile("filepath", size, R7, sizitowrite);
当需要用本地的数据来替换被调试程序内存中一块数据时,可以使用以下脚本:
# -*- coding: cp936 -*-
# 本模块用某一个文件的数据覆盖R2指向的内存的数据,数据大小是文件大小
import idc
import os
backupfile = AskFile(0, '*.*', 'select the file to load')
size = os.path.getsize(backupfile)
ea = GetRegValue('R2')
loadfile(backupfile, 0, ea, size)