首页
社区
课程
招聘
[原创]某加固新版frida检测绕过-trace一把嗦
发表于: 16小时前 1608

[原创]某加固新版frida检测绕过-trace一把嗦

16小时前
1608

学习frida检测原理后, 向朋友寻找样本练手, 正好是某*加固企业版

根据网上资料成功绕过大部分样本的检测, 但某icbc是新版加固, 原方案不起作用

最终通过trace成功定位检测点并绕过, 写下此篇分享思路

注意: 由于复现时疏忽, 在Pixel6a上绕过旧版加固时使用了florida, 原版frida hook clone时进程仍然会被杀而非打印线程函数, 在Pixel3XL上绕过新版加固全程使用原版frida, 可参考新版定位和绕过思路 (我的锅)

工具:

设备环境:

文中样本均下载自应用商店,日期为12.8-12.10

声明:

关键SO: libDexHelper.so

样本: com.jxbank.mbank

搜集包名,加固方案,lib库等信息

hook dlopen 定位检测so, 低版本使用"dlopen", 高版本"android_dlopen_ext"

如果加载该so时, 在init, init_array, JNI_OnLoad等位置检测, 则加载该so后会立马杀掉进程

但在加载libDexHelper.so后一段时间才退出进程, 说明该so中创建了子线程进行检测

6-dlopen-load-so

linux中最常用的线程创建函数是pthread_create, 定义如下

在hook dlopen中添加代码, 当加载libDexHelper.so时hook pthread_create减少多余输出(libart也会创建很多线程)

hook_pthread_create函数中打印创建的线程函数所在so以及偏移地址

结果如下, 没有成功打印

7-hook-pthread-create

所以可能并没有走pthread_create创建线程,而是更底层的系统调用clone

hook clone, 打印线程函数所在模块和偏移

注意: 不能同时hook pthread_thread, 否则崩溃, 推测是因为libDexHelper检测了有没有hook libc的pthread_thread

结果如下, 输出的线程函数都在libc.so+0xc9c00中
注意: 由于复现时疏忽, 在Pixel6a上绕过旧版加固使用了florida, 原版frida hook clone时进程仍然会被杀而非打印线程函数
在Pixel3XL上绕过新版加固全程使用原版frida, 可参考新版定位和绕过思路
19-hook-clone-libc

拉取libc.so扔进ida分析该地址

0xc9c00对应函数是"__pthread_start", 交叉引用发现在libc的"pthread_create"函数中通过clone封装了该函数

pthread_create本质上通过clone创建子线程, 子线程函数地址作为clone的参数传递

可以发现pthread_create的参数3线程函数地址传给此处v30+96, 封装后作为clone的参数4

所以, 修改hook_clone, 通过参数4+96即可拿到真正的子线程函数地址

参考文章【APP 逆向百例】某当劳 Frida 检测 中的解释

可以发现成功输出libDexHelper.so中创建了哪些线程检测函数

8-hook-clone

一个简单的思路是直接nop检测函数

成功绕过检测进入app

9-nop-detect-thread

至此某*加固旧版的frida检测成功绕过, 但检测函数到底做了什么? 有待进一步分析

想分析检测函数中具体做了什么需要分析libDexHelper.so, 直接提取apk中的so可以发现是加密状态

start没有指令全是数据, init_proc则是有elf相关结构, 可能是自定义linker

11-init-start

在dlopen刚加载该so后进行dump, 此时从文件加载到内存中, 应是解密状态

dump成功, 进入手机端的shell复制到"/sdcard/Download"下方便pull

10-dump-so

adb pull到电脑端后使用SoFixer修复

12-FixSO

修复后可以正常分析so, 这里贴上2个检测函数

14-detect-thread-5d8cc-status-maps13-detect-thread-func

经过以上分析, 可以总结出通杀脚本如下

首次执行时注释bypass_detect_func, 打印libDexHelper.so创建的线程函数地址

之后修改bypass_detect_func中nopFunc的偏移地址, 再次执行即可绕过

除此之外, 其他bank样本也可以使用相同方法绕过检测

大部分bank是某*企业版, 招商是网易易盾, 兴业是爱加密

BOC

14-BOC

ABC

15-ABC

CCB

16-CCB

四大行中ICBC比较特殊, 是新版某*加固, 且无法使用旧版的思路定位检测点

假设hook clone, 绕过了线程检测函数, 此时再hook pthread_create进程仍会结束

不难猜测是libDexHelper.so中检测了libc.so的pthread_create是否被hook

整理文章时发现此问题, 但由于新版加固中已经绕过该检测, 故不再深究旧版

继续使用上述通杀脚本, 分别hook pthread_create和clone, 均没有打印出线程函数, 进程直接被杀

hook pthread_create

hook clone

23-bangbang-new-hook-clone

进程被杀, 没有其他信息, 但可以尝试trace进程崩溃前的函数执行流从而定位检测点

oacia师傅的 stalker_trace_so 插件可以实现该功能, 使用插件前需要dump so, 同上操作类似不多赘述

将stalker_trace_so.py复制到ida的plugins目录下即可使用

使用方式为Edit > Plugins > stalker trace so, 自动生成trace脚本, spawn模式运行即可

脚本需要修改so_name为app运行时so的真实名称 (默认为ida打开的文件名)

hook_dlopen 当加载目标so时, 执行trace

spawn模式执行脚本

trace结果如下

不难看出在JNI_OnLoad中执行了一系列操作以及检测, 调用 "_ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl512validAddressEPvS1" 后进程被杀

直接搜索validaddress, 向上交叉引用发现JNI_OnLoad中调用了

"p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl5::p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl5::p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISISSISlS5Sl5IS0SI5S5S5SI5lSl5"

很明显的检查操作并根据返回值决定是否杀掉进程, 没有调用exit, kill等函数, 而是jump 非法内存

观察if条件, 当该函数返回0时, if条件必定不满足, 那么hook replace该函数, 强制返回值为0便可以绕过

成功绕过该检测, 但仍有其他检测

绕过该检测后继续尝试hook pthread_create 和 clone

结果如下, hook pthread_create和旧版类似, 仍然会被杀(检测libc.so的pthread_create是否被hook)

但hook clone成功输出创建的检测线程 (此处可能出现6或7个, 似乎有2个并不是检测frida)

基于此, 同旧版类似, 尝试直接nop线程检测函数

绕过线程检测函数后成功进入app

至此可以得出结论: 新版相对旧版额外添加了检测函数0x36390, 绕过后和旧版思路基本相同

新旧版都检测了libc.so的pthread_create, 到底在哪里检测? 这是接下来的重点内容

在stalker_trace_so脚本中绕过检测并trace

可以发现最后崩溃时调用了几个函数,逐一查看后发现sub_54B20函数疑似检测libc和libart

交叉引用可以发现该函数有多处调用, 并且传入了libart.so

libc.so有1处调用, 并且根据结果判断是否要jump 非法内存退出

33-bangbang-new-func-54b20-libc

绕过思路同上类似, replace该函数, 强制返回0, 打印函数参数观察检测了哪些东西

同时hook pthread_create观察进程是否会被杀

可以发现成功绕过了检测libc.so

那么libart.so在哪里检测的呢? 只需要注释 bypass_detect_func (nop线程检测函数) 即可

完整日志如下, libart主要检测用于注册/注销native方法的函数, 以及修复静态类的跳板函数

关于绕过某*加固的新版和旧版frida检测的绕过至此结束, 以上分析比较基础, 没有深入检测原理, 以及深究是否存在其他检测

整理时发现不够细心没考虑到不同情况导致走了很多弯路, 下面介绍trace指令流定位而非函数调用链定位

以下内容基于最初认为: 新版加固没有创建线程检测函数 (不走pthread_create以及clone,可能有其他创建线程的骚操作), 而是在JNI_OnLoad进行所有检测, 仅通过stalker_trace_so无法成功定位, 必须使用更强大的trace工具, 从trace函数调用链向指令流进发

那么,回到最开始的地方: hook pthread_create , 并通过trace JNI_OnLoad的指令流定位检测点

工具使用追佬的 vm-trace , 详情可参考文章[原创]基于VM的全新Trace框架发布!功能强大,一分钟1.5g,提高你的逆向体验~

使用前需要准备环境:

Android 14以下的测试机

推送test.so到app私有目录 "/data/data/<package_name>/"

由于我的Pixel 3XL Android10关闭selinux后有bug, 不能spawn启动app

所以不将test.so推送到/data/local/tmp, 而是app私有目录

虽然提取log更麻烦但不需要额外权限

脚本如下:

hook_soload 和 prepareArgs 是原脚本自带的函数

hook_soload主动加载了test.so到app中, 加载目标so后执行hook和trace函数

hook_JNI_OnLoad 是hook函数模版, 用于hook指定地址的函数, 可自定义

设置好函数偏移地址即可, 注意函数参数个数和类型不能弄错

调用了test.so的vmtrace进行trace

test.so和log均使用app私有目录

spawn模式启动

这里有个小技巧:

我们的主要目的是定位崩溃点和检测函数, 而非根据trace还原算法

log.txt可能几千万行代码, 4-5GB, 提取到pc再分析太慢, 使用tail命令打印最后几行trace即可

tail命令默认打印10行, 可通过-n参数指定行数

不难发现在0x382c4处跳转到非法内存0x12dc导致app进程被杀

跟进so发现关键检测函数, 根据上述内容, 直接hook replace该函数并强制返回0即可绕过

绕过函数

trace结果, 成功绕过

新的崩溃点在0x3a5d8

40-bangbang-new-vmtrace-result2

跟进后发现调用sub_54B20后根据返回值判断是否jump非法内存

而54b20前文提到过, 用于检测libc.so和libart.so的关键函数是否被hook

同上, replace该函数, 强制返回0

绕过该检测后trace发现hook pthread_create成功, 打印出检测线程函数

同上nop这些检测函数即可

绕过检测函数后成功进入app

另外虽然此处崩溃, 但trace结果反复循环一段代码, 即单字节读取maps的内容

43-bangbang-new-vmtrace-result3

跟进发现代码属于sub_5d368函数, 扫描maps

值得一提的是之前使用stalker_trace_so没有发现该函数, 不hook该函数也能正常绕过检测

测试发现如果trace JNI_OnLoad, 无论是否hook该函数都会崩溃, 推测有其他检测, 或者trace对环境有影响

不hook 5D368时

hook 5D368时

trace结果如下 (两次trace报错结果一致)

48-bangbang-new-vmtrace-result4

列举分析过程中遇到的检测函数和疑似的检测函数

函数内部有多处疑似inline hook检测的特征

46-inline-hook-detect

交叉引用该函数发现疑似hook 了自身的read, open, openat等函数

所以该函数大概率是hook自身的read/open系列函数, 使用自定义的函数, 防止被逆向人员hook

在尝试hook ae1f4后会导致崩溃, 即执行到frida的hook跳转代码后被识别为非法内存

0x42098函数伪代码如下, 打开maps后单字节读取指定so的部分内存属性, 但没有杀进程

检测root, frida, xposed, hook等特征

使用原版SoFixer会出现导入表符号不匹配问题
如图所示左边是正确符号,右边是错误符号, 非常影响分析

修复方案参考 [原创] SoFixer导入表问题修复及ELF解析简记 但修复版 SoFixer 没有Release包
感谢小风提供编译好的修复版 SoFixer

【APP 逆向百例】某当劳 Frida 检测

从inlinehook角度检测frida

[原创]《安卓逆向这档事》第十九课、表哥,你也不想你的Frida被检测吧!(下)

[原创]基于VM的全新Trace框架发布!功能强大,一分钟1.5g,提高你的逆向体验~

function hook_dlopen() {
    const funcName = "android_dlopen_ext";                  // old version is "dlopen",
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);  // 查找导出函数 (null 代表搜索所有模块)
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
        // hook dlopen
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        // 读取加载的so名称字符串并打印
                        var path = this.pathPtr.readCString(); 
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main(){
    hook_dlopen();
}
setImmediate(main);
function hook_dlopen() {
    const funcName = "android_dlopen_ext";                  // old version is "dlopen",
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);  // 查找导出函数 (null 代表搜索所有模块)
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
        // hook dlopen
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        // 读取加载的so名称字符串并打印
                        var path = this.pathPtr.readCString(); 
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main(){
    hook_dlopen();
}
setImmediate(main);
#include <pthread.h>
int pthread_create(pthread_t *thread,               //  保存新创建线程的线程标识符tid
                   const pthread_attr_t *attr,      //  线程属性对象的指针
                   void *(*start_routine)(void *),  //  线程入口函数地址
                   void *arg);                      //  线程函数的参数
#include <pthread.h>
int pthread_create(pthread_t *thread,               //  保存新创建线程的线程标识符tid
                   const pthread_attr_t *attr,      //  线程属性对象的指针
                   void *(*start_routine)(void *),  //  线程入口函数地址
                   void *arg);                      //  线程函数的参数
function hook_pthread_create() {
    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthread_create addr: ", pthread_create_addr);
    Interceptor.attach(pthread_create_addr, {
        onEnter: function (args) {
            var thread_func_addr = args[2];
            var module = Process.findModuleByAddress(thread_func_addr);
            console.log(`pthread_create thread func: ${module.name}+0x${(thread_func_addr - module.base).toString(16)}`);
        }, onLeave: function (retval) {
        }
    });
}
 
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    hook_pthread_create();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main(){
    hook_dlopen();
}
setImmediate(main);
function hook_pthread_create() {
    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthread_create addr: ", pthread_create_addr);
    Interceptor.attach(pthread_create_addr, {
        onEnter: function (args) {
            var thread_func_addr = args[2];
            var module = Process.findModuleByAddress(thread_func_addr);
            console.log(`pthread_create thread func: ${module.name}+0x${(thread_func_addr - module.base).toString(16)}`);
        }, onLeave: function (retval) {
        }
    });
}
 
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    hook_pthread_create();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main(){
    hook_dlopen();
}
setImmediate(main);
#define _GNU_SOURCE
#include <sched.h>
// clone参数: 函数地址, 栈, 共享资源flag, 函数参数
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...);
#define _GNU_SOURCE
#include <sched.h>
// clone参数: 函数地址, 栈, 共享资源flag, 函数参数
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...);
function hook_clone() {
    // int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
    var clone_addr = Module.findExportByName("libc.so", "clone");
    if (clone_addr) {
        Interceptor.attach(clone_addr, {
            onEnter: function (args) {
                var addr = args[0];
                if (!addr.isNull()) {
                    var mod = Process.findModuleByAddress(addr);    // 获取地址所在的模块
 
                    if (mod) {
                        var offset = addr.sub(mod.base);    // 计算偏移
                        console.log(`[+]${mod.name}!${offset}`);
                    } else {
                        console.log(`[+] Unknown Module (Anonymous Memory), Addr: ${addr}`);
                    }
                }
            }
        });
    } else {
        console.log("[-] clone export not found in libc.so");
    }
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create();    // 注意: 不能同时hook pthread_thread, 否则崩溃
                    hook_clone();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
function hook_clone() {
    // int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
    var clone_addr = Module.findExportByName("libc.so", "clone");
    if (clone_addr) {
        Interceptor.attach(clone_addr, {
            onEnter: function (args) {
                var addr = args[0];
                if (!addr.isNull()) {
                    var mod = Process.findModuleByAddress(addr);    // 获取地址所在的模块
 
                    if (mod) {
                        var offset = addr.sub(mod.base);    // 计算偏移
                        console.log(`[+]${mod.name}!${offset}`);
                    } else {
                        console.log(`[+] Unknown Module (Anonymous Memory), Addr: ${addr}`);
                    }
                }
            }
        });
    } else {
        console.log("[-] clone export not found in libc.so");
    }
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create();    // 注意: 不能同时hook pthread_thread, 否则崩溃
                    hook_clone();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
adb pull /system/lib64/libc.so ./libc64.so
adb pull /system/lib64/libc.so ./libc64.so
function hook_clone() {
    var clone = Module.findExportByName('libc.so', 'clone');
    Interceptor.attach(clone, {
        onEnter: function (args) {
            //只有当 args[3] 不为 NULL 时,才说明上层确实把 “线程控制块指针” 传进来了
            if (args[3] != 0) {
                var thread_func_addr = args[3].add(96).readPointer()        // 真正的用户线程函数地址
                var module = Process.findModuleByAddress(thread_func_addr); // 根据线程函数地址 addr,找它属于哪个模块
                var offset = (thread_func_addr - module.base);              // 获取相对于 base 的偏移
                console.log(`[+]libc.so clone thread func: ${module.name}+0x${offset.toString(16)}`);
            }
        }
    });
}
function hook_clone() {
    var clone = Module.findExportByName('libc.so', 'clone');
    Interceptor.attach(clone, {
        onEnter: function (args) {
            //只有当 args[3] 不为 NULL 时,才说明上层确实把 “线程控制块指针” 传进来了
            if (args[3] != 0) {
                var thread_func_addr = args[3].add(96).readPointer()        // 真正的用户线程函数地址
                var module = Process.findModuleByAddress(thread_func_addr); // 根据线程函数地址 addr,找它属于哪个模块
                var offset = (thread_func_addr - module.base);              // 获取相对于 base 的偏移
                console.log(`[+]libc.so clone thread func: ${module.name}+0x${offset.toString(16)}`);
            }
        }
    });
}
function nopFunc(addr) {
    Memory.protect(addr, 4, 'rwx');  // 修改该地址的权限为可读可写
    var writer = new Arm64Writer(addr);
    writer.putRet();   // 直接将函数首条指令设置为ret指令
    writer.flush();    // 写入操作刷新到目标内存,使得写入的指令生效
    writer.dispose();  // 释放 Arm64Writer 使用的资源
    console.log("nop " + addr + " success");
}
function bypass_detect_func() {
    var base = Module.findBaseAddress("libDexHelper.so")
    // jxbank
    nopFunc(base.add(0x561d0));
    nopFunc(base.add(0x52cc0));
    nopFunc(base.add(0x5ded4));
    nopFunc(base.add(0x5e410));
    nopFunc(base.add(0x5fb48));
    nopFunc(base.add(0x592c8));
    nopFunc(base.add(0x69470));
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create();
                    //hook_clone();
                    bypass_detect_func();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
function nopFunc(addr) {
    Memory.protect(addr, 4, 'rwx');  // 修改该地址的权限为可读可写
    var writer = new Arm64Writer(addr);
    writer.putRet();   // 直接将函数首条指令设置为ret指令
    writer.flush();    // 写入操作刷新到目标内存,使得写入的指令生效
    writer.dispose();  // 释放 Arm64Writer 使用的资源
    console.log("nop " + addr + " success");
}
function bypass_detect_func() {
    var base = Module.findBaseAddress("libDexHelper.so")
    // jxbank
    nopFunc(base.add(0x561d0));
    nopFunc(base.add(0x52cc0));
    nopFunc(base.add(0x5ded4));
    nopFunc(base.add(0x5e410));
    nopFunc(base.add(0x5fb48));
    nopFunc(base.add(0x592c8));
    nopFunc(base.add(0x69470));
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create();
                    //hook_clone();
                    bypass_detect_func();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
function dump_so(so_name, package_name) {
    var libso = Process.getModuleByName(so_name);
    console.log("[name]:", libso.name);
    console.log("[base]:", libso.base);
    console.log("[size]:", ptr(libso.size));
    console.log("[path]:", libso.path);
    //包名需要设置
    var file_path = "/data/data/" + package_name + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
    var file_handle = new File(file_path, "wb");
    if (file_handle && file_handle != null) {
        Memory.protect(ptr(libso.base), libso.size, 'rwx');
        var libso_buffer = ptr(libso.base).readByteArray(libso.size);
        file_handle.write(libso_buffer);
        file_handle.flush();
        file_handle.close();
        console.log("[dump]:", file_path);
    }
}
 
function hook_dlopen_dump_so(soName, package_name) {
    // hook android_dlopen_ext,该函数是Android系统加载so的函数
    // 当使用该函数加载指定so时,设置is_can_hook为true,表示可以hook,之后执行dump_so
    // 也就是加载so后马上dump,可以防止被反调试
    var once_flag = true;
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook && once_flag) {
                    dump_so(soName, package_name);
                    once_flag = false;
                }
            }
        }
    );
}
function main(){
    hook_dlopen_dump_so("libDexHelper.so","com.icbc");
}
setImmediate(main);
function dump_so(so_name, package_name) {
    var libso = Process.getModuleByName(so_name);
    console.log("[name]:", libso.name);
    console.log("[base]:", libso.base);
    console.log("[size]:", ptr(libso.size));
    console.log("[path]:", libso.path);
    //包名需要设置
    var file_path = "/data/data/" + package_name + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
    var file_handle = new File(file_path, "wb");
    if (file_handle && file_handle != null) {
        Memory.protect(ptr(libso.base), libso.size, 'rwx');
        var libso_buffer = ptr(libso.base).readByteArray(libso.size);
        file_handle.write(libso_buffer);
        file_handle.flush();
        file_handle.close();
        console.log("[dump]:", file_path);
    }
}
 
function hook_dlopen_dump_so(soName, package_name) {
    // hook android_dlopen_ext,该函数是Android系统加载so的函数
    // 当使用该函数加载指定so时,设置is_can_hook为true,表示可以hook,之后执行dump_so
    // 也就是加载so后马上dump,可以防止被反调试
    var once_flag = true;
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook && once_flag) {
                    dump_so(soName, package_name);
                    once_flag = false;
                }
            }
        }
    );
}
function main(){
    hook_dlopen_dump_so("libDexHelper.so","com.icbc");
}
setImmediate(main);
function hook_pthread_create() {
    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthread_create addr: ", pthread_create_addr);
    Interceptor.attach(pthread_create_addr, {
        onEnter: function (args) {
            var thread_func_addr = args[2];
            var module = Process.findModuleByAddress(thread_func_addr);
            console.log(`pthread_create thread func: ${module.name}+0x${(thread_func_addr - module.base).toString(16)}`);
        }, onLeave: function (retval) {
        }
    });
}
 
function hook_clone() {
    var clone = Module.findExportByName('libc.so', 'clone');
    Interceptor.attach(clone, {
        onEnter: function (args) {
            //只有当 args[3] 不为 NULL 时,才说明上层确实把 “线程控制块指针” 传进来了
            if (args[3] != 0) {
                var thread_func_addr = args[3].add(96).readPointer()        // 真正的用户线程函数地址
                var module = Process.findModuleByAddress(thread_func_addr); // 根据线程函数地址 addr,找它属于哪个模块
                var offset = (thread_func_addr - module.base);              // 获取相对于 base 的偏移
                console.log(`[+]libc.so clone thread func: ${module.name}+0x${offset.toString(16)}`);
            }
        }
    });
}
 
function nopFunc(addr) {
    Memory.protect(addr, 4, 'rwx');  // 修改该地址的权限为可读可写
    var writer = new Arm64Writer(addr);
    writer.putRet();   // 直接将函数首条指令设置为ret指令
    writer.flush();    // 写入操作刷新到目标内存,使得写入的指令生效
    writer.dispose();  // 释放 Arm64Writer 使用的资源
    console.log("nop " + addr + " success");
}
 
function bypass_detect_func() {
    var base = Module.findBaseAddress("libDexHelper.so")
    // jxbank
    nopFunc(base.add(0x561d0));
    nopFunc(base.add(0x52cc0));
    nopFunc(base.add(0x5ded4));
    nopFunc(base.add(0x5e410));
    nopFunc(base.add(0x5fb48));
    nopFunc(base.add(0x592c8));
    nopFunc(base.add(0x69470));
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create(); // 如果hook会由于检测libc.so而崩溃
                    hook_clone();            // hook clone打印检测线程正常运行
                    bypass_detect_func();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
function hook_pthread_create() {
    var pthread_create_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthread_create addr: ", pthread_create_addr);
    Interceptor.attach(pthread_create_addr, {
        onEnter: function (args) {
            var thread_func_addr = args[2];
            var module = Process.findModuleByAddress(thread_func_addr);
            console.log(`pthread_create thread func: ${module.name}+0x${(thread_func_addr - module.base).toString(16)}`);
        }, onLeave: function (retval) {
        }
    });
}
 
function hook_clone() {
    var clone = Module.findExportByName('libc.so', 'clone');
    Interceptor.attach(clone, {
        onEnter: function (args) {
            //只有当 args[3] 不为 NULL 时,才说明上层确实把 “线程控制块指针” 传进来了
            if (args[3] != 0) {
                var thread_func_addr = args[3].add(96).readPointer()        // 真正的用户线程函数地址
                var module = Process.findModuleByAddress(thread_func_addr); // 根据线程函数地址 addr,找它属于哪个模块
                var offset = (thread_func_addr - module.base);              // 获取相对于 base 的偏移
                console.log(`[+]libc.so clone thread func: ${module.name}+0x${offset.toString(16)}`);
            }
        }
    });
}
 
function nopFunc(addr) {
    Memory.protect(addr, 4, 'rwx');  // 修改该地址的权限为可读可写
    var writer = new Arm64Writer(addr);
    writer.putRet();   // 直接将函数首条指令设置为ret指令
    writer.flush();    // 写入操作刷新到目标内存,使得写入的指令生效
    writer.dispose();  // 释放 Arm64Writer 使用的资源
    console.log("nop " + addr + " success");
}
 
function bypass_detect_func() {
    var base = Module.findBaseAddress("libDexHelper.so")
    // jxbank
    nopFunc(base.add(0x561d0));
    nopFunc(base.add(0x52cc0));
    nopFunc(base.add(0x5ded4));
    nopFunc(base.add(0x5e410));
    nopFunc(base.add(0x5fb48));
    nopFunc(base.add(0x592c8));
    nopFunc(base.add(0x69470));
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    //hook_pthread_create(); // 如果hook会由于检测libc.so而崩溃
                    hook_clone();            // hook clone打印检测线程正常运行
                    bypass_detect_func();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
frida -Uf com.icbc -l trace_libDexHelper_fixed_icbc_kwajw.js
frida -Uf com.icbc -l trace_libDexHelper_fixed_icbc_kwajw.js
[Pixel 3 XL::com.icbc ]-> start Stalker!
Stalker end!
call1:JNI_OnLoad
call2:readlink
call3:j_p5SS$Sl5S5IS55I5_5ISI5I5SS5SIS0SlSISlS5S55_SOSI5lS0SlSIS_SOS05$S0
call4:p5SS$Sl5S5IS55I5_5ISI5I5SS5SIS0SlSISlS5S55_SOSI5lS0SlSIS_SOS05$S0 
call5:j_pSO5_5SSI5$S$SI5I5l5ISlSOS05l5ISISISIS0SISISI5$5_S$SISIS5S05S5$SI
call6:pSO5_5SSI5$S$SI5I5l5ISlSOS05l5ISISISIS0SISISI5$5_S$SISIS5S05S5$SI 
call7:j_pS_5$SlSO5SS$SI5ISlSISOSl5SSIS0Sl5I5S5I5S5IS$S_SISI5I5ISl5I5_S$S5
call8:pS_5$SlSO5SS$SI5ISlSISOSl5SSIS0Sl5I5S5I5S5IS$S_SISI5I5ISl5I5_S$S5
call9:sub_41FE0
call10:setsockopt
call11:j_pS$SlS_S_S$5ISI5_5S5ISlSI5_SlS55lSIS0SI5IS$SIS0SOS05_5IS_Sl5_SI5I
call12:pS$SlS_S_S$5ISI5_5S5ISlSI5_SlS55lSIS0SI5IS$SIS0SOS05_5IS_Sl5_SI5I
call13:j_pSl5I5$S5Sl5lSOSISOSIS0Sl5$5lSlS05lSlSI5_SISlS5SlSOSl5S5I5ISlSIS0
call14:pSl5I5$S5Sl5lSOSISOSIS0Sl5$5lSlS05lSlSI5_SISlS5SlSOSl5S5I5ISlSIS0
call15:getppid
call16:j_p5lS05ISISOSl5lS$SIS$5S5I5ISIS$S_5lSIS05S5I5SS_5I5lSO5_SOSI5_S05I
call17:p5lS05ISISOSl5lS$SIS$5S5I5ISIS$S_5lSIS05S5I5SS_5I5lSO5_SOSI5_S05I
call18:sub_32B78
call19:sched_yield
call20:socket
call21:fscanf
call22:atoi
call23:strrchr
call24:__strlen_chk
call25:__strncpy_chk2
call26:__vsprintf_chk
call27:connect
call28:fread
call29:regfree
call30:readdir
call31:__strncpy_chk
call32:wcstoul
call33:__errno
call34:sub_42098
call35:fputc
call36:dl_iterate_phdr
call37:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl5C2ENSt6__ndk117basic_string_viewIcNS1_11char_traitsIcEEEE
call38:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl5C2ENSt6__ndk117basic_string_viewIcNS1_11char_traitsIcEEEE
call39:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl562p5lS_SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SIlS5_Ev    
call40:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl562p5lS_SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SIlS5_Ev      
call41:fileno
call42:__sF
call43:sub_309C0
call44:sub_72CA8
call45:sub_308E0
call46:sub_45D38
call47:sub_2F8A0
call48:sub_B3B40
call49:sub_30270
call50:sub_B85DC
call51:sub_30E50
call52:sub_33590
call53:sub_335FC
call54:sub_3360C
call55:strtoll
call56:j_j_strtol
call57:j_strtol
call58:strtol
call59:sub_31500
call60:sub_35E24
call61:memcmp
call62:strtoul
call63:pthread_mutex_lock
call64:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl55parseEP9elf64_hdr
call65:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl55parseEP9elf64_hdr
call66:__strchr_chk
call67:j__ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISISSISlS5Sl5IS0SI5S5S5SI5lSl5Ev  
call68:_ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISISSISlS5Sl5IS0SI5S5S5SI5lSl5Ev    
call69:fdopen
call70:j__ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl512validAddressEPvS1_
call71:_ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl512validAddressEPvS1_
call72:__open_2
call73:mprotect
Process terminated
[Pixel 3 XL::com.icbc ]->
 
Thank you for using Frida!
[Pixel 3 XL::com.icbc ]-> start Stalker!
Stalker end!
call1:JNI_OnLoad
call2:readlink
call3:j_p5SS$Sl5S5IS55I5_5ISI5I5SS5SIS0SlSISlS5S55_SOSI5lS0SlSIS_SOS05$S0
call4:p5SS$Sl5S5IS55I5_5ISI5I5SS5SIS0SlSISlS5S55_SOSI5lS0SlSIS_SOS05$S0 
call5:j_pSO5_5SSI5$S$SI5I5l5ISlSOS05l5ISISISIS0SISISI5$5_S$SISIS5S05S5$SI
call6:pSO5_5SSI5$S$SI5I5l5ISlSOS05l5ISISISIS0SISISI5$5_S$SISIS5S05S5$SI 
call7:j_pS_5$SlSO5SS$SI5ISlSISOSl5SSIS0Sl5I5S5I5S5IS$S_SISI5I5ISl5I5_S$S5
call8:pS_5$SlSO5SS$SI5ISlSISOSl5SSIS0Sl5I5S5I5S5IS$S_SISI5I5ISl5I5_S$S5
call9:sub_41FE0
call10:setsockopt
call11:j_pS$SlS_S_S$5ISI5_5S5ISlSI5_SlS55lSIS0SI5IS$SIS0SOS05_5IS_Sl5_SI5I
call12:pS$SlS_S_S$5ISI5_5S5ISlSI5_SlS55lSIS0SI5IS$SIS0SOS05_5IS_Sl5_SI5I
call13:j_pSl5I5$S5Sl5lSOSISOSIS0Sl5$5lSlS05lSlSI5_SISlS5SlSOSl5S5I5ISlSIS0
call14:pSl5I5$S5Sl5lSOSISOSIS0Sl5$5lSlS05lSlSI5_SISlS5SlSOSl5S5I5ISlSIS0
call15:getppid
call16:j_p5lS05ISISOSl5lS$SIS$5S5I5ISIS$S_5lSIS05S5I5SS_5I5lSO5_SOSI5_S05I
call17:p5lS05ISISOSl5lS$SIS$5S5I5ISIS$S_5lSIS05S5I5SS_5I5lSO5_SOSI5_S05I
call18:sub_32B78
call19:sched_yield
call20:socket
call21:fscanf
call22:atoi
call23:strrchr
call24:__strlen_chk
call25:__strncpy_chk2
call26:__vsprintf_chk
call27:connect
call28:fread
call29:regfree
call30:readdir
call31:__strncpy_chk
call32:wcstoul
call33:__errno
call34:sub_42098
call35:fputc
call36:dl_iterate_phdr
call37:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl5C2ENSt6__ndk117basic_string_viewIcNS1_11char_traitsIcEEEE
call38:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl5C2ENSt6__ndk117basic_string_viewIcNS1_11char_traitsIcEEEE
call39:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl562p5lS_SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SIlS5_Ev    
call40:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl562p5lS_SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SIlS5_Ev      
call41:fileno
call42:__sF
call43:sub_309C0
call44:sub_72CA8
call45:sub_308E0
call46:sub_45D38
call47:sub_2F8A0
call48:sub_B3B40
call49:sub_30270
call50:sub_B85DC
call51:sub_30E50
call52:sub_33590
call53:sub_335FC
call54:sub_3360C
call55:strtoll
call56:j_j_strtol
call57:j_strtol
call58:strtol
call59:sub_31500
call60:sub_35E24
call61:memcmp
call62:strtoul
call63:pthread_mutex_lock
call64:j__ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl55parseEP9elf64_hdr
call65:_ZN63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl55parseEP9elf64_hdr
call66:__strchr_chk
call67:j__ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISISSISlS5Sl5IS0SI5S5S5SI5lSl5Ev  
call68:_ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISISSISlS5Sl5IS0SI5S5S5SI5lSl5Ev    
call69:fdopen
call70:j__ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl512validAddressEPvS1_
call71:_ZNK63p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISlS5Sl5IS0SI5S5S5SI5lSl563p5lS5SISISlSl5lSlSl5SIS05l5SIS5I5ISI5SISIS5Sl5IS0SI5S5S5SI5lSl512validAddressEPvS1_
call72:__open_2
call73:mprotect
Process terminated
[Pixel 3 XL::com.icbc ]->
 
Thank you for using Frida!
function hook_36390() {
    var targetAddr = Module.findBaseAddress("libDexHelper.so").add(0x36390);
    // 定义替换函数
    var patch_detection = new NativeCallback(function (arg0) {
        console.log(">>> 检测函数 sub_36390 已触发, 拦截并返回 0");
        return 0; // 这里的返回值会自动存入 x0
    }, 'int', ['pointer']);
    // 实施替换
    Interceptor.replace(targetAddr, patch_detection);
 
}
function hook_dlopen() {
    const funcName = "android_dlopen_ext";
    const libc = Module.findBaseAddress("libc.so");
    var funcPtr = Module.findExportByName(null, funcName);
 
    if (funcPtr !== null && funcPtr !== undefined) {
        console.log(`[*] Hooking ${funcName} at libc.so!0x${(funcPtr - libc.base).toString(16)}`);
 
        Interceptor.attach(funcPtr, {
            onEnter: function (args) {
                this.pathPtr = args[0];
 
                if (this.pathPtr !== null && this.pathPtr !== undefined) {
                    try {
                        var path = this.pathPtr.readCString();
                        console.log("\x1b[36m[dlopen] \x1b[0m" + path);
                        if (path.indexOf("libDexHelper.so") !== -1) {
                            this.isTarget = true;
                        }
                    } catch (e) {
                        console.log("[!] Error reading path string in " + this.funcName);
                    }
                }
            }, onLeave: function (retval) {
                if (this.isTarget) {
                    hook_36390();
                }
            }
        });
    } else {
        console.log("[-] Warning: " + funcName + " not found in exports.");
    }
}
function main() {
    hook_dlopen();
}
setImmediate(main);
function hook_36390() {
    var targetAddr = Module.findBaseAddress("libDexHelper.so").add(0x36390);
    // 定义替换函数
    var patch_detection = new NativeCallback(function (arg0) {
        console.log(">>> 检测函数 sub_36390 已触发, 拦截并返回 0");
        return 0; // 这里的返回值会自动存入 x0
    }, 'int', ['pointer']);
    // 实施替换
    Interceptor.replace(targetAddr, patch_detection);
 
}

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 4小时前 被东方玻璃编辑 ,原因: 添加旧版复现时florida避坑
收藏
免费 95
支持
分享
最新回复 (66)
雪    币: 764
活跃值: (2887)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
666
16小时前
0
雪    币: 3705
活跃值: (2364)
能力值: ( LV12,RANK:209 )
在线值:
发帖
回帖
粉丝
3
表哥牛逼
16小时前
0
雪    币: 105
活跃值: (2242)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
66666666666
16小时前
0
雪    币: 4304
活跃值: (3420)
能力值: ( LV12,RANK:220 )
在线值:
发帖
回帖
粉丝
5
太强了,支持一波~
16小时前
0
雪    币: 7513
活跃值: (7568)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
6
棕熊 太强了,支持一波~
感谢佬的vmtrace,强推
16小时前
0
雪    币: 2357
活跃值: (2916)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
666
16小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
前排
16小时前
0
雪    币: 754
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
牛逼
16小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
太强了
16小时前
0
雪    币: 7
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太厉害了
16小时前
0
雪    币: 18
活跃值: (1362)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
太厉害了!!
16小时前
0
雪    币: 740
活跃值: (2517)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
太厉害了!!
15小时前
0
雪    币: 31
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14

你的帖子非常有用,感谢分享!
15小时前
0
雪    币: 160
活跃值: (1566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
太厉害了!!
15小时前
0
雪    币: 58
活跃值: (2240)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
16
很经典的过检测文章。
15小时前
0
雪    币: 579
活跃值: (575)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
66
15小时前
0
雪    币: 1907
活跃值: (1514)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
18
已严肃学习
15小时前
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
感谢分享
15小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
666666666666666666666666666
15小时前
0
雪    币: 3768
活跃值: (4040)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
6
14小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
66666
14小时前
0
雪    币: 8222
活跃值: (4753)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
tql,666
14小时前
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
感谢分享
14小时前
0
雪    币: 4986
活跃值: (5064)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
6666
14小时前
0
游客
登录 | 注册 方可回帖
返回