使用Frida的一个脚本来dump apk的Dex
一、需求
1.APP 加固发展到现在已经好几代了,从整体加固到代码抽取到虚拟机保护,加固和脱壳的方案也逐渐趋于稳定。随着保护越来越强,脱壳机们也变得越来越费劲,繁琐。
不过对于我来说,很多时候其实并不需要那些被强保护起来的代码,我只是想单纯的看看这个地方的业务逻辑。所以,我追求的是更加快速、简便的脱壳方法 相对于IDA动态调试找入口点来dump文件要简单的多,只需要一行命令即可
二、实现
1.得益于FRIDA, 在 PC 上面进行内存搜索、转储都变得十分方便,再也不需要考虑什么Xposed、什么Android开发、什么代码注入,只需要关注如何去搜索想要的东西,于是依赖一个几十行代码的小脚本,就可以将大部分内存中的 dex 脱下来。在过去的一年,我几乎所有脱壳的工作都是由此脚本来完成,目前已经随手开源:FRIDA-DEXDump, 欢迎star。对于完整的 dex,采用暴力搜索 dex035 即可找到。而对于抹头的 dex,通过匹配一些特征来找到。
三、补充
1.目前基本上我遇到的大部分 tx、bb、ijm、360、baidu 很多都是可以 dump 的,毕竟现代壳的核心功能并不是为了保护整体 DEX。而大多数是防止重打包,所以这些不影响我们分析代码
四、使用
1.(不会安装使用 FRIDA 的,请先自行百度学会..)
默念一声"我想脱个壳"。
启动 APP。
启动 frida-server。
python main.py。
默数三秒,脱好了。
脱好壳的dex在工具目录内生成app包名的目录存放
五、不废话,上图
1.手机需要root(自行百度)
2.上传frida服务端到手机
#adb push frida服务端文件路径 /data/local/tmp
#我执行的命令如下,注意frida的版本以及服务端版本一致 以及64位或32的的文件 我测试机是Nexus 5 32位的
adb push D:\reversetool\框架工具\frida\12.9.4\frida-server-12.9.4-android-arm /data/local/tmp

3.重命名Frida文件名赋予可执行权限#这个是给可执行权限,当然给777也行
chmod 755 frida_server
4.执行frida服务端
#执行Frida服务端,执行后只能看到光标闪烁,正常现象,验证是否成功
./frida_server
#在重新打开一个cmd窗口执行 frida-PS -U 就会列出手机端所有进程列表
frida-PS -U

5.下载DEXDump以下是脚本目录结构 点我下载

6.安装app,开始执行脱壳(目标APP 某日优鲜)某梆的企业壳



7.Frida Hook so导出函数代码,启动方式为:frida -U -f xxxxx.xxxx.xxx -l hook.js --no-pause
let library_loaded = 0;
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function(args) {
// first arg is the path to the library loaded
const library_path = Memory.readCString(args[0]);
const libsgmainso = Module.findBaseAddress('libencrypt.so');
console.log('findBaseAddress: ', libsgmainso);
console.log("[...] Loading library : " + library_path);
if (library_path.includes("libencrypt")) { //so文件名称
console.log("[...] Loading library : " + library_path);
library_loaded = 1;
}
},
onLeave: function(args) {
// if it's the library we want to hook, hooking it
if (library_loaded === 1) {
console.log("[+] Loaded");
var nativePointer = Module.findExportByName("libencrypt.so", "hmac_sha1");
console.log("native: " + nativePointer);
Interceptor.attach(nativePointer, {
onEnter: function(args){
var buffer = Memory.readByteArray(args[0],500);
var hexstr = hexdump(buffer, {
offset: 0,
length: 500,
header: true,
ansi: false
})
console.log(hexstr);
console.log(args[1]);
buffer = Memory.readByteArray(args[2],100);
hexstr = hexdump(buffer, {
offset: 0,
length: 500,
header: true,
ansi: false
})
console.log(hexstr);
console.log(args[3]);
},
onLeave: function(retval){
send(retval.toInt32());
}
});
// hook_jni("libencrypt.so", "hmac_sha1");
library_loaded = 0;
}
},
});
在浏览的同时希望给予作者打赏,来支持作者的服务器维护费用.一分也是爱~