【Android 逆向】frida 检测绕过

android,逆向,frida,检测,绕过 · 浏览次数 : 1490

小编点评

The code you provided is about hooking functions in the Android system library. **Steps:** 1. **Intercept `dlopen` and `android_dlopen_ext` functions:** - Attach a listener to `dlopen` and `android_dlopen_ext` functions. - Inside the listener, check if the function path matches the target library name. - Set a flag `is_can_hook` to indicate whether a hook can be installed. 2. **Hook `pthread_create` function:** - Use `Interceptor.attach` to hook the `pthread_create` function. - Set a callback function to be called when `pthread_create` is called. 3. **Bypass security checks for `libmsaoaidsec.so`:** - Use `Interceptor.replace` to intercept function calls in `libmsaoaidsec.so`. - Check if the function address is valid and belongs to the library module. - If valid, bypass security checks by setting a flag. 4. **Set a callback for `pthread_create` success:** - Set a callback function to be called when `pthread_create` is successful. - Extract the thread function address from the return value of `pthread_create`. 5. **Bypass anti-hook detection:** - Intercept function calls in `libc.so` and `android_dlopen_ext` to avoid anti-hook detection. - Use `Interceptor.replace` to intercept function calls in the target library. 6. **Run the main function:** - Call `ByPassTracerPid` to initialize the anti-hook mechanism. - Call `hook_dlopen` and `main` functions to perform the necessary steps. **Output:** The code will print messages indicating the following: - Function `dlopen` is hooked. - Function `android_dlopen_ext` is hooked. - `pthread_create` function is hooked. - Security checks are bypassed for `libmsaoaidsec.so`. **Note:** This code assumes that the target library is `libmsaoaidsec.so` and it is located in the Android system library. The library paths may need to be adjusted based on your specific environment.

正文

1. aaa.apk 安装到手机,是一个叫玩吧的应用

./hooker
......
23248  浏 览 器                                     com.browser2345_oem                             
32541  玩吧                                        com.wodi.who                                    
 2447  电话和短信存储                                   com.android.providers.telephony                 
 2447  电话服务                                      com.android.phone                               
 3264  电量和性能                                     com.miui.powerkeeper  
......

2. 启动hluda版frida server hluda-server-14.2.13-android-arm64 绕过一些对frida特征的检查

执行 frida -Uf com.wodi.who --no-pause,直接崩溃退出

Spawned `com.wodi.who`. Resuming main thread!                           
[MI 5X::com.wodi.who]-> Process terminated
[MI 5X::com.wodi.who]->

说明有对frida 附着到进程存在检测

3. 常用检测有 对 TracerPid 的检测,参考r0trace 的方案进行绕过

var ByPassTracerPid = function () {
    var fgetsPtr = Module.findExportByName("libc.so", "fgets");
    var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
    Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
        var retval = fgets(buffer, size, fp);
        var bufstr = Memory.readUtf8String(buffer);
        if (bufstr.indexOf("TracerPid:") > -1) {
            Memory.writeUtf8String(buffer, "TracerPid:\t0");
            console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
        }
        return retval;
    }, 'pointer', ['pointer', 'int', 'pointer']));
};

日志

Spawned `com.wodi.who`. Resuming main thread!                           
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid:  0
Process terminated
[MI 5X::com.wodi.who]->

还是不行,看来还有别的地方检测

4.尝试hook pthread_create 来看一下哪里调用到了它

function hook_func() {
    var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
    Interceptor.attach(pthread_creat_addr,{
        onEnter(args){
            console.log("call pthread_create...")
            let func_addr = args[2]
            console.log("The thread function address is " + func_addr)
            console.log('pthread_create called from:\n' 
            + Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress)
            .join('\n')
             + '\n');
        }
    })
}

执行日志:


call pthread_create...
The thread function address is 0xc0512129
The libmsaoaidsec.so base 0xc0501000
pthread_create called from:
0xc05123fd libmsaoaidsec.so!0x113fd
0xc0511ab7 libmsaoaidsec.so!0x10ab7
0xc0511bc1 libmsaoaidsec.so!0x10bc1
0xc050d5b9 libmsaoaidsec.so!_init+0x1ac
0xec63662b

......
tracerpid replaced: TracerPid:  0
Process terminated

可以看到 libmsaoaidsec.so 执行了0x113fd 后好像就出问题了,而且这个是在_init+0x1ac,很值得怀疑,看一下反汇编的代码

0xc0512129 - 0xc0501000 = 0x11129
可以看到这里看起来一个线程搞事情

int sub_113E0()
{
  _DWORD *v0; // r4
  pthread_t v2; // [sp+0h] [bp-10h] BYREF
  int v3; // [sp+4h] [bp-Ch]

  v0 = off_1FC04;
  v3 = *(_DWORD *)off_1FC04;
  pthread_create(&v2, 0, (void *(*)(void *))sub_11128, 0);
  return *v0 - v3;
}

那么hook 掉这个 sub_11128 ,让他啥也不干,对应偏移地址 0x000113E0

    
    Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
        console.log("0x00011129 replace success!!!")
    }, 'void', []))

执行日志

***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'xiaomi/tiffany/tiffany:8.1.0/OPM1.171019.019/V11.0.3.0.ODBCNXM:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 12322, tid: 12322, name: com.wodi.who  >>> com.wodi.who <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x32b1
    r0 0000c6dd  r1 0000008c  r2 8ea8c4cb  r3 0000023d
    r4 00000000  r5 0008d5f4  r6 00003225  r7 000001aa
    r8 dd932900  r9 ffd70784  sl 00000000  fp ffd70878
    ip ea1a962c  sp ffd6e638  lr c052bc95  pc c052bc96  cpsr 200f0030

backtrace:
    #00 pc 00001c96  /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
    #01 pc 00001c91  /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
***

还是崩了,说明还有地方在检测,比如这个00001c96+0x12000处,
可以看到这里在检测linker的情况,查询了符号表和字符串表,估计实在检查一些函数是否被hook,那先hooker当前这个函数

    Interceptor.replace(module.base.add(0x00013AB0+1), new NativeCallback(function() {
        console.log("0x00013AB1 replace success!!!")
    }, 'void', []))

注意: Thumb指令的地址 ,hook的时候要加1,然后就ok了,进程不再崩溃,执行frida命令ok

日志

Process

tracerpid replaced: TracerPid:  0
tracerpid replaced: TracerPid:  0
[MI 5X::com.wodi.who]-> Process
{
    "arch": "arm",
    "codeSigningPolicy": "optional",
    "id": 12563,
    "pageSize": 4096,
    "platform": "linux",
    "pointerSize": 4
}
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid:  0

全部代码

var ByPassTracerPid = function () {
    var fgetsPtr = Module.findExportByName("libc.so", "fgets");
    var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
    Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
        var retval = fgets(buffer, size, fp);
        var bufstr = Memory.readUtf8String(buffer);
        if (bufstr.indexOf("TracerPid:") > -1) {
            Memory.writeUtf8String(buffer, "TracerPid:\t0");
            console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
        }
        return retval;
    }, 'pointer', ['pointer', 'int', 'pointer']));
};
//setImmediate(ByPassTracerPid);

function hook_dlopen(soName) {
    Interceptor.attach(Module.findExportByName(null, "dlopen"),
        {
            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) {
                    console.log("hook start...");
                    hook_func()
                }
            }
        }
    );
 
    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) {
                    console.log("hook start...");
                    hook_func()
                }
            }
        }
    );
}

function hook_func() {
    var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
    Interceptor.attach(pthread_creat_addr,{
        onEnter(args){
            console.log("call pthread_create...")
            let func_addr = args[2]
            console.log("The thread function address is " + func_addr)
 
            let libmsaoaidsec = Process.findModuleByName("libmsaoaidsec.so")
            if (libmsaoaidsec != null){
                console.log("The libmsaoaidsec.so base " + libmsaoaidsec.base)
                bypass_thread(libmsaoaidsec)
            }

            console.log('pthread_create called from:\n' 
            + Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress)
            .join('\n')
             + '\n');
        }
    })
}

function bypass_thread(module) {
    // Interceptor.replace(module.base.add(0x0000FA98+1), new NativeCallback(function() {
    //     console.log("0x0000FA99 replace success!!!")
    // }, 'void', []))
    
    Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
        console.log("0x00011129 replace success!!!")
    }, 'void', []))

    
P
}

function main() {
    ByPassTracerPid()
    hook_dlopen("libc.so")
}

setImmediate(main)

与【Android 逆向】frida 检测绕过相似的内容:

【Android 逆向】frida 检测绕过

1. aaa.apk 安装到手机,是一个叫玩吧的应用 ./hooker ...... 23248 浏 览 器 com.browser2345_oem 32541 玩吧 com.wodi.who 2447 电话和短信存储 com.android.providers.telephony 2447 电话服

【Android逆向】frida 破解 jwxdxnx02.apk

apk 路径: https://pan.baidu.com/s/1cUInoi 密码:07p9 这题比较简单,主要是用于练习frida 1. 安装apk到手机 需要输入账号密码 2. 使用jdax 查看apk package hfdcxy.com.myapplication; import andr

[Android 逆向]frida 破解 切水果大战原版.apk

1. 手机安装该apk,运行,点击右上角礼物 提示 支付失败,请稍后重试 2. apk拖入到jadx中,待加载完毕后,搜素失败,找到疑似目标类MymmPay的关键方法payResultFalse 4. adb logcat 或者androidstudio 查看该进程的日志,发现以下日志 com.mf

【Android逆向】frida 破解 滚动的天空

1. apk 安装到手机中 2. 玩十次之后,会提示 充值 3. adb shell dumpsys window | grep mCurrentFocus 查看一些当前activity是哪一个 是 AppActivity 4. 阅读代码,感觉是unity3d做的游戏 5. apk拖入到jadx中,

【Android逆向】frida hook so 函数

1. apk来自52pojie 链接:https://pan.baidu.com/s/1vKC1SevvHfeI7f0d2c6IqQ 密码:u1an 2.apktool反编译apk,拿到so文件 java -jar ../apktool_2.2.4.jar d app-debug.apk 3. 用j

【Android逆向】Frida 无脑暴力破解看雪test2.apk

1. 安装apk到手机 adb install -t test2.apk apk下载位置: https://www.kanxue.com/work-task_read-800625.htm 2. 题目提示输入一个五位的数字,那么可以尝试暴力破解 3. apk拖入到jadx中可以看到 public c

【Android逆向】静态分析+frida破解test2.apk

有了上一篇的基础 https://www.cnblogs.com/gradyblog/p/17152108.html 现在尝试静态分析的方式来处理 为什么还要多此一举,因为题眼告诉了我们是五位数字,所以可以爆破,不告诉这个题眼的话,就得分析 1. IDA 打开libroysue.so,查看JNI_O

【Android逆向】脱壳项目frida_dump 原理分析

脱dex核心文件dump_dex.js 核心函数 function dump_dex() { var libart = Process.findModuleByName("libart.so"); var addr_DefineClass = null; var symbols = libart.e

【Android逆向】脱壳项目 frida-dexdump 原理分析

1. 项目代码地址 https://github.com/hluwa/frida-dexdump 2. 核心逻辑为 def dump(self): logger.info("[+] Searching...") st = time.time() ranges = self.agent.search_

[Android逆向]Exposed 破解 jwxdxnx02.apk

使用exposed 遇到了一些坑,这里记录一下 源码: package com.example.exposedlesson01; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.X