本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!
推荐阅读
这个样本 unidbg 部分可以参考龙哥的 csdn 教程,可以参考一下
龙哥 csdn 最右样本
前言
最右 app 参数分析,版本 5.7.3
charles 抓包
一共有三个加密参数 sign request response
一个一个来看,java
层的就不再分析了,可以参考龙哥样本
so 分析
先使用 unidbg
加载 so
查看动态注册的函数地址,先来分析 encodeAES
函数
0x1 encodeAES
ida
跳过来,主要查看这个函数
点进来可以看到,这里是标准的 AES_128_cbc
算法,调用的是 openssl
库
通过查找 openssl 相关的资料得知,j_EVP_EncryptInit_ex 此函数的 后面两个参数 分别是 aes 的 key iv
可以参考此文章: https://blog.csdn.net/viewsky11/article/details/78983234
0x2 sign
此函数是变形的 md5,龙哥的 csdn 已经放出 python 源码,这里就不再分析了
0x3 decodeAES
ida
跳转到 decodeAES
函数,主要分析此函数
这里跟加密逻辑相同,使用的 openssl
库解密,下面使用 frida hook
一下
frida hook
具体的 hook
代码,俺就不贴出来,大家自行写一下,有啥问题一起讨论哈,我这里主要是 hook 了 java 层的几个 native 函数,跟 so aes key iv 相关的函数
先来看下 encodeAES
函数部分
1、encodeAES 参数
2、aes key
3、aes iv
4、aes encrypt result,最后会把 aes iv 拼接到加密结果前面
这里是 sign
比较简单,就是拿着 aes
加密结果进行 md5
运算
这是 decodeAES
部分
1、decodeAES 参数,也是请求的响应值
2、aes key
3、aes iv,这里的 iv 正是 参数一的前 16 个字节
4、aes 解密结果,但不是明文,显然后面还有其他的处理
5、最后才是最终的明文
unidbg
下面开始使用 unidbg 跑起来,不过这个样本的 aes key iv 都是动态生产的,所以需要先把 key iv 固定才行
下面的话我就直接贴代码了,具体含义可以参考龙哥的文章
unidbg hook 使用大全
public void ReplaceArgByConsoleDebugger() {
emulator.attach().addBreakPoint(module.base + 0x5E1A2, new BreakPointCallback() {
@Override
public boolean onHit(Emulator<?> emulator, long address) {
String fakeInput = "1b 4a 4a 59 59 59 59 e9 e9 f8 f8 f8 f8 09 09 09".replace(" ", "");
emulator.getBackend().mem_write(0x403d2700, hexToByteArray(fakeInput));
Inspector.inspect(emulator.getBackend().mem_read(0x403d2700, 16), " 0x403d2700 ");
return true;
}
});
emulator.attach().addBreakPoint(module.base + 0x5E140, new BreakPointCallback() {
@Override
public boolean onHit(Emulator<?> emulator, long address) {
String fakeInput = "c1 10 90 90 90 90 9f 9f 9f 9f be be be be ce ce ".replace(" ", "");
emulator.getBackend().mem_write(0x403df040, hexToByteArray(fakeInput));
Inspector.inspect(emulator.getBackend().mem_read(0x403df040, 16), " 0x403df040 ");
return true;
}
});
emulator.attach().addBreakPoint(module.base + 0x5d22a, new BreakPointCallback() {
@Override
public boolean onHit(Emulator<?> emulator, long address) {
String fakeInput = "de fd fd 0d 0d 0d 0d 1d 1d ac ac ac ac bc bc bc".replace(" ", "");
int length = fakeInput.length();
MemoryBlock fakeInputBlock = emulator.getMemory().malloc(length, true);
fakeInputBlock.getPointer().write(hexToByteArray(fakeInput));
emulator.getBackend().reg_write(ArmConst.UC_ARM_REG_R6, fakeInputBlock.getPointer().peer);
return true;
}
});
}
代码写完跑起来,调用 encodeAES
函数,正常运行,结果跟 frida hook
出来的结果相同
在调用 sign
签名函数,结果也是相同的
最后便是 decodeAES
结果也是正常解密出来
最后
最右的分析到此结束,这里还有一个坑,就是 aes 解密之后还有一步处理,这个大家自行分析吧,总之就是要细心,不然可能会走很多弯路
此样本难度不高,主要是 key iv 动态生成的,会影响到 unidbg 的动态调试,这个搞完也算是,对 unidbg 的使用有了进一步的了解
最后附上 python
还原的效果图,有啥问题可以一起讨论哦