0x00 题目分析

Rust,安全性极佳

静态代码基本没法看,只能动调了

0x01 解

直接搜字符串,可以看到一段base64的字串:

跟进去解一下

可以看出来cryforhelp应该就是密文了

但是从哪里下手呢?毕竟Rust反编译是这样的

动调吧(

通过动调,一步步看我们的输入被进行了什么操作就行了

那么首先需要知道哪个函数是输入的

这个通过在输入时暂停然后往回跟就能找到这个位置了(此处改了一下名方便后面定位)

之后可以在下面找到输入被存储的地方

看一下整个循环

可以发现其将输入存入v27,如果输入为空的话则补69(ASCII == ‘E’),之后有一个函数,里面长这样

过于离谱,直接出去看v197

可以发现进行的操作比较简单,将一个八字节的字符串两两分组,之后分别-1,+0,+1,+2

然后v197做异或,输出到v23

之后在v23处下硬件断点,可以发现断在了这里

都看看会发现v93就是v23的内容,而v98是一个异或表,这一步是将上一步的结果与v98所存的异或表内的值进行异或

之后再跟v95

可以发现断在了这里,这是一个赋值,v101是上面v95的值,需要将其放入v103内

再跟v103,会发现到这里

这是rust的base64加密的样子,别问,问就是当特征值处理

之后再继续跟这个v108

可以发现到了这个v5,但是v5内并没有任何值,因此继续跟下去这个a2

之后会有一个跟这个情况一样的(即等号左边并没被赋值),直接继续跟下去即可

然后会到这里

查看发现v108内就是跟出来的函数,而再继续跟就会开始打印失败的字符串然后HeapFree

基本可以判断最后这个v108就是结果了

所以综合一下不难看出加密的流程为:

1
2
3
4
1.每八个字节为一组,两两分组,分别进行-1 +0 +1 +2的操作
2.每个字节异或0x33
3.根据异或表进行异或
4.base64加密

所以解密过程就比较明了了

不过怎么获得异或表呢?

对它使用00吧!(00^xx=xx)

在进行异或表异或那一步将输入计算后的值改为00就可以在最后对比的地方得到base64加密的异或表了

大概长度140bytes,转成数组dump下来之后可以写脚本

这里我因为调试的时候没有把第一个值给及时改为00,导致dump下来的数据第一个异或值是错的,正确值的异或表中的值为3(0x33)

不过这只影响第一个值,后面都是对的,跑出来结果第一个值改一下变为f即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import base64
xor = "3F8gIsJ5GVY12otH0xn8VRTN0ntYWQlC3iy0SNnyG6lA4ab7/zjB1eLod3hvIgTmFj4MNVJc/cHlWRzQrlqy3Rn4QuYsiVnlEZzIe4Fwf2+8bwKP9/TIcK4C+FvicggJb79LObXQHqM="
xor = base64.b64decode(xor)
xor=bytearray(xor)
enc = "igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmqm2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc="
enc = base64.b64decode(enc)
enc=bytearray(enc)
dec = [0]*len(enc)
for i in range(len(enc)):
dec[i] = enc[i]^xor[i]

for i in range(len(dec)):
dec[i]^=0x33
x=-1
for i in range(0,len(dec),2):
if i % 8 ==0:
x=-1
dec[i]-=x
dec[i+1]-=x
x+=1
for i in range(len(dec)):
print(chr(dec[i]),end="")
# flag{6e2480b3-4f02-4cf1-9bc0-123b75f9a922}EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE