美文网首页
代码还原的技术: Unidbg hook_add_new实现条件

代码还原的技术: Unidbg hook_add_new实现条件

作者: fenfei331 | 来源:发表于2021-09-04 16:02 被阅读0次

    一、目标

    在做代码还原的时候,有时候会分析一组结果,希望在中途下个条件断点,比如在代码行0x1234,R0=0x5678的时候触发断点。

    今天我们就来试着搞一下。

    TIP: Unidbg代码同步到官方最新版,最新版已经支持浮点寄存器的显示了。

    二、步骤

    先写个floatdemotwo

    把祖传算法升个级

    extern "C" JNIEXPORT jstring JNICALL
    Java_com_fenfei_app_floatdemo_MainActivity_stringFromJNI(
            JNIEnv* env,
            jobject Obj, jdouble value) {
        std::string hello = "Hello from C++";
    
        double p=3.14159;
        double s,v,rc;
    
        for(int i=0 ; i< 10; i++){
            hello +="\n";
    
            v = 2*p* (value + i);
            s = p * (value + i) * (value + i);
    
            rc = v+s;
    
            hello += std::to_string(rc);
    
        }
    
        return env->NewStringUTF(hello.c_str());
    }
    

    算出10个圆的周长和面积之和。

    打印出来结果是这样的

    Hello from C++
    150.796320
    197.920170
    251.327200
    311.017410
    376.990800
    449.247370
    527.787120
    612.610050
    703.716160
    801.105450
    

    我们的目标是要在结果等于 #449.247370# 的时候触发断点,假装分析下后面 527.787120 的计算过程。

    IDA一把

    ida1.png

    我们在0x127C0下断点,然后n单步几下,到了0x127D4,执行完 FADD D0, D1, D0 这个加法指令之后,可以看到 D0的值是 150.796320

    目标就是它了。我们把条件断点下在0x127D4,当D0=449.247370 的时候触发。

    hook_add_new

    先创建一个ffcodehook类,继承自com.github.unidbg.arm.backend.CodeHook
    然后把它加入到emulator

    // com/fenfei/test/runfloatdemo.java
    analyseHookA = new FFCodehook(emulator);
    emulator.getBackend().hook_add_new(analyseHookA, module.base + 0x127D8, module.base + 0x127D8, emulator);
    
    // com/fenfei/test/ffcodehook.java
    public class FFCodehook implements CodeHook {
        private final Emulator<?> emulator;
        public FFCodehook(Emulator<?> emulator) {
            super();
    
            this.emulator = emulator;
        }
    
        private Unicorn.UnHook unHook;
    
        @Override
        public void onAttach(Unicorn.UnHook unHook) {
            if (this.unHook != null) {
                throw new IllegalStateException();
            }
            this.unHook = unHook;
        }
    
        @Override
        public void detach() {
            if (unHook != null) {
                unHook.unhook();
                unHook = null;
            }
        }
    
        private static BigInteger newBigInteger(byte[] data) {
            if (data.length != 16) {
                throw new IllegalStateException("data.length=" + data.length);
            }
            byte[] copy = Arrays.copyOf(data, data.length);
            for (int i = 0; i < 8; i++) {
                byte b = copy[i];
                copy[i] = copy[15 - i];
                copy[15 - i] = b;
            }
            byte[] bytes = new byte[copy.length + 1];
            System.arraycopy(copy, 0, bytes, 1, copy.length); // makePositive
            return new BigInteger(bytes);
        }
    
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            try {
                if (address == 0x400127d8) {
    
                    byte[] data = backend.reg_read_vector(Arm64Const.UC_ARM64_REG_Q0);
                    if (data != null) {
                        String strShow = String.format(Locale.US, " Q0=0x%s%s", newBigInteger(data).toString(16), Utils.decodeVectorRegister(data));
                        System.out.println("##### value  " + strShow);
                    }
                }
            } catch (BackendException e) {
                throw new IllegalStateException(e);
            }
        }
    }
    

    这样就可以把运行到 0x127D8 指令时的 D0的值都打印出来。

    ##### value   Q0=0x4062d97b7414a4d2(150.79631999999998)
    ##### value   Q0=0x4068bd72085b1854(197.92016999999998)
    ##### value   Q0=0x406f6a786c22680a(251.3272)
    ##### value   Q0=0x407370474fb549fa(311.01741000000004)
    ##### value   Q0=0x40778fda5119ce07(376.9908)
    ##### value   Q0=0x407c13f53a3ec02f(449.24737)
    ##### value   Q0=0x40807e4c05921038(527.78712)
    ##### value   Q0=0x408324e161e4f765(612.6100499999999)
    ##### value   Q0=0x4085fdbab21815a0(703.71616)
    ##### value   Q0=0x408908d7f62b6ae8(801.10545)
    

    来个条件

    现在可以做判断了,在 D0=449.247370 的时候断在它的下一一行,进入调试模式。

    double bOutD = bytes2Double(data);
    if(bOutD == 449.247370){
        Debugger MyDbg = emulator.attach(DebuggerType.CONSOLE);
        MyDbg.addBreakPoint(0x400127dc);
    }
    

    好了,成功进入到了调试模式,可以慢慢分析后面 527.787120 的计算过程了。

    注意:
    浮点数不能直接用 == 判断,因为精度不一样,比较安全的做法是这样的:

    final double THRESHOLD = .0001;
    double bOutD = bytes2Double(data);
    if (Math.abs(bOutD - 449.247370 ) < THRESHOLD) {
        ...
    }
    

    三、总结

    条件断点在分析一组数据的时候很有用。

    hook_add_new其实还可以当Inline Hook用。你也许会问,Inline Hook使用 xhook和其他一些Hook工具不香吗?

    悟空,等你遇到那些神通广大会检测重要代码是否被修改的妖怪的时候,就会想起“硬件断点”的好处了。

    ffshow.jpeg

    老一辈的人常告诉我们,年轻的时候多吃点苦,这样老了才能习惯啊!

    相关文章

      网友评论

          本文标题:代码还原的技术: Unidbg hook_add_new实现条件

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