一、前言 1、题目https://bbs.pediy.com/thread-260650.htm https://bbs.pediy.com/thread-260655.htm
二位大佬的两种解题思路,膜拜膜拜
2、这篇帖子你会看到什么ollvm可以使用ida的trace功能辅助还原,看到样本上手尝试一下。 上面的帖子中有部分使用trace进行辅助还原,这篇帖子是通过trace后的汇编指令进行的ollvm还原过程,记录分享一下过程,不喜勿喷。
3、ida trace功能
(1)Instruction tracing调试器将为每条指令保存所有修改后的寄存器值。 https://www.hex-rays.com/products/ida/support/idadoc/1446.shtml
(2)Basic block tracing调试器将保存到达临时基本块断点的所有地址。 https://www.hex-rays.com/products/ida/support/idadoc/1628.shtml
(3)Function tracing调试器将保存发生函数调用或函数返回的所有地址。 https://www.hex-rays.com/products/ida/support/idadoc/1447.shtml
二、还原ollvm混淆函数过程 1、对应到还原函数 sub_13CE4
定位过程可以参考上面2个帖子
2、通过frida进行函数调用function call_13CE4() {
var base_xxx = Module.findBaseAddress("libnative-lib.so")
if(base_xxx){
var addr_13CE4 = base_xxx.add(0x13CE4)
console.log("0x13CE4 :", addr_13CE4)
var sub_13CE4 = new NativeFunction(addr_13CE4, "void", ["pointer", "int", "pointer", "int", "pointer"])
var input1_str = "pediy_imyang_lXcaTALmow"
var input1_buffer = Memory.allocUtf8String(input1_str)
var input2_str = "www.pediy.com&kanxue"
var input2_buffer = Memory.allocUtf8String(input2_str)
var result = Memory.alloc(0x26);// 38
console.log("input1_str len ", input1_str.length)
console.log("input2_str len ", input2_str.length)
sub_13CE4(input1_buffer,input1_str.length,input2_buffer,input2_str.length,result)
console.log(hexdump(result, {length: result.length}))
}
}
结果显示:
参数:
参数1 pediy_imyang_lXcaTALmow
参数2 23
参数3 www.pediy.com&kanxue
参数4 20
参数5 结果地址
结果:
79 79 03 09 00 01 a4 b8 b6 c8 9e b4 7f 4f 29 b4 4d 47 c7 38 2f 85 1a d5 76 18 f9 b8 20 c5 d5 52 98 cb 5f 94 1c 8c
3、在0x13CE4和函数结束的位置0x下断点,trace出来函数中汇编
trace后的cfg,变黄色就是执行的汇编指令被trace过
sub_13CE4中调用了sub_13808和sub_172D0
4、分析trace文件 (1)分析参数1参数1 pediy_imyang_lXcaTALmow 对应trace文件 以 0x0000000000000070看一下具体处理 参数1 中的 0x70 -> 0x51,是通过如下进行的查询0x70的位置是0x51 最终结果为
参数1 加密后
(2)分析参数3参数3 www.pediy.com&kanxue
trace文件中参数3只用了16个字符进行后续的处理 这里的处理和参数1处理的方式相同
参数3 加密后
(3)结果生成使用参数1加密后的字节和参数3加密后的字节进行计算加密生成结果
图一
图一是 参数1加密字节0x00000000514D43F9 和 参数3加密字节 0x00000000F5F5F531 生成的结果是 0x00000000A4B8B6C8
图二
图二是 参数1加密字节0x00000000b6cff93c 变形为 00000000CFF93CB6 (未参与加密)
参数3加密字节 0x00000000514d43f9 和 常数 0x0000000068DE32AA 加密乘车生成的结果是 0x000000009EB47F4F
图三
图三是 参数1加密字节0x00000000b6ef9f85 变形为 0x000000009F85B6EF
和 参数3加密字节 0x00000000B631FBA8 生成的结果是 0x0000000029B44D47
图四
图三是 参数1加密字节0x00000000cf506afb 变形为 0x00000000FBCF506A
和 参数3加密字节 0x000000003CF77FEF 生成的结果是 0x00000000C7382F85
拼接结果 A4B8B6C8 9EB47F4F 29B44D47 C7382F85 和结果对比
797903090001 a4b8b6c8 9eb47f4f 29b44d47 c7382f85 1ad57618 f9b820c5 d55298cb 5f941c8c
根据以上的分析可以得到算法如下: 参数1加密后字节
514d43f9 b6cff93c b6ef9f85 cf506afb ef208329 3ca8f563 63636363 63636363
参数3加密字节
f5f5f531 514d43f9 b631fba8 3cf77fef f5f5f531 514d43f9 b631fba8 3cf77fef
循环8次
参数1加密后字节会随着循环次进行变化
0次 514d43f9 -> 514d43f9
1次 b6cff93c -> cff93cb6
2次 b6ef9f85 -> 9f85b6ef
3次 cf506afb -> fbcf506a
....
这是有规律的根据循环进行的变化
在第1次和第5次的时候
参数1加密后字节只是做的了变形 未参加加密
参数3加密字节与常量0x0000000068DE32AA进行了加密
其他循环中都是参数1加密后字节与参数3加密字节进行加密操作
以图一为例,计算如下:
X8 = 0x00000000f5f5f531
X9 = 0x0000000514d43f9
W11 = X8 & (X8^X9)
w8 = X9&(X9^X8)
w8 = 0xa4b8b6c8
797903090001 这个值的赋值可以通过2种方式
方法一: 动态调试的时候 x4指向的地址 前六为是固定的 直接可以拿到(多次调试的结果)
方法二:trace中找赋值过程
以上就是通过对trace的汇编指令进行的ollvm函数还原,按以上信息可以写出算法,偷懒先不写了,可以看一下上面的帖子。
三、总结1、trace的分析还需要继续加深学习和掌握,上面的分析中对内存中连续值的赋值和拼装找的还不是很好; 2、非常感谢看雪论坛,故把分析过程分享给大家 3、这都是大佬的经验之谈,牛逼牛逼
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2020-9-2 09:43
被neilwu编辑
,原因:
上传的附件: