绕过最新版bilibili APP反Frida机制

安卓的最新版 B 站 APP(7.76.0)有反 FRIDA 机制,本文介绍一下如何绕过它

问题说明

截止到 2024 年 5 月 1 日,B 站最新版的安卓 APP(7.76.0)有反 Frida 机制,不管是 spawn 还是 attach,都无法注入 frida,如下图所示。本文介绍一下如何绕过它

绕过最新版bilibili APP反Frida机制

方法

定位检测点

检测 Frida 的机制一般在 Native 层实现,通常会创建几个线程轮询检测。首先要知道检测机制是由哪个 so 实现的,通过 hook android_dlopen_ext 函数,观察加载到哪个 so 的时候,触发反调试进程终止即可。Frida 脚本代码与输出如下,最终可以定位到检测点在 libmsaoaidsec.so 中。

var interceptor = Interceptor.attach(Module.findExportByName(null"android_dlopen_ext"),
        {
            onEnterfunction (args{
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("[LOAD]", path)
                }
            },
        }
)

绕过最新版bilibili APP反Frida机制

绕过检测点

对抗

使用 IDA 载入 libmsaoaidsec.so,发现没有导入 pthread_create 符号

绕过最新版bilibili APP反Frida机制

使用 Frida 脚本尝试 HOOK pthread_create 函数,也没有找到来自 libmsaoaidsec.so 的调用

var interceptor = Interceptor.attach(Module.findExportByName(null"pthread_create"),
        {
            onEnterfunction (args{
                var module = Process.findModuleByAddress(ptr(this.returnAddress))
                if (module != null) {
                    console.log("[pthread_create] called from"module.name)
                }
                else {
                    console.log("[pthread_create] called from", ptr(this.returnAddress))
                }
            },
        }
)

绕过最新版bilibili APP反Frida机制

分析

尽管表现有点奇怪,但它一定会调用 pthread_create 创建检测线程。所以尝试 hook dlsym 函数,在加载 libmsaoaidsec.so 之前挂钩 dlsym 函数,代码如下

function hook_dlsym({
    var count = 0
    console.log("=== HOOKING dlsym ===")
    var interceptor = Interceptor.attach(Module.findExportByName(null"dlsym"),
        {
            onEnterfunction (args{
                const name = ptr(args[1]).readCString()
                // const module = Process.findModuleByAddress(ptr(this.returnAddress))
                console.log("[dlsym]", name)
                if (name == "pthread_create") {
                    count++
                }
            }
        }
    )
    return Interceptor
}

function hook_dlopen({
    var interceptor = Interceptor.attach(Module.findExportByName(null"android_dlopen_ext"),
        {
            onEnterfunction (args{
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("[LOAD]", path)
                    if (path.indexOf("libmsaoaidsec.so") > -1) {
                        hook_dlsym()
                    }
                }
            },
        }
    )
    return interceptor
}

var dlopen_interceptor = hook_dlopen()

输出如下,在加载 libmsaoaidsec.so 后,调用了 2 次 dlsym 获取 pthread_create 函数,然后进程就终止了。证明它确实会调用 pthread_create,只是调用方式不是直接调用,可能采取了一些对抗手段。

绕过最新版bilibili APP反Frida机制

绕过

它应该是使用了一些反 hook 的手段,没有必要和它正面对抗。简单描述一下我的绕过策略,创建一个 fake_pthread_create 函数,它只有一条 ret 汇编指令,然后 hook 来自 libmsaoaidsec.so 的前 2 次对 dlsym 的调用,返回 fake_pthread_create 函数的地址,这样就达成了欺骗它调用 fake_pthread_create 函数的目的。最终代码如下

function create_fake_pthread_create({
    const fake_pthread_create = Memory.alloc(4096)
    Memory.protect(fake_pthread_create, 4096"rwx")
    Memory.patchCode(fake_pthread_create, 4096, code => {
        const cw = new Arm64Writer(code, { pc: ptr(fake_pthread_create) })
        cw.putRet()
    })
    return fake_pthread_create
}

function hook_dlsym({
    var count = 0
    console.log("=== HOOKING dlsym ===")
    var interceptor = Interceptor.attach(Module.findExportByName(null"dlsym"),
        {
            onEnterfunction (args{
                const name = ptr(args[1]).readCString()
                console.log("[dlsym]", name)
                if (name == "pthread_create") {
                    count++
                }
            },
            onLeavefunction(retval{
                if (count == 1) {
                    retval.replace(fake_pthread_create)
                }
                else if (count == 2) {
                    retval.replace(fake_pthread_create)
                    // 完成2次替换, 停止hook dlsym
                    interceptor.detach()
                }
            }
        }
    )
    return Interceptor
}

function hook_dlopen({
    var interceptor = Interceptor.attach(Module.findExportByName(null"android_dlopen_ext"),
        {
            onEnterfunction (args{
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    console.log("[LOAD]", path)
                    if (path.indexOf("libmsaoaidsec.so") > -1) {
                        hook_dlsym()
                    }
                }
            }
        }
    )
    return interceptor
}

// 创建虚假pthread_create
var fake_pthread_create = create_fake_pthread_create()
var dlopen_interceptor = hook_dlopen()

执行「frida -U -f tv.danmaku.bili -l bypass.js」后即可绕过反 frida 机制,如下图所示

绕过最新版bilibili APP反Frida机制

代码也可从 github 下载,见引用[1]。

引用

[1] https://github.com/ddddhm1234/bypass_bilibili/


原文始发于微信公众号(网络空间威胁观察):绕过最新版bilibili APP反Frida机制

版权声明:admin 发表于 2024年5月1日 下午5:24。
转载请注明:绕过最新版bilibili APP反Frida机制 | CTF导航

相关文章