代码还原的技术: Unidbg hook_add_new实现条件断点(二)

简介: 代码还原的技术: Unidbg hook_add_new实现条件断点(二)

一、目标


在做代码还原的时候,有时候会分析一组结果,希望在中途下个条件断点,比如在代码行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一把

2222.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工具不香吗?


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


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


TIP: 本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系,本文涉及到的代码项目可以去 奋飞的朋友们 知识星球自取,欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: fenfei331 讨论下。


关注微信公众号: 奋飞安全,最新技术干货实时推送


相关文章
|
4月前
|
Go
Go 1.22 for 循环的两处重要更新
本文介绍了 Go 1.22 版本对 for 循环所做的两处重要更新:循环的每次迭代都会创建新变量 和 循环支持对整数范围进行迭代。 - 循环的每次迭代都会创建新变量,有效避免了以往版本中常见的闭包陷阱,提高了代码的安全性和可预测性。 - 循环支持对整数范围进行迭代,极大地增强了 for 循环的灵活性,使得编写计数循环更加直接和简洁。
90 1
Go 1.22 for 循环的两处重要更新
|
11月前
|
Web App开发 JavaScript API
ng-template 使用过程中参数传递错误的单步调试
ng-template 使用过程中参数传递错误的单步调试
|
23小时前
|
JSON 算法 数据安全/隐私保护
brida和frida练习hook逆向技术【中】
本文介绍了如何在未加壳、未混淆的 APK 中定位并破解加密算法,并使用 Burp 插件 autoDecoder 进行自动化加解密及口令爆破。文中详细描述了从反编译到配置插件的全过程,并提供了关键要素如 AES 算法、SECRET_KEY 和 Base64 编码的具体应用。此外,还展示了如何调整并发数以提高爆破成功率。
9 0
brida和frida练习hook逆向技术【中】
|
10天前
|
Java Android开发 数据安全/隐私保护
brida和frida练习hook逆向技术【上】
使用zangcc测试包.apk,练习 Brida 和 Frida 的 Hook 逆向技术。
13 0
brida和frida练习hook逆向技术【上】
|
4月前
|
Android开发
安卓逆向 -- Hook多个dex文件
安卓逆向 -- Hook多个dex文件
53 1
|
11月前
|
人工智能 自然语言处理 语音技术
pull错代码,恢复到pull之前 ---本地代码回退
pull错代码,恢复到pull之前 ---本地代码回退
119 0
|
缓存 Java 应用服务中间件
Eclipse-无法执行现有代码,依旧执行以前的代码
Eclipse-无法执行现有代码,依旧执行以前的代码
494 0
|
Windows
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
187 0
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
|
Windows
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)
180 0
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)