首页
社区
课程
招聘
[原创] 一次某梆加固的反root和反frida绕过with GPT5.6sol
发表于: 1小时前 45

[原创] 一次某梆加固的反root和反frida绕过with GPT5.6sol

1小时前
45

分析过程

老板扔了一个apk过来,让我绕过反调试。老规矩还是先在真机上跑一遍,发现直接闪退,大概率是设备root的问题,用magisk hide一下就正常运行了。

然后就是看反调试在哪了,解压之后又是经典的libDexHelper.so,网上有很多绕过的教程,思路各不相同,我主要参考了xiaoeryu大佬的博客。正当我准备热火朝天开干的时候,突然发现我frida用不了了,而且平板还反复死机,突然想起来一个问题:
b03K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6N6r3q4U0K9$3!0$3k6i4u0X3L8r3!0%4i4K6u0W2j5$3!0E0i4K6u0r3M7i4g2W2M7%4c8A6L8$3&6K6i4K6u0r3y4e0j5K6x3e0j5K6x3U0W2Q4x3V1k6X3M7X3W2V1j5g2)9J5k6r3k6S2K9h3I4W2k6q4)9J5k6s2c8G2i4K6u0V1M7%4m8S2N6$3&6Q4x3X3c8#2L8X3q4T1L8r3g2Q4x3X3c8@1L8#2)9J5k6r3q4U0j5$3g2K6M7#2)9J5k6s2A6&6k6$3!0@1k6e0j5@1i4K6u0V1N6$3S2A6L8r3g2Q4x3X3c8H3M7X3g2H3j5i4u0A6L8X3N6Q4x3X3c8X3L8%4u0Q4x3X3c8S2M7s2m8Q4x3X3c8D9j5i4g2F1j5H3`.`.


那就很尴尬了,想要用frida hook得先让他跑起来,让他跑起来得hide,hide了又hook不了了,网上的博客中都没提到过这个问题(哭),在679K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3M7X3W2V1j5g2)9J5c8X3k6J5K9h3c8S2i4K6u0r3K9i4y4K6N6h3g2K6i4K6u0r3x3U0M7^5x3W2!0q4c8W2!0n7b7#2)9^5b7#2!0q4y4W2)9&6b7#2)9^5z5g2!0q4y4#2)9&6b7#2)9^5b7W2!0q4y4g2)9^5z5q4!0n7x3q4!0q4y4g2)9^5c8q4)9^5y4#2!0q4y4#2!0n7b7g2!0m8y4$3k6J5K9h3c8S2i4@1f1$3i4K6R3^5i4K6V1H3i4@1f1#2i4K6S2m8i4K6W2r3i4@1f1&6i4K6R3I4i4@1u0r3i4@1f1#2i4K6R3#2i4K6S2p5i4@1f1^5i4@1u0r3i4K6V1&6i4@1f1@1i4@1t1^5i4@1q4m8i4@1f1&6i4K6V1%4i4@1q4q4i4@1f1&6i4@1p5J5i4K6V1^5i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1$3i4K6V1$3i4@1t1&6i4@1f1$3i4@1t1K6i4K6V1#2i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1@1i4@1u0p5i4K6R3$3i4@1f1$3i4K6R3^5i4K6V1I4i4@1f1$3i4K6R3%4i4K6V1J5i4@1f1#2i4@1u0q4i4K6V1%4i4@1f1#2i4K6S2p5i4K6R3%4i4@1f1%4i4@1u0m8i4@1p5%4i4@1g2r3i4@1u0o6i4K6R3^5i4@1g2r3i4@1u0o6i4K6R3&6i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1#2i4@1t1&6i4@1t1J5i4@1f1^5i4K6R3@1i4K6R3$3i4@1f1&6i4@1p5I4i4@1u0m8i4@1f1@1i4@1u0q4i4@1u0r3i4@1f1$3i4K6S2m8i4K6S2m8i4@1f1#2i4K6S2r3i4K6S2p5M7X3!0G2N6q4!0q4y4q4!0n7z5g2)9&6c8W2!0q4y4#2!0n7b7W2)9&6y4g2!0q4z5q4!0n7c8W2)9^5y4#2!0q4y4g2!0m8y4g2!0n7c8q4!0q4y4q4!0n7b7g2)9^5y4W2!0q4x3#2)9^5x3q4)9^5x3R3`.`.

用ida打开libDexHelper.so,发现加壳了

先把magisk hide关掉,然后用frida把so dump下来,再用sofixer修复

function my_hook_dlopen(soName) {
    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) {
                    dump_so(soName);
                }
            }
        }
    );
}
 
function dump_so(so_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/com.****/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + "android_dlopen_ext.so";
    //其中,com.***为包名
    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);
    }
}
 
setImmediate(my_hook_dlopen("libDexHelper.so"));

然后sofixer修复so

.\SoFixer-Windows-64.exe -s libDexHelper.so_0x77e84cc000_0x129000android_dlopen_ext.so -o out1.so

这样就得到一个正常的so了

先确认一下是libDexHelper的反调

function hook_dlopen() {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                this.fileName = args[0].readCString()
                console.log(`dlopen onEnter: ${this.fileName}`)
            }, onLeave: function(retval){
                console.log(`dlopen onLeave fileName: ${this.fileName}`)
                if(this.fileName != null && this.fileName.indexOf("libDexHelper.so") >= 0){
                    let JNI_OnLoad = Module.getExportByName(this.fileName, 'JNI_OnLoad')
                    console.log(`dlopen onLeave JNI_OnLoad: ${JNI_OnLoad}`)
                }
            }
        }
    );
}

setImmediate(hook_dlopen)


接下来就是hook pthread_create看起了什么反调试线程

function hook_pthread_create(){
    var pthC_addr = Module.findExportByName("libc.so", "pthread_create");
    console.log("pthC_addr >> ", pthC_addr);

    Interceptor.attach(pthC_addr, {
        onEnter:function(args){
            console.log(args[2], Process.findModuleByAddress(args[2]).name);
        }, onLeave:function(retval){

        }
    });
}

hook_pthread_create();


可以看到这里没有hook到libDexHelper起的线程,网上的博客说的是某梆也hook了pthread_create,所以需要hook更底层的clone函数,但是我试了之后发现仍然不能看到libDexHelper.so起的线程,不知道是不是版本不同的问题。

既然如此,我们就换个思路,我们hook dlopen的时候得知他已经onleave了,说明大概率是在JNI_Onload里进行的反调(JNI_Onload执行于dlopen onleave后,详细可以看https://bbs.kanxue.com/thread-286004.htm),那我们就去看他JNI_Onload里是怎么反调的,这里我直接让codex去找了,很快就找出来反root在sub_532B8,反frida在sub_548DC


其实也就是简单搜一下字符串回溯一下,安卓的崩溃日志位于/data/tombstone中。查看日志发现,pc被指向到0x1fc导致段错误。而内存中存在/su/bin等检查root的字符串,他们恰好也在sub_532b8中出现了,说明GPT定位的root检测函数是正确的。


那这样大概率所有的检测都复用的一套退出函数,我们深入分析一下,其中sub_548DC调用了sub_31C64

sub_532b8也同样调用了

注意到sub_532b8调用sub_31c64的第二个参数刚好就是崩溃日志中x1的值,第三个参数刚好是x2的值,说明我们找的函数是正确的,这是一个统一处理检测结果的函数,我们只要把这个函数直接ret掉即可

"use strict";

const SO = "libDexHelper.so";
let installed = false;

function describe(p) {
    const m = Process.findModuleByAddress(p);
    return m === null ? p.toString() : m.name + "+0x" + p.sub(m.base).toString(16);
}

function bt(ctx) {
    return Thread.backtrace(ctx, Backtracer.ACCURATE)
        .slice(0, 20).map(describe).join("\n    ");
}

function ret0(addr) {
    Memory.patchCode(addr, 8, code => code.writeByteArray([
        0x00, 0x00, 0x80, 0x52,
        0xc0, 0x03, 0x5f, 0xd6
    ]));
}

function install() {
    if (installed) return;
    const m = Process.findModuleByName(SO);
    if (m === null) return;
    installed = true;

    const dispatcher = m.base.add(0x31c64);
    ret0(dispatcher);
}

function hookLoader(name) {
    const p = Module.findExportByName(null, name);
    if (p === null) return;
    Interceptor.attach(p, {
        onEnter(args) {
            this.hit = false;
            try { this.hit = args[0].readCString().indexOf(SO) !== -1; } catch (_) {}
        },
        onLeave() { if (this.hit) install(); }
    });
}

hookLoader("android_dlopen_ext");
hookLoader("dlopen");
console.log("[ready] exact thread origin tracer");

碎碎念

GPT很快就逆完了,但感觉我好像什么都没干,其中GPT在尝试绕过的时候卡住了几次,我也只能给一些方向性的建议,实际上自己也没有底,最后整理完写博客的时候才慢慢搞懂一些细节。ai确实极大的提高了逆向的速度,但如果仅限于使用ai而没有自己深入的进行分析总结,到时候也只会变成以前大家所不屑的“脚本小子”。


冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回