soul cs字段unidbg逆向
so逆向
unidbg能跑了,接下就是结合ida进行逆向。
![](https://img.haomeiwen.com/i2591919/11455f241270aecf.png)
先跳转到函数的地址0xaa73c
![](https://img.haomeiwen.com/i2591919/1868f923983ac28d.png)
很显然,so经过了混淆。实际上,里面很多函数都经过了ollvm平坦化。
![](https://img.haomeiwen.com/i2591919/5d06e0fa535073d7.png)
接下来,我们要把它进行一个还原。
![](https://img.haomeiwen.com/i2591919/d0697b7a0c00e851.png)
鼠标放在BX
语句上,Tab
切换到汇编界面
![](https://img.haomeiwen.com/i2591919/7335af8763c8ea3e.png)
在0xAA7B4下断点
![](https://img.haomeiwen.com/i2591919/69829bb3381d64de.png)
patch这条命令,让它直接跳转到0xaa7b8
![](https://img.haomeiwen.com/i2591919/60825083178f87fc.png)
![](https://img.haomeiwen.com/i2591919/ced15a37026827e6.png)
变成了sub_AA7B8
,但它显然不是函数,在它上面按U
,把它解析成数据
![](https://img.haomeiwen.com/i2591919/0bbbe340f7db075b.png)
再按C
,转成代码
![](https://img.haomeiwen.com/i2591919/eaa7b08bb5140936.png)
![](https://img.haomeiwen.com/i2591919/8e246fa2a2e90a56.png)
在loc_AA7B8
这一段代码的最后按E
,标记其为函数结尾。
再转回到伪代码界面,按F5
![](https://img.haomeiwen.com/i2591919/d76a323cceaa0f25.png)
可以看到,比之前稍微多了一些代码。继续下断点,patch。
![](https://img.haomeiwen.com/i2591919/1a5ee06f790202a1.png)
0xAA9F4
下断点
![](https://img.haomeiwen.com/i2591919/0e9ba78fac897512.png)
patch,直接跳转0xaa9f8
![](https://img.haomeiwen.com/i2591919/54b3ba23f8796f8c.png)
处理一下
![](https://img.haomeiwen.com/i2591919/e662258dba679c89.png)
回到伪代码界面F5
![](https://img.haomeiwen.com/i2591919/62aeaa7e55d0c1c5.png)
又多了一些代码。
![](https://img.haomeiwen.com/i2591919/80d3ee55124b3d92.png)
![](https://img.haomeiwen.com/i2591919/5a04d182ec1c8e06.png)
![](https://img.haomeiwen.com/i2591919/b1f05ffbd7993116.png)
![](https://img.haomeiwen.com/i2591919/71f6d995d606b15f.png)
![](https://img.haomeiwen.com/i2591919/46bd2c8ceca46e66.png)
代码越来越多了。
![](https://img.haomeiwen.com/i2591919/d270407ad12653ea.png)
![](https://img.haomeiwen.com/i2591919/c77f8bedd629265a.png)
![](https://img.haomeiwen.com/i2591919/9afc1757cc0186d7.png)
0xaa9f8
,很熟悉的数字,实际上,从这里开始,之后都是会跳转到0xaa9f8
,因为这里是ollvm的分发块
![](https://img.haomeiwen.com/i2591919/98c6607e2a971a0c.png)
接下来的工作,就是不断的把跳转指令BX R0
改为B 0xAA9F8
![](https://img.haomeiwen.com/i2591919/6ac1f9330012e61c.png)
经过近1个小时的修改,sub_AA73C
变成了一个1000多行代码的函数。
![](https://img.haomeiwen.com/i2591919/8235c90ad5067e14.png)
想从里面找到加密的函数不太容易,先hook几个函数看看
看看sub_94DA4
![](https://img.haomeiwen.com/i2591919/16d37fb282fc41d6.png)
也是被混淆了,先下断点看看(这个函数被调用了几次)
![](https://img.haomeiwen.com/i2591919/c7dc779050b3c7e9.png)
![](https://img.haomeiwen.com/i2591919/410fd65239173a44.png)
可以看到这里出现了加密结果的一部分数据,而且是关键的数据。
![](https://img.haomeiwen.com/i2591919/43c27f7c96ca1e13.png)
对0xbffff6a8
进行写跟踪,看看哪里对它进行了写入操作
emulator.traceWrite(0xbffff6a8L, 0xbffff6a8L+16);
![](https://img.haomeiwen.com/i2591919/d1f8bacce27a103c.png)
跳转到写入0xc166a512
的地方,也就是0xaae64
![](https://img.haomeiwen.com/i2591919/331f57d551102156.png)
![](https://img.haomeiwen.com/i2591919/ef377e9b02d3bf08.png)
下个断点看看
![](https://img.haomeiwen.com/i2591919/1984d2e0660c87f8.png)
看看0xbffff6d8
的值
![](https://img.haomeiwen.com/i2591919/5ce5b0ed800145b7.png)
继续对0xbffff6d8
进行写跟踪,看看哪里对它进行了写入
emulator.traceWrite(0xbffff6d8L, 0xbffff6d8L+4);
![](https://img.haomeiwen.com/i2591919/12ae33bca932290b.png)
跳转到0x97ce8
![](https://img.haomeiwen.com/i2591919/18dec1b25c79b7ed.png)
然后就跳转到了一个更多代码的函数,而且这个函数有接近50个传入参数,这显然是不对的
![](https://img.haomeiwen.com/i2591919/2365bc9a8a22fc2b.png)
![](https://img.haomeiwen.com/i2591919/49ab6195b46653f2.png)
而且从指令看也不太对,没有push
操作。那就从这里往上面找,找到push的地方
![](https://img.haomeiwen.com/i2591919/ec7b82cb4b5a4684.png)
最终是在0x9609C
找到了函数sub_9609C
。我们可以像之前一样,下断点,修复跳转的地方,把它修补成一个正常的函数。
也可以直接在函数入口下断点,先看看入参。
![](https://img.haomeiwen.com/i2591919/c2b98d393abf010b.png)
![](https://img.haomeiwen.com/i2591919/211f506848c62eb5.png)
blr
在函数返回处下断点,然后c
执行到函数返回处,看看原r2
的值。
![](https://img.haomeiwen.com/i2591919/168067f527ccd6db.png)
cyberchef看看是不是MD5
![](https://img.haomeiwen.com/i2591919/49e8ca51ee3043ee.png)
和unidbg能对上。
继续往下执行,发现sub_9609C
还被调用了,看看数据
![](https://img.haomeiwen.com/i2591919/ea48b39ccc422023.png)
![](https://img.haomeiwen.com/i2591919/dd03313e8a0a685f.png)
这个是url+时间戳重排序+字符串常量
blr
在函数返回处下断点,然后c
执行到函数返回处,看看原r2
的值。
![](https://img.haomeiwen.com/i2591919/f7e7a8c40f3e253f.png)
在cyberchef验证下
![](https://img.haomeiwen.com/i2591919/6bf10dc30a3b54e9.png)
也能够对上。至此需要的字段都找到了来源,接下来就是算法实现
import hashlib
def calc_cs(url, header, ts):
ts = ts.to_bytes(4, 'big').hex()
print(ts)
data1 = ''.join((header, 'SoulPowerful'))
print(data1)
s1 = hashlib.md5(data1.encode()).hexdigest()
print(s1)
t2 = ''.join(ts[idx] for idx in [1, 4, 2, 7, 6, 0, 5, 3])
data2 = ''.join((url, t2, 'kG@yGB9'))
print(data2)
s2 = hashlib.md5(data2.encode()).hexdigest()
print(s2)
cs = ''.join([
'028f',
s1[0:2],
ts[3],
ts[1],
s1[2:4],
ts[6],
ts[5],
s1[4:6],
ts[4],
ts[0],
s1[6:8],
ts[7],
ts[2],
'776U',
s2[0:8],
'77ac'
])
return cs
def test_cs():
cs = calc_cs('hello', 'everhu', 0x01234567)
print(cs)
assert cs == '028f0b315a6533402772776U12a566c177ac'
![](https://img.haomeiwen.com/i2591919/2c11ecd8a461dcd9.png)
总结
-
028f, 776U, 77ac
这几个暂时不完全清楚是怎么来的,只能说cs的逆向完成了一部分。 - ollvm的逆向分析太难了,如果不是刚好找到突破口,或者加密的逻辑再复杂点的话,感觉很难有所收获。暂时还没有能力去除控制流平坦化,以后学会了会再尝试分析。