0x00 摘要
Apk脱壳方法有两种:
(1)使用脱壳神器ZjDroid进行脱壳(现在此方法不是很好使,因为很多应用都同步更新自己的防御机制,个人觉得熟练脱壳还是得使用 IDA 进行操练)。
(2)使用 IDA Pro 在 dvmDexFileOpenPartial 这个函数下断点进行脱壳。(大杀技)
加壳能防止源代码被偷窥,但是这只能防止静态分析,无法防止动态调试。不管怎么加壳保护,原始的classes.dex在App运行时都要加载到内存中。所以如果在App加载classes.dex处下个断点,然后再把classes.dex对应内存中的内容抠出来还原成原始的classes.dex文件,就能达到脱壳的目的了。
0x01 实验
(1)以第1届Alictf的EvilApk300(如图0所示)为例,简单介绍一下使用IDA Pro 进行脱壳的步骤
- step 1:将手机连接电脑
[Bash shell] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 |
|
如果成功,手机上 app 会弹出 “Waiting For Debugger”
- step 2:操作 IDA
依次点击”Debbuger -> Attach -> Remote ARMLinux/Android debugger”启动IDA Pro中的Android Debbuger
然后在弹出的对话框中点击”Debug options”按钮,将“Suspend on process entry point”,“Suspend on thread start/exit”,“Suspend on library load/unload”这几个选项勾选上,再将Hostname配置为localhost,端口:23946
注意:Ctrl + F 方便查找
- step 3:继续 IDA
脱壳的时候重点关注:dvmDexFileOpenPartial 函数(在该函数处下断点)
依次点击“Debugger -> Debugger windows -> Module list”,找到so文件列表
在Module list中找到libdvm.so这个文件(注意:Ctrl + F 方便查找)
双击libdvm.so,在弹出的函数列表中找到dvmDexFileOpenPartial函数,然后双击该函数就看到dvmDexFileOpenPartial函数的具体实现
在dvmDexFileOpenPartial函数处下断点(F2 下断点)
- step 4:使用jdb命令动态调试Apk
点击 ida 左上角的绿色运行按钮(F9)
打开 DDMS 工具(android-sdk\sdk\tools\ddms.bat)
使用jdb命令进行调试时,一般选择8700端口,因为8700是默认的调试端口;打开终端窗口,输入:
[Bash shell] 纯文本查看 复制代码
1 2 3 |
|
此时 IDA 会弹出 ”Add map…” 窗口(点击 cancel 按钮即可):
此时进程就执行到了dvmDexOpenPartial函数断点处,dvmDexOpenPartial 函数的定义:
[C++] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
dvmDexFileOpenPartial 函数的原型如下所示:
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
其中 addr表示Dex文件在内存中的起始地址,
len 表示Dex文件的大小,
ppDvmDex是一个指向DvmDex类型的二级指针,具体表示什么,我也不知道
脱壳只用到 addr 和 len 这两个参数,所以需要获取 R0 和 R1 寄存器的值(ARM的传递参数机制规定 R0 保存着函数从左至右的第一个参数,R1 保存着函数从左至右的第二个参数),可以查看到寄存器列表中的内容如图所示:
- step 5:在 IDA 中编写idc脚本dump内存还原dex文件
选择 File -> Script command…
稍等片刻,即可以把 dump 出来的 dex 文件保存在 C 盘根目录
IDC脚本:
[C] 纯文本查看 复制代码
1 2 3 4 5 |
|
- step 6:使用 JEB 分析dump 出来的 dex 文件[此处内容请参考原文]
本文脱壳核心思想:在 dvmDexFileOpenPartial 函数处下断点,然后动态调试 Apk,待App 运行到断点处后,写一个 idc 脚本将 dex 文件所对应的内存 dump 出来,然后还原成 dex 文件就完成脱壳操作了,最后再分析反编译 dex 所得到的 smali 文件。 |
- 参考文献
[1] 听鬼哥说ZJDROID脱壳的简单使用:http://blog.csdn.net/guiguzi1110/article/details/38727753
[2] 安卓逆向学习笔记(9)- 使用IDA Pro进行简单的脱壳 :http://blog.csdn.net/pengyan0812/article/details/46275317
[3] Android应用方法隐藏及反调试技术浅析:http://www.kuqin.com/shuoit/20151012/348473.html0x00 摘要
Apk脱壳方法有两种:
(1)使用脱壳神器ZjDroid进行脱壳(现在此方法不是很好使,因为很多应用都同步更新自己的防御机制,个人觉得熟练脱壳还是得使用 IDA 进行操练)。
(2)使用 IDA Pro 在 dvmDexFileOpenPartial 这个函数下断点进行脱壳。(大杀技)
加壳能防止源代码被偷窥,但是这只能防止静态分析,无法防止动态调试。不管怎么加壳保护,原始的classes.dex在App运行时都要加载到内存中。所以如果在App加载classes.dex处下个断点,然后再把classes.dex对应内存中的内容抠出来还原成原始的classes.dex文件,就能达到脱壳的目的了。
0x01 实验
(1)以第1届Alictf的EvilApk300(如图0所示)为例,简单介绍一下使用IDA Pro 进行脱壳的步骤
- step 1:将手机连接电脑
[Bash shell] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 |
|
如果成功,手机上 app 会弹出 “Waiting For Debugger”
- step 2:操作 IDA
依次点击”Debbuger -> Attach -> Remote ARMLinux/Android debugger”启动IDA Pro中的Android Debbuger
然后在弹出的对话框中点击”Debug options”按钮,将“Suspend on process entry point”,“Suspend on thread start/exit”,“Suspend on library load/unload”这几个选项勾选上,再将Hostname配置为localhost,端口:23946
注意:Ctrl + F 方便查找
- step 3:继续 IDA
脱壳的时候重点关注:dvmDexFileOpenPartial 函数(在该函数处下断点)
依次点击“Debugger -> Debugger windows -> Module list”,找到so文件列表
在Module list中找到libdvm.so这个文件(注意:Ctrl + F 方便查找)
双击libdvm.so,在弹出的函数列表中找到dvmDexFileOpenPartial函数,然后双击该函数就看到dvmDexFileOpenPartial函数的具体实现
在dvmDexFileOpenPartial函数处下断点(F2 下断点)
- step 4:使用jdb命令动态调试Apk
点击 ida 左上角的绿色运行按钮(F9)
打开 DDMS 工具(android-sdk\sdk\tools\ddms.bat)
使用jdb命令进行调试时,一般选择8700端口,因为8700是默认的调试端口;打开终端窗口,输入:
[Bash shell] 纯文本查看 复制代码
1 2 3 |
|
此时 IDA 会弹出 ”Add map…” 窗口(点击 cancel 按钮即可):
此时进程就执行到了dvmDexOpenPartial函数断点处,dvmDexOpenPartial 函数的定义:
[C++] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
dvmDexFileOpenPartial 函数的原型如下所示:
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
其中 addr表示Dex文件在内存中的起始地址,
len 表示Dex文件的大小,
ppDvmDex是一个指向DvmDex类型的二级指针,具体表示什么,我也不知道
脱壳只用到 addr 和 len 这两个参数,所以需要获取 R0 和 R1 寄存器的值(ARM的传递参数机制规定 R0 保存着函数从左至右的第一个参数,R1 保存着函数从左至右的第二个参数),可以查看到寄存器列表中的内容如图所示:
- step 5:在 IDA 中编写idc脚本dump内存还原dex文件
选择 File -> Script command…
稍等片刻,即可以把 dump 出来的 dex 文件保存在 C 盘根目录
IDC脚本:
[C] 纯文本查看 复制代码
1 2 3 4 5 |
|
- step 6:使用 JEB 分析dump 出来的 dex 文件[此处内容请参考原文]
本文脱壳核心思想:在 dvmDexFileOpenPartial 函数处下断点,然后动态调试 Apk,待App 运行到断点处后,写一个 idc 脚本将 dex 文件所对应的内存 dump 出来,然后还原成 dex 文件就完成脱壳操作了,最后再分析反编译 dex 所得到的 smali 文件。 |
- 参考文献
[1] 听鬼哥说ZJDROID脱壳的简单使用:http://blog.csdn.net/guiguzi1110/article/details/38727753
[2] 安卓逆向学习笔记(9)- 使用IDA Pro进行简单的脱壳 :http://blog.csdn.net/pengyan0812/article/details/46275317
[3] Android应用方法隐藏及反调试技术浅析:http://www.kuqin.com/shuoit/20151012/348473.html