美文网首页APP & program
Frida Stalker 是什么?

Frida Stalker 是什么?

作者: fenfei331 | 来源:发表于2022-06-16 07:46 被阅读0次

    一、目标

    在分析so中的算法时,Trace和Debug是常用的手段。

    了解一些调试器原理的同学都知道,Trace和Debug需要修改原始代码加上个int 3,来激活调试器。

    这样有些App可以依赖检测关键代码来判断是否被调试。

    也许你会说,我们可以patch掉检测代码,上次飞哥遇到一个狠人app,B去检测A处的代码,C去检测B处的代码,D去检测C处的代码,…… 反正套娃了 5-6次,我就崩溃了。

    还好有 Stalker

    Stalker是基于动态重新编译的代码跟踪器。 它将代码指令复制到内存中的另一个位置,在该位置对其进行调整以适应新位置并包括其他跟踪指令。 如果应用程序在原始位置检查其代码,则会发现该代码是完整无缺的,因为它是被篡改的代码的副本。

    二、步骤

    Stalker Trace Code

    我们还是以上次分析的某小说App来演示 Stalker 的用法, http://91fans.com.cn/post/readbookone/

    Stalker在ARM32下貌似不大好使,这里我们在ARM64下做的测试

    function trace_entry(baseAddr,tatgetAddr){
        Interceptor.attach(tatgetAddr, {
            onEnter: function(args){
                console.log("enter tatgetAddr====================================================================");
    
                this.pid = Process.getCurrentThreadId();
                Stalker.follow(this.pid,{
                    events:{
                                                            // 暂时不需要这些 events
                        call:false,
                        ret:false,
                        exec:false,
    
                        block:false,
                        compile:false
                    },
                    onReceive:function(events){
                    },
    
                    transform: function (iterator) {
                        var instruction = iterator.next();
                        const startAddress = instruction.address;
                                            // 从ida里面 找到 Java_com_baidu_searchbox_NativeBds_dae1 函数的 代码 在 0xE84 和 0x126C 之间
                        var isModule = startAddress.compare(baseAddr.add(0xE84)) >= 0 && startAddress.compare(baseAddr.add(0x126C)) < 0;
                        do{
                            if (isModule){
                                    console.log(instruction.address.sub(baseAddr) + "\t:\t" + instruction);
                            }
                            iterator.keep();
                        } while ((instruction = iterator.next()) !== null);
                    },
    
                    onCallSummary:function(summary){
    
                    }
                });
            },onLeave: function(retval){
                Stalker.unfollow(this.pid);
                console.log("retval:"+retval);
                console.log("leave tatgetAddr====================================================================");
            }
        });
    }
    

    需要解释的是 transform 函数, 其他的 events、 onReceive 和 onCallSummary 目前我们还用不到,它们可以做block 和 call之类的跟踪分析。

    transform 遍历执行了当前的每一行汇编指令,默认显示的地址是实际内存地址,我们 instruction.address.sub(baseAddr) 减去了一个so的基地址,得到的就和ida中显示的地址一致了

    main.png

    加Hook

    光显示指令没啥意思,指令看上去还没有ida好看呢。

    但是这个是活的执行,我们可以加个hook,通过ida分析,感觉差不多 0xFB8的时候是计算key的长度。

    key.png

    所以我们在这里加个打印

    do{
        if (isModule){
            console.log(instruction.address.sub(baseAddr) + "\t:\t" + instruction);
    
            if(instruction.address.sub(baseAddr) == 0xfb8){
                iterator.putCallout((context) => {
                var string = Memory.readCString(context["x21"]);
                console.log("####  key = " + string)
                })
            }
        }
        iterator.keep();
    } while ((instruction = iterator.next()) !== null);
    

    这样就可以顺利的打印出本次aes算法中用的key了

    0xfb4        :        add x21, x21, x0, lsr #1
    0xfb8        :        mov x0, x21
    0xfbc        :        ldr x22, [x8, #0x580]
    0xfc0        :        bl #0x7a751c55f0
    ####  key = D0CD8B760CE07BC3
    0xfc4        :        mov x1, x0
    0xfc8        :        mov x0, x20
    0xfcc        :        blr x22
    0xfd0        :        ldr x8, [x20]
    

    更帅的Trace

    我们现在掌握了打印指令和寄存器值的方法。不过这样打出来太不帅了,IDA的Trace只会打印被修改的寄存器的值。

    还好有大佬已经写好了

    https://github.com/bmax121/sktrace

    先 把我们代码中 Stalker 部分注释掉,因为要干掉登录和vip,所以先启动我们的js

    frida -U -l bqgst.js -f com.bqg.ddnoverl --no-pause
    

    然后启动 sktrace

    python sktrace.py -m attach -l libTxtFormatter.so -i Java_com_baidu_searchbox_NativeBds_dae1 com.bqg.ddnoverl
    

    -l 指定so名称

    -i 指定要Trace的函数名

    最后跟的是包名或者app名称

    0x7a2e289e9c        add        x29, sp, #0x50        ; x29=0x7a7bdb9d48->0x7a7bdb9c50
    0x7a2e289ea0        mov        x20, x0        ; x20=0x0->0x7c02192b70
    0x7a2e289ea4        ldr        x8, [x20]        ; x8=0x79a1c49061b6ff43->0x7b3fe0e198
    0x7a2e289ea8        mov        x1, x2        ; x1=0x9e30a688->0x7a7bdb9d18
    0x7a2e289eac        mov        x2, xzr        ; x2=0x7a7bdb9d18->0x0
    0x7a2e289eb0        mov        x19, x3        ; x19=0x7cb23102a0->0x7a7bdb9d1c
    0x7a2e289eb4        ldr        x8, [x8, #0x548]        ; x8=0x7b3fe0e198->0x7b3fbe20e0
    0x7a2e289ebc        ldr        x8, [x20]        ; x0=0x7c02192b70->0x7b522130f0, x1=0x7a7bdb9d18->0x7dee5ef7cc, x3=0x7a7bdb9d1c->0x10, x4=0x7a7bdb9d58->0x0, x8=0x7b3fbe20e0->0x7b3fe0e198, x11=0x40->0x522130f7, x12=0xb->0xffff00000eff, x13=0x380->0xafba2fb8, x16=0x7a2e289e94->0x7dd27ad7f8, x17=0x7cb23102a0->0x7dee554c78, x30=0x7deaefdc0c->0x7a2e289ebc
    0x7a2e289ec0        mov        x21, x0        ; x21=0x0->0x7b522130f0
    0x7a2e289ec4        ldr        x22, [x8, #0x580]        ; x22=0x7abbab01b8->0x7b3fbe5504
    0x7a2e2895f0        adrp        x16, #0x7a2e29a000        ; x16=0x7dd27ad7f8->0x7a2e29a000, x30=0x7a2e289ebc->0x7a2e289ecc
    0x7a2e2895f4        ldr        x17, [x16, #0xfe8]        ; x17=0x7dee554c78->0x7dee561980
    0x7a2e2895f8        add        x16, x16, #0xfe8        ; x16=0x7a2e29a000->0x7a2e29afe8
    

    现在打出来的,就有ida Trace内味了。

    同学们还可以模仿下sktrace的代码,搞个更趁手的兵刃出来。

    三、总结

    矛与盾的战斗是永不停息的,无痛hook,硬件断点应该是趋势。

    一个趁手的调试器非常难得,一个能被Debug的App是藏不住秘密的。

    ffshow.jpeg

    万事纷纷一笑中,渊明把菊对秋风

    相关文章

      网友评论

        本文标题:Frida Stalker 是什么?

        本文链接:https://www.haomeiwen.com/subject/xwucvrtx.html