ByteCTF MordernCPP WriteUp

2021-10-19
#wp #ctf #re

通过Ghidra分析可以看出main函数里面有大量try catch结构。整个程序的核心控制逻辑都是由try catch来控制的。因此动调的时候尽量都跟进函数里,先分析出程序的大体执行流程。

image-20211019153756139

可以识别几处函数的跳转(图片来自Socular师傅)

5d8c3853-57e7-4d2a-a8e8-1e471c34db22

动调过后可以发现,两个关键函数为sub_40211Csub_4024A4。通过常数可以轻松识别出来,sub_4024A4是TEA加密,密钥可以调试得来为byte-ctfwecome~。密文与从0x536800开始的40字节对比。因此可以直接写出解密脚本。

解得原文为

[0x0c, 0xf0, 0x69, 0xd8, 0x4a, 0x32, 0xfb, 0x62, 0x8e, 0xa4, 0xcc, 0x0c, 0xc0, 0x22, 0x63, 0xe5, 0xb6, 0xfd, 0x07, 0x5e, 0xe6, 0xfe, 0xc6, 0x8d, 0xfd, 0x8d, 0x51, 0xad, 0xe4, 0x68, 0xfa, 0x14, 0x78]

sub_40211C函数先逐字符将flag转化为01串(每个字符对应的01串长度不一定相等),然后把这个01串8个一组,变成二进制数组,传入TEA加密。

由于这个对应表可能是c++的某种hash表储存,难以直接找到。因此我写了一个IDA的条件断点来输出对应的01串。

image-20211019161241416

执行会有如下输出

image-20211019161515594

因此多来几次,把所有的可能字符都打出表来,再遍历即可

l=[0x0c, 0xf0, 0x69, 0xd8, 0x4a, 0x32, 0xfb, 0x62, 0x8e, 0xa4, 0xcc, 0x0c, 0xc0, 0x22, 0x63, 0xe5, 0xb6, 0xfd, 0x07, 0x5e, 0xe6, 0xfe, 0xc6, 0x8d, 0xfd, 0x8d, 0x51, 0xad, 0xe4, 0x68, 0xfa, 0x14, 0x78]

ss="".join([bin(b)[2:].zfill(8) for b in l])
table={
    '!': '00110110',
    '#': '101001',
    '%': '00010',
    '&': '10100011100',
    '(': '010011',
    ')': '111100',
    '*': '0110010',
    '+': '10111',
    '-': '10100010',
    ';': '1010000',
    '=': '000000',
    '@': '1110011',
    '[': '110011',
    ']': '00100',
    '^': '01111',
    '_': '01010',
    '{': '10001',
    '}': '1010001111',
    'a': '100101',
    'b': '00001',
    'c': '01110',
    'd': '11011',
    'e': '0011010',
    'f': '010010',
    'g': '111011',
    'h': '01000',
    'i': '10110',
    'j': '00110111',
    'k': '1111010',
    'l': '110010',
    'm': '00011',
    'n': '10000',
    'o': '10100011101',
    'p': '0110011',
    'q': '011000',
    'r': '111110',
    's': '01011',
    't': '11000',
    'u': '11110110',
    'v': '000001',
    'w': '111000',
    'x': '00101',
    'y': '10011',
    'z': '101000110',
    '1': '100100',
    '2': '111111',
    '3': '01101',
    '4': '11010',
    '5': '11110111',
    '6': '001100',
    '7': '111010',
    '8': '00111',
    '9': '10101',
    '0': '1110010'
}

states=[(ss,'')]
while len(states):
    s,result=states.pop(0)
    for ch,bi in table.items():
        if s.startswith(bi):
            states.append((s[len(bi):],result+ch))
            break
    else:
        break
print(result)

最后flag为bytectf{autofp=[=](m0d3rnc++juejuezi){};}。(是c++的lambda表达式