Android安全/应用逆向--33--使用IDA Pro进行脱壳

7-10、使用IDA Pro进行脱壳
注:本文之针对加密壳(教学级),高端商业壳的复杂度远远超出想象,目前难以搞定
加壳是为了让自身的classes.dex得到保护,防止APK的源代码被偷窥。

脱壳总目标:到达dvmDexFileOpenPartial 函数处,dump出内存中的dex文件。这也是脱壳的核心思想

Apk脱壳方法有两种:

(1)使用脱壳神器ZjDroid进行脱壳(现在此方法不是很好使,因为很多应用都同步更新自己的防御机制,个人觉得熟练脱壳还是得使用 IDA 进行操练)。
(2)使用 IDA Pro 在 dvmDexFileOpenPartial 这个函数下断点进行脱壳。(大杀技)

虽然加壳能防止源代码被偷窥,但是这只能防止静态分析,无法防止动态调试。不管怎么加壳保护,原始的classes.dex在App运行时都要加载到内存中。所以如果在App加载classes.dex处下个断点,然后再把classes.dex对应内存中的内容抠出来还原成原始的classes.dex文件,就能达到脱壳的目的了。

获取libdbm.so文件

adb pull system/lib/libdvm.so E:/sensor               
//注意:直接在命令行下执行,不需要先执行adb shell。同时主机路径不能是磁盘的根目录,必须要先建文件夹

批注:
adb pull 安卓设备路径 主机路径         //从安卓设备中读出文件
adb push 主机路径 安卓设备路径         //向安卓设备中写入文件
1
2
3
4
5
6
脱壳步骤:
一、架设调试桥
1、上传IDA调试服务器地址:G:\daimashenji\IDAPro70\dbgsrv\android_server
2、cmd进入到该目录下: G:\daimashenji\IDAPro70\dbgsrv
3、导入IDA调试服务器:adb push android_server /data/local/tmp
4、adb shell 
5、cd到/data/local/tmp下:chmod 777 android_server
6、./android_server(如果失败重启手机)

二、部署安卓
1、端口转发:adb forward tcp:23946 tcp:23946
2、adb shell下执行:am start -D -n com.e.te/com.e.te.MainActivity(包名/启动页面)启动页面不一定是这样
3、会弹出框

三、部署IDA(此时打开IDA就行,不要添加任何东西)
1、IDA-debugger-Attach-remote ARMlinux/Android debugger
2、填入IP(localhost/手机IP地址)、密码没有不用填,保存默认网络设置
3、高级设置:左边345,右边:235,下面:3。保存设置
4、点击要调试的包名选入
5、此时相关的应用程序将显示红色蜘蛛,如果遇到弹窗,一律点击取消Cancel,以及Apply

注意:此时可以再开一个IDA32位,用于静态分析libdvm.so

四、开始下断
1、此时已经进入动态调试页面

2、IDA--debugger--debugger windows--module list,查找libdvm.so并双击进入
注:在Dalvik虚拟机中是libdvm.so,在ART虚拟机中是libart.so,Android4.4开始加入ART运行时(虚拟机),Android5.0开始ART虚拟机已经完全替代Dalvik虚拟机。

3、alt+T,搜索dvmDexFileOpenPartial函数,并进入该函数

4、在该函数处第一个可下断点之处下断点。静态分析得到该函数的相对地址,在动态调试的IDA中使用ctrl+S找到libdvm.so直接查看基地址,两地址相加得到绝对地址,使用G键跳转,然后下断点

大多教材是将第五步的命令执行和第四步颠倒,实际上可能没有顺序

五、调试拷贝
1、运行IDA,让IDA跑起来,如果弹出窗口,一律点击取消Cancel,以及Apply

2、打开命令窗口,执行:

jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
1
3、此时IDA将停止。R0寄存器出现debug字样(或者是其他字样),则可以开始正常进行脱壳

4、运行程序。包括F7、F8、F9等快捷键。重点关注所下的断点。主要是分析其中的运行判断逻辑,同时运行成功后才能将常规代码载入内存,以便dump内存数据。注意:可能会遇到反调试检测,遇到则按照之前的方法进行绕过

5、IDA --file --script command --编写脚本 --run

6、脚本如下:

auto fp, dex_addr, end_addr;
    fp = fopen("f:\\dump.dex", "wb");
    end_addr = r0 +r1;
    for (dex_addr = r0; dex_addr< end_addr; dex_addr ++)
               fputc(Byte(dex_addr), fp);

7、编写完脚本之后,使用shift+F2调出IDA脚本,运行脚本

8、找到dump.dex,并对其进行smali分析

六、应用还原
1、修改反编译之后的AndroidManifest.xml内容

android:name=”com.shell.superApplication”       //删除该段,大多是后面也是用这个名字
1
如果有自己的Application,就改成自己的Application即可

2、删除多余的APK变种文件。即之前所说的存放在assets、libs等文件夹下的独立多余的文件。

3、使用apktool进行回编译,保留未签名文件

4、将dump.dex该命为classes.dex文件,并使用压缩软件打开未签名文件,替换掉未签名APK下的dex文件

5、签名APK,至此完成还原,脱壳结束。

七、后续步骤
1、分析dump.dex,如果不能使用dex2jar等工具分析Java代码,则分析Smali代码。分析时注意log信息等

2、在手机文本中输入多内容时,可以借助命令:adb shell input text “要输入的内容”
注意:必须要有双引号,必须是英文,测试不识别中文

逆向加固应用的知识总结
APK加固的两种方式:一种是对源APK整体做一个加固,放到指定位置,运行的时候再解密动态加载;还有一种是对so进行加固,在so加载内存的时候进行解密释放。

一个APK加固,外面肯定得套一个壳,这个壳必须是自定义的Application类,它需要做一些初始化操作,一般加固的APK壳的Application类都喜欢叫StubApplication。

步骤如下:

1、查看是否加固

首先解压出classes.dex文件,使用dex2jar工具查看Java代码,发现只有一个Application类,所以猜测APK被加壳了
然后用APKtool来反编译APK,得到它的资源文件和AndroidManifest.xml内容,包括包名和入口的Activity类,记住这些内容

2、寻找加固之后的源APK程序

加固APK一般存放在3个地方:

1、应用的asset目录中。这个目录是不参与APK的资源编译过程的,所以很多加固的应用会把加密之后的源APK放到这里,存放形式可能是jar文件也可能是其他非常规资源文件
2、应用的libs中的so文件中。把源APK进行拆分,存到so文件中,加大分析难度,存放形式是不被应用加载的so文件
3、把源APK加密放到壳的dex文件尾部。这种方式会导致用dex2jar工具解析dex失败
直接打开看即可。有难度时这一步是不会有任何收获的

3、获取到内存中的dex文件(解密后的dex文件)

使用动态调试,给libdvm.so中的函数dvmDexFileOpenPartial下断点,得到dex文件在内存中的起始地址和大小。因为内存中的数据肯定是没有加密的(这似乎也说明了即时加密技术基本上是不存在的),而这个函数是最终分析dex文件,加载到内存中的函数:

int dvmDexFileOpenPartial(const void* addr,int len,DvmDex** ppDvmDex);
1
第一个参数是dex内存的起始地址,第二个参数是dex大小。代码运行到该函数处会解密dex文件到内存,而之后会继续向后运行,内存数据将被覆盖或回收等导致变化,因此在此处下断点会暂停在解密的dex文件的那一刻,使得dex文件在内存中不会变化,所以在该函数处下断点可以dump出内存中的dex文件

知识点:本地盘中的数据是加密的,加载到内存的时候要进行解密,如此机器才能识别数据
--------------------- 
版权声明:本文为CSDN博主「随 亦」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wutianxu123/article/details/82931127

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值