分类 蜀道山CTF 下的文章

没报名,赛后问朋友要的题,看了看。

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
2024-11-17T12:43:52.png
可以看出 unk_140031520 大概率就是enc了,我们双击进去进行X-Ref,发现它在下面的函数进行了初始化。
2024-11-17T12:44:33.png
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!}'