赞
踩
历史文章了,补发上来
动态分析(dynamic analysis)是指在严格控制的环境(沙盒)中执行恶意软件,并使用系统检测实用工具记录其所有行为
静态分析(static analysis)通过浏览程序代码来理解程序的行为。
关于动静态分析,两者目的是相同的,无非是破解软件,分析软件行为,但是动态分析会比静态高效一点,
由于对静态分析比较熟悉,先说一下静态分析的思路。
你是要破解APP,为了获取什么:
运行APP,查看log、toast、运行信息等;
全局查找关键字符串和日志信息
大部分加密函数,关键函数会放在so文件里,用ida分析so文件,可以帮助我们定位到关键函数,然后继续修改smali,从而达到我们破解的目的。
但是今天不讲静态分析。
以阿里Crackme为例,学习ida native分析。
1.反编译
用AndroidKiller对目标apk进行反编译;
反编译成功后,为了后面的动态调试,需要我们做两件事;
1.在AndroidManifest.xml中添加android:debuggable=”true”
2.在入口处添加waitForDebugger代码进行等待调试
找到入口,添加一行代码:invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
其实对应的Java代码就是:android.os.Debug.waitForDebugger();
保存,再点击编译,编译成功;AndroidKiller会自动对apk进行签名,这也是其方便之处;
再次反编译,可以看到java源码中增加了Debug.waitForDebugger();函数
1.插件安装
android studio安装smalidea-0.03插件,点击File->Settings->plugins->instal plugins from disk,选择下载的zip包就行,不要解压。安装完成后,AS提示重启生效,重启即可
2.导入工程
点击File->Open,选择文件目录即可
3.设置调试配置
Run->Edit configurations,点击+号,新建remote类型调试器,设置Name, 修改端口号,用DDMS查看应用占用端口,一般都是8700;
盗一张图
4.开始调试
因为我之前添加了waitForDebugger(),所以先下好断点,直接打开app,点击Debug(也就是绿色的那个小按钮),可以看到下图,(如果没有添加waitForDebugger(),可以用命令adbshell am start -D -n com.yaotong.crackme/.MainActivity来打开apk,从而进入调试模式)已经进入调试;
此时,DDMS那边,红色小蜘蛛也变成绿色了,代表已经进入调试了。
开始调试,使用F7单步调试,F8单步跳出进行操作;
至此,已经实现用Android Studio对smali进行动态调试,但是鉴于在实战中用Android Studio对smali进行动态调试的情况很少,原因是一般apk都不会像这些creakme这么小,当apk过大,一步步调试就显得过慢,所以出现用ida进行动态调试。
F5/Tab 翻译成C语言
y 还原JNI函数名
一般JNI函数方法名首先是一个指针加上一个数字,比如v3+676。然后将这个地址作为一个方法指针进行方法调用,并且第一个参数就是指针自己,比如(v3+676)(v3…)。这实际上就是我们在JNI里经常用到的JNIEnv方法。因为Ida并不会自动的对这些方法进行识别,所以当我们对so文件进行调试的时候经常会见到却搞不清楚这个函数究竟在干什么,因为这个函数实在是太抽象了。解决方法非常简单,只需要对JNIEnv指针做一个类型转换即可。
选中v3变量,按下y键;
将声明类型转换成JNIEnv*;
Shift+F12 打开so中所有的字符串内容窗口
Ctrl+S 在IDA View窗口时,是查看segment信息
Ctrl+S 在调试窗口,也就是Debug View时,可以快速定位到我们想要调试的so文件映射到内存
的地址
G 在IDA调试页面的时候,我们可以使用G键快速跳转到指定的内存位置
这里如果跳转到目的地址之后,发现是DCB数据的话,可以在使用 P 键,进行转化即可
F7 可以单步进入调试
F8 可以单步调试
a.在IDA中找到android_server
在IDA安装目录\dbgsrv\android_server
b.将android_server放到设备/data/local/tmp,并执行
用命令adb push
tip: 需要真机,模拟器不能运行,原因是结构不同,一个是arm,一个是x86
此时权限不足,不能执行,需要添加权限;
添加权限;
添加权限后;
执行./android_server;
此时ida仍然连接不上,因为还需要进行端口转发,
adb forward tcp:23946 tcp:23946
c.设置ida连接上设备
选择Debugger–>Attach–>Remote ARMLinux/Android debugger;
设置Hostname为127.0.0.1或者localhost,也就是本地;Port默认23946,不需要改;
在Debug option勾选这三项,方便调试;
点击上面的ok后,会出现下图的进程列表,如果android_server没有以root权限运行,是看不到这么多进程的,所以要以root权限运行,然后找到需要调试的进程,可以试用Search功能进行搜索进程。
以2016阿里的Crackme为例进行调试。
目的:获取密码,或者绕过输入密码的界面;
思路:找到输入密码按钮的关键函数,看是否能找到密码;先静态分析,查看源码,若是调用了so,需要到native层进行静态分析,然后动态调试,对关键函数进行下断点,理清函数执行流程,寻找突破。
这里我使用AndroidKiller打开apk,找到入口为 com.yaotong.crackme.MainActivity
查看并分析源码;发现securityCheck()放在native层调用,这时候我们需要到native层分析。
将libcrackme.so拖到ida中分析,找到securityCheck()函数的位置;一般是完整的包名加函数名,如:Java_com_yaotong_crackme_MainActivity_securityCheck
发现native函数的相对地址:11A8
此时另外打开一个ida,按之前的方式,关联调试应用,选择对应的调试进程;
用ctrl+s找到对应so,也就是libcrackme.so的基地址为:5BA11000
而绝对地址=基地址+相对地址=5BA11000+11A8=5BA121A8;使用G键,直接跳转到这个地址;
选择第一个小蓝点,下个断点,然后F9运行程序;
然后就挂掉了;
这种情况一般就是做了反调试。
先简单说下调试原理,IDA是将android_server在root环境下注入到被调试的进程中,用到的技术是Linux的ptrace,而Android的进程如果被另一个进程ptrace之后,会在相应进程的 status文件中(文件目录/proc/[pid]/status)的一个字段(TracerPid)中标注是被哪个进程ptrace。这里就是反调试的关键。
没有被调试的正常情况,如下:
应用被29443进程号的应用ptrace;
查看29443的pid是谁;
也就是我们之前启动的ida带的android_server了。
常见的反调试技术:
因为AndroidKiller集成大部分功能,所以还是用AndroidKiller来完成这部分。
发现不行。。。
好吧,原因是我debuggable放错地方了。。。 T.T
好了,再来一次;
还是不行,想哭
此时发现正常的调试手段是进不去的,因为此应用的反调试方式是使用了上面的第二种方式,而且还是在底层写了一个检测的循环,原理便是在程序运行过程中,循环检测进程中的TracerPid标识来确定程序是否被调试。只要一运行程序,就退出了调试界面,说明这个循环检测程序执行的时机非常早,已知最早的两个时机是:一个是.init_array,一个是JNI_OnLoad。
那么正常方式进不去,有什么办法是能够在.init_array加载之前就能够进入debug?这是就想到waitForDebugger()函数了,只要把waitForDebugger()放在.init_array加载之前就可以了,但是这里不想又重打包,可以换个方式,用am命令,以调试的方式启动应用。
adb shell am start -D -n com.yaotong.crackme/.MainActivity -D,用debug方式启动
步骤按理应该是如下:
第一步:运行:adb shell am start -D -n com.yaotong.crackme/.MainActivity
出现Debugger的等待状态
第二步:启动IDA 进行目标进程的Attach操作
第三步:运行:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
第四步:设置Debugger Option选项
第五步:点击IDA运行按钮,或者F9快捷键,运行;jdb成功的attach住了,debug消失,正常运行
但是我在第三步的时候jdb连接不上,没办法,看来动态是不行了,只能静态去找反调试的位置了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。