蜀道山 CTF 部分Reverse
没报名,赛后问朋友要的题,看了看。
loser (Nononono!.exe)
赛中2解
该程序实现了一个类似Base64的算法和一个标准TEA解密算法,用来对输入数据进行编码和加密,并与加密后的结果进行比较,由于程序使用C++,结构体众多,逆向难度中等偏上。
首先是一个类似Base64的编码算法,开始做的时候测试了几个数据,看着很像base64但是其实并不是,算法是以3个字节为一组,每一个字节分别按位与 0x3f 用以获取低6位,然后第2个和第三个and后的数据是要换位置的,第四个字节是前面三个字节的高2位,所以没有加密只是编码,在下面Exp可以看如何解码。
其次是一个TEA解密,拿到key后我们只需要写一个TEA加密,就可以“解密”了。值得注意的是在我们加密前,需要对l和r两个参数进行xor ord('S')即可。
最后是enc了,我们搜索字符串常量right
可以看出 unk_140031520 大概率就是enc了,我们双击进去进行X-Ref,发现它在下面的函数进行了初始化。
copy下来,就可以写exp了。
一个特别小的注意点就是,enc是DWORD big-endian。
Exp:
from regadgets import *
from z3 import *
def decrypt(enc):
assert len(enc) % 4 == 0
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
result = []
for i in range(0, len(enc), 4):
a1 = table.index(enc[i + 0])
a2 = table.index(enc[i + 2])
a3 = table.index(enc[i + 1])
a4 = table.index(enc[i + 3])
result.append(a1 | ((a4 & 0b110000) << 2))
result.append(a2 | ((a4 & 0b001100) << 4))
result.append(a3 | ((a4 & 0b000011) << 6))
return bytes(result)
v4 = [0] * 48
v4[0] = 165
v4[1] = 100
v4[2] = 159
v4[3] = 4
v4[4] = 57
v4[5] = 183
v4[6] = 166
v4[7] = 23
v4[8] = 34
v4[9] = 205
v4[10] = 38
v4[11] = 77
v4[12] = 125
v4[13] = 16
v4[14] = 130
v4[15] = 219
v4[16] = 133
v4[17] = 219
v4[18] = 39
v4[19] = 57
v4[20] = 66
v4[21] = 60
v4[22] = 30
v4[23] = 165
v4[24] = 34
v4[25] = 205
v4[26] = 38
v4[27] = 77
v4[28] = 125
v4[29] = 16
v4[30] = 130
v4[31] = 219
v4[32] = 214
v4[33] = 55
v4[34] = 104
v4[35] = 128
v4[36] = 177
v4[37] = 249
v4[38] = 21
v4[39] = 25
v4[40] = 68
v4[41] = 24
v4[42] = 66
v4[43] = 36
v4[44] = 143
v4[45] = 120
v4[46] = 162
v4[47] = 44
print(len(v4))
v4 = byte2dword(v4, endian='big')
v4 = [i ^ ord('S') for i in v4]
dec = tea_encrypt(v4, key=[ord('L'), ord('Z'), ord('S'), ord('D')])
print(decrypt(dec.decode()))
# 48
# b'LZSDS{how_how_how_how_how_ow_ow_ow!}'