【胖虎的逆向之路】03——Android一代壳脱壳办法罗列&实操
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
【胖虎的逆向之路】03——Android脱壳办法罗列&脱壳原理详解
【胖虎的逆向之路】01——动态加载和类加载机制详解
【胖虎的逆向之路】02——Android整体加壳原理详解&实现
文章目录
前言
在上文中我们讲解了关于Android整体加壳的原理和实际操作现在我们来针对目前主流的脱壳工具以及流程进行讲解由于作者能力有限会尽力的详细描述 整体壳脱壳 的流程及原理如本文中有任何错误烦请指正感谢~
一、主流脱壳方法
1.工具脱壳法
工具脱壳是指的利用现有的工具进行脱壳很多的大佬已经开发了很多实用的工具我们可以直接搞来使用嘻嘻嘻~
1) Frida-DexDump
得益于Frida, 在电脑上面进行内存搜索、转储的时候都变得十分方便不再去通过繁琐的Xposed代码来获取Dex中对应的类与方法仅需要关注如何去搜索想要的函数即可对于完整的 dex采用暴力搜索 dex035 即可找到。而对于抹头的 dex通过匹配一些特征来找~
- 支持模糊搜索断头dex深度搜索模式。
- 兼容所有安卓版本支持frida。
- 一键安装无需修改系统易于部署和使用
项目地址: https://github.com/hluwa/FRIDA-DEXDump
使用方法也变得简单很多在这里借助一个大佬的使用流程图可以快速进行脱壳
我们简单演示一下这里结合objection一起使用
然后再次打开脱下来的dex即可~
ps:获取到dex后,推荐使用Jadx进行反编译dex2jar有点过时了…
另外附上深度介绍 深入 FRIDA-DEXDump 中的矛与盾
2) Fart
Fart 的制作过程略显繁琐主要是FART的代码是通过修改少量Android源码文件而成的经过修改的Android源码编译成系统镜像刷入手机这样的手机启动后针对Apk可以进行脱壳~
基于此我更愿意称之为是脱壳鸡因为是把经过修改的Android源码编译成了系统镜像刷入了手机~
官方介绍
ART环境下基于主动调用的自动化脱壳方案基于Android 6.0实现理论上可以移植到任何系统上~
项目地址https://github.com/hanbinglengyue/FART
具体的实现原理和步骤在看雪
脱壳流程
1、安装待脱壳apk并到设置中授予sd卡读写权限(否则dump下的文件无法写入到sdcard)
2、点击app图标开始进入fart脱壳过程
接下来可以对logcat中的tag为ActivityThread的log进行过滤等待待脱壳app进程出现"fart run over"此时fart主动调用过程结束。脱壳下来的
dex文件和函数体bin文件均在/sdcard/fart/app包名的目录下~
下面截图为fart的运行流程和脱壳结果
官方Ps添加frida版的fart的两种不同实现各有特色。可以实现具体到对某一个类下的所有函数甚至是对某一个函数的CodeItem的dump。需要的可以去体验下其强大的脱壳能力。(注意测试环境为pixel Android8.0,frida-server 12.8.0)
3) Youpk
Youpk基于ART的主动调用的脱壳机主要针对dex整体加固和各式各样的dex抽取加固但是目前 Youpk 只支持 pixel 1代。所以必须需要 pixel 1代手机而且需要刷入对应的系统~
基本流程如下:
- 从内存中dump DEX
- 构造完整调用链, 主动调用所有方法并dump CodeItem
- 合并 DEX, CodeItem
项目地址https://github.com/youlor/unpacker
在该地址中有较多的流程及方法、注意问题等有需要的可以去看一哈
4) 常用脱壳工具对比
2.Hook脱壳法
我们上面有写到只要函数中包含DexFile对象其实就可以通过Hook拿到该对象然后取到begin和size从而进行脱壳目前使用较多的Hook框架是Xposed和frida两种感觉Frida使用人数较多也方便在这里用frida进行演示~
首先使用GDA识别加壳程序~
看起来很明显是进行了整体加壳有没其他加壳暂时不知道我们先进行脱壳处理
首先找到脱壳点~
通过IDA打开libart.so搜索DexFile我们可以找到海量的脱壳点
然后我们编写hook脚本
这里之所以获取begin加上一个指针是因为我们前面讲了dexfile含有一个虚函数地址所以加上一个指针偏移
然后在手机中启动frida_server
附加进程进行dump这里我们存在sdcard下面所以需要提前赋予读写文件权限
从图中可以看得出来到这里就已经脱壳成功~
然后使用jadx打开对应的dex进行查看
此时说明我们整体脱壳成功不过应用看起来还有抽取壳抽取壳后续会单开一篇文章进行记录~
3.插桩脱壳法
插桩脱壳法就是在Android源码里面定位到相应的脱壳点然后插入相应的代码重新编译源码生成系统镜像最后就可以使用定制的系统进行脱壳~
其原理感觉跟youpk比较像如何编译源码不再进行赘述有需要的小伙伴可以看下这篇文章~
源码编译1——Android6.0源码编译详解
那么还是借助大佬已经完成的图片进行讲解同理、还是定位脱壳点我们还是随便定位一个脱壳点LoadMethod 然后进行插桩
//add
char dexfilepath[100]=0;
memset(dexfilepath,0,100);
sprintf(dexfilepath,"%d_%zu_LoadMethod.dex",getpid(),dex_file.Size());
int dexfd = open(dexfilepathm,O_CREAT|O_RDWR,666);
if(dexfd>0){
int result = write(dexfd,dex_file.Begin(),dex_file.Size());
if(result>0){
close(dexfd);
LOG(WARNING)<<"LoadMethod"<<dexfilepath;
}
}
//add
同理我们在execute同样插桩此段代码最后进行编译编译成功
然后给程序授权sdcard权限再次启动应用就可以看见脱取的dex文件就保存在sdcard目录下
然后在使用jadx打开dex就会得到跟上面一样的结果~
Ps:由于该方法需要进行Android源码修改编译本文作者没有进行实现若有任何问题欢迎随时沟通有问题了我再去编译
4.插桩脱壳法
反射脱壳我自己的理解是利用反射得到一系列的classloader最后得到DexFile结构然后获取变量mCookie&mFileName这两个属性后得到dexFile内存指针然后该指针转换为dexfile再通过findClassDef来匹配寻找的dex最后dump写入文件~
借助前人的总结流程如下
那么还是做一下演示~
mCookie是在native层的dexfile的指针然后我们利用反射原理来获取到mCookie就可以进行脱壳了在这里还是使用frida进行代码演示~
编写hook代码ing
打印出相关值
就可以看到相同大小的dex
然后使用jadx打开发现同样的界面又出现了
5.动态调试脱壳法
动态调试法其核心原理还是要得到DexFile的起始地址和大小不过所有的方式不同 如果说上面是针对代码做修改得到一些值那么接下来就是利用IDA工具获取对应的起始地址和大小然后再通过脚本进行dump~
请欣赏
首先选一个脱壳点我们还是选择DexFile::DexFile
然后手机启动android_servcer记得要以Root启动
然后使用IDA进行附加进程
然后ida开始介入
然后我们打开libart.so并定位到DexFile::DexFile
然后在该函数下断点然后F9过来看一哈
在这里就可以很明显看到X1就是DexFile的起始地址X4是偏移值
然后利用Frida进行dump~
直接运行run即可
然后使用gda查看本地的dump.dex文件
可以发现这里竟然是代理类对比大小不是我们想要的dex再来一遍F9,可以看到地址再次改变再次结合长度来计算试了几次还是没有出来后来就没有在进行了不过感觉是可以得出来的作为演示没有废太多的功夫~
6.特殊API调试法
特殊API调试意思是指的通过Android系统提供的API方法来获取Dex在Android 7.0 及以下系统提供了getDex及getBytes这两个API所以如果我们想要获取对象可以直接调用这两个API~
但是在实际测试中发现在Android 高版本中Dex的getBytes方法依然存在但是核心的Class类中的getDex方法已经消失不见了~
编写hook代码
操作流程
然后我们查看程序的类对象随便dump一个类对象
得到dex之后我们再次使用jadx工具打开~
发现就可以成功的dump~
二、实验总结
本文总结了当下dex整体加壳的常用的一些脱壳方案并进行复现但是在这里仅作为实验加深自己的理解为主目前也不会这么简单的就可以拿到源Dex但是有兴趣的朋友可以像我一样去把整个流程走一遍加深自己的理解~
三、参考文献
https://bbs.kanxue.com/thread-273293.htm#msg_header_h2_6
文中所述图片部分取自该文章栓Q~