使用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(自行百度)

获取root权限



  2.上传frida服务端到手机

确定Frida版本push文件

#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

上传frida服务端



  3.重命名Frida文件名赋予可执行权限

#这个是给可执行权限,当然给777也行
chmod 755 frida_server


  4.执行frida服务端

改名给权限

#执行Frida服务端,执行后只能看到光标闪烁,正常现象,验证是否成功
./frida_server
#在重新打开一个cmd窗口执行 frida-PS -U 就会列出手机端所有进程列表
frida-PS -U



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

解压出来的目录文件是这个样子的



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

安装apk文件

某梆企业壳

脱壳成功



  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; 
        } 
    }, 
 }); 

在浏览的同时希望给予作者打赏,来支持作者的服务器维护费用.一分也是爱~