吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 32795|回复: 30
上一主题 下一主题
收起左侧

[Android 脱壳] 使用 IDA 进行简单的脱壳

  [复制链接]
跳转到指定楼层
楼主
加菲猫 发表于 2016-1-6 15:41 回帖奖励
本帖最后由 加菲猫 于 2016-1-6 17:33 编辑

写在前面:

0. 主要针对 http://blog.csdn.net/pengyan0812/article/details/46275317 这篇文章进行二次加工,因此算作“Android 分享”,感谢原作者的分享

1. 在实验过程中,原作个别步骤存在问题,因此按照自己的实验过程重新记录实验步骤

2. 文章以实践为主,很少涉及理论知识

3. 由于图片较多,上传过于混乱,因此你可以下载图文排版异常精美的 PDF 版及其对应的 apk 文件

4. 贴后答疑,如果你在实验的过程中存在问题可以留言(不要咨询我特别高深的问题,因为这篇文章都是我瞎编了,我也不会,哈哈哈)

5. 感谢所有乐于分享的人们

6. 附件内容超过 1M,请前往:http://pan.baidu.com/s/1nuyxc9N 密码:d29f

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] 纯文本查看 复制代码
[/size][size=16px]adb install C:\Users\Bravelee\Desktop\jscrack.apk[/size]

[size=16px]-------启动服务,开启监听-------[/size]
[size=16px]adb shell[/size]
[size=16px]su root[/size]
[size=16px]chmod 777 /data/local/tmp/android_server[/size]
[size=16px]/data/local/tmp/android_server[/size]

[size=16px]------------端口转发------------[/size]
[size=16px]再次打开一个终端窗口:[/size]
[size=16px]adb forward tcp:23946 tcp:23946[/size]

[size=16px]-----------root 模式下启动该 app----------[/size]
[size=16px]因为加壳了,所以只能查看 manifest.xml 文件才能获取 apk 对应的包名[/size]
[size=16px]adb shell[/size]
[size=16px]su root[/size]
[size=16px]am start -D -n com.ali.tg.testapp/com.ali.tg.testapp.MainActivity[/size]
[size=16px]

如果成功,手机上 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] 纯文本查看 复制代码
[/size]
[size=16px]jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700[/size]
[align=left][size=16px]

此时 IDA 会弹出 ”Add map…” 窗口(点击 cancel 按钮即可):

此时进程就执行到了dvmDexOpenPartial函数断点处,dvmDexOpenPartial 函数的定义:
[C++] 纯文本查看 复制代码
[/size]
[size=16px]/*[/size]
[size=16px]* Create a DexFile structure for a "partial" DEX.  This is one that is in[/size]
[size=16px]* the process of being optimized.  The optimization header isn't finished[/size]
[size=16px]* and we won't have any of the auxillary data tables, so we have to do[/size]
[size=16px]* the initialization slightly differently.[/size]
[size=16px]*[/size]
[size=16px]* Returns nonzero on error.[/size]
[size=16px]*/[/size]
[size=16px]int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)[/size]
[size=16px]{[/size]
[size=16px]    DvmDex* pDvmDex;[/size]
[size=16px]    DexFile* pDexFile;[/size]
[size=16px]    int parseFlags = kDexParseDefault;[/size]
[size=16px]    int result = -1;[/size]

[size=16px]    /* -- file is incomplete, new checksum has not yet been calculated[/size]
[size=16px]    if (gDvm.verifyDexChecksum)[/size]
[size=16px]        parseFlags |= kDexParseVerifyChecksum;[/size]
[size=16px]    */[/size]

[size=16px]    pDexFile = dexFileParse((u1*)addr, len, parseFlags);[/size]
[size=16px]    if (pDexFile == NULL) {[/size]
[size=16px]        ALOGE("DEX parse failed");[/size]
[size=16px]        goto bail;[/size]
[size=16px]    }[/size]
[size=16px]    pDvmDex = allocateAuxStructures(pDexFile);[/size]
[size=16px]    if (pDvmDex == NULL) {[/size]
[size=16px]        dexFileFree(pDexFile);[/size]
[size=16px]        goto bail;[/size]
[size=16px]    }[/size]

[size=16px]    pDvmDex->isMappedReadOnly = false;[/size]
[size=16px]    *ppDvmDex = pDvmDex;[/size]
[size=16px]    result = 0;[/size]

[size=16px]bail:[/size]
[size=16px]    return result;[/size]
[size=16px]}[/size]
[size=16px]


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] 纯文本查看 复制代码
auto fp, dex_addr,end_addr;
    fp = fopen("C:\\dump.dex","wb");
    end_addr = r0 + r1;
    for (dex_addr = r0; dex_addr < end_addr; dex_addr ++)
        fputc(Byte(dex_addr),fp);


  • 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





免费评分

参与人数 12吾爱币 +4 热心值 +12 收起 理由
sun20052677 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
redABC + 1 + 1 我很赞同!
迷之裙摆 + 1 + 1 谢谢@Thanks!
8181405c + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
canyang + 1 用心讨论,共获提升!
UNCLE + 1 谢谢@Thanks!
Amanda小黑 + 1 用心讨论,共获提升!
jikefeng + 1 热心回复!
e007 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
yunhsk + 1 热心回复!
myoldid + 1 棒棒的
Ericky + 1 已经处理,感谢您对吾爱破解论坛的支持!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| 加菲猫 发表于 2016-1-11 17:42 |楼主
myoldid 发表于 2016-1-8 13:07
我在输入 jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700 后,报致命错误,无法附加 ...

不好意思,回复略晚,  adb forward tcp:23946 jdwp:5586  --->   adb forward tcp:23946 tcp:23946

欢迎一起交流学习
推荐
mmpo789 发表于 2016-3-14 02:48
加菲猫 发表于 2016-1-11 17:42
不好意思,回复略晚,  adb forward tcp:23946 jdwp:5586  --->   adb forward tcp:23946 tcp:23946

...

我输入 jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700 后,报致命错误,无法附加到目标 VM  不知道你说的这是什么意思:adb forward tcp:23946 jdwp:5586  --->   adb forward tcp:23946 tcp:23946
沙发
 楼主| 加菲猫 发表于 2016-1-6 15:43 |楼主
我去。。。。粘贴过来排版如此混乱。。。。 请大家下载精美的 pdf 版吧,谢谢,另外咨询一下版主,论坛支持 Markdown 排版格式吗?谢谢

点评

抱歉,论坛不支持Markdown 排版,文章还得编辑下,现在图片是盗链无法显示,最好上传到本地。  详情 回复 发表于 2016-1-6 16:30
3#
aikuimail 发表于 2016-1-6 15:54
用代码标记呀楼主,你的图片挂了吧
4#
Ericky 发表于 2016-1-6 16:17
赞一个!
5#
Hmily 发表于 2016-1-6 16:30
加菲猫 发表于 2016-1-6 15:43
我去。。。。粘贴过来排版如此混乱。。。。 请大家下载精美的 pdf 版吧,谢谢,另外咨询一下版主,论坛支持 ...

抱歉,论坛不支持Markdown 排版,文章还得编辑下,现在图片是盗链无法显示,最好上传到本地。
6#
smcree 发表于 2016-1-6 16:33
的确,图片都挂了 ,估计是图片比较多,没上传成功。
7#
 楼主| 加菲猫 发表于 2016-1-6 17:39 |楼主
Hmily 发表于 2016-1-6 16:30
抱歉,论坛不支持Markdown 排版,文章还得编辑下,现在图片是盗链无法显示,最好上传到本地。

终于排版好了

点评

太辛苦了,还有2个图片没有上传,还是在那转转的。  详情 回复 发表于 2016-1-6 18:23
8#
Hmily 发表于 2016-1-6 18:23

太辛苦了,还有2个图片没有上传,还是在那转转的。
9#
yyj85391 发表于 2016-1-6 21:24 来自手机
好教程啊,堪称手把手叫
10#
myoldid 发表于 2016-1-7 08:48
难得一见的详细教程,中午试试。多谢楼主分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-7 13:21

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表