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

一、目标

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

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

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

二、步骤

先写个floatdemotwo

把祖传算法升个级

1extern "C" JNIEXPORT jstring JNICALL 2Java_com_fenfei_app_floatdemo_MainActivity_stringFromJNI( 3 JNIEnv* env, 4 jobject Obj, jdouble value) { 5 std::string hello = "Hello from C++"; 6 7 double p=3.14159; 8 double s,v,rc; 9 10 for(int i=0 ; i< 10; i++){ 11 hello +="\n"; 12 13 v = 2*p* (value + i); 14 s = p * (value + i) * (value + i); 15 16 rc = v+s; 17 18 hello += std::to_string(rc); 19 20 } 21 22 return env->NewStringUTF(hello.c_str()); 23}

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

打印出来结果是这样的

1Hello from C++ 2150.796320 3197.920170 4251.327200 5311.017410 6376.990800 7449.247370 8527.787120 9612.610050 10703.716160 11801.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

1// com/fenfei/test/runfloatdemo.java 2analyseHookA = new FFCodehook(emulator); 3emulator.getBackend().hook_add_new(analyseHookA, module.base + 0x127D8, module.base + 0x127D8, emulator); 4 5// com/fenfei/test/ffcodehook.java 6public class FFCodehook implements CodeHook { 7 private final Emulator<?> emulator; 8 public FFCodehook(Emulator<?> emulator) { 9 super(); 10 11 this.emulator = emulator; 12 } 13 14 private Unicorn.UnHook unHook; 15 16 @Override 17 public void onAttach(Unicorn.UnHook unHook) { 18 if (this.unHook != null) { 19 throw new IllegalStateException(); 20 } 21 this.unHook = unHook; 22 } 23 24 @Override 25 public void detach() { 26 if (unHook != null) { 27 unHook.unhook(); 28 unHook = null; 29 } 30 } 31 32 private static BigInteger newBigInteger(byte[] data) { 33 if (data.length != 16) { 34 throw new IllegalStateException("data.length=" + data.length); 35 } 36 byte[] copy = Arrays.copyOf(data, data.length); 37 for (int i = 0; i < 8; i++) { 38 byte b = copy[i]; 39 copy[i] = copy[15 - i]; 40 copy[15 - i] = b; 41 } 42 byte[] bytes = new byte[copy.length + 1]; 43 System.arraycopy(copy, 0, bytes, 1, copy.length); // makePositive 44 return new BigInteger(bytes); 45 } 46 47 @Override 48 public void hook(Backend backend, long address, int size, Object user) { 49 try { 50 if (address == 0x400127d8) { 51 52 byte[] data = backend.reg_read_vector(Arm64Const.UC_ARM64_REG_Q0); 53 if (data != null) { 54 String strShow = String.format(Locale.US, " Q0=0x%s%s", newBigInteger(data).toString(16), Utils.decodeVectorRegister(data)); 55 System.out.println("##### value " + strShow); 56 } 57 } 58 } catch (BackendException e) { 59 throw new IllegalStateException(e); 60 } 61 } 62}

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

1##### value Q0=0x4062d97b7414a4d2(150.79631999999998) 2##### value Q0=0x4068bd72085b1854(197.92016999999998) 3##### value Q0=0x406f6a786c22680a(251.3272) 4##### value Q0=0x407370474fb549fa(311.01741000000004) 5##### value Q0=0x40778fda5119ce07(376.9908) 6##### value Q0=0x407c13f53a3ec02f(449.24737) 7##### value Q0=0x40807e4c05921038(527.78712) 8##### value Q0=0x408324e161e4f765(612.6100499999999) 9##### value Q0=0x4085fdbab21815a0(703.71616) 10##### value Q0=0x408908d7f62b6ae8(801.10545)

来个条件

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

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

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

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

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

三、总结

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

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

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

ffshow.jpeg

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

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

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

PHP POST 接受长字符串时出现500错误

昨天在开发的时候遇到一个问题,formentype“multipart/formdata”表单提交时显示500错误。开始我以为是php代码问题,我检查了一遍代码,没有问题。之后设置断点,依旧报错500,这就说明断点代码就没有执行,表单提交动作根本没有触发后端的php代码。于是,我将注意力放在了php配置上,反复修改配置调试,而且重装了php依

Twitter的分布式自增ID算法snowflake (Java版)

概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移