逆向攻防世界CTF系列30-re2-cpp-is-awesome

64位无壳,c++代码,根据shift+f12得flag定位到这,直接看到if(V8!=xx)可以猜测是在验证,跟进sub_400B56也验证了我们的猜测

image-20241112203334509

初始化和字符串分配

std::allocator<char>::allocator(&v12, a2, a3);
std::string::basic_string(v11, a2[1], &v12);
std::allocator<char>::~allocator(&v12);

这里,程序使用分配器对象 allocator 来管理内存,并将用户输入的字符串(即 flag 值)存储在 v11 中。之后释放分配器对象。

其实上面的那些不认识的代码可以猜测出来的,重要的是while循环

if ( *v8 != off_6020A0[dword_6020C0[v14]] )

这个是取出我们输入得字符每个字符去做校验

off_6020A0是key可以理解为,看看dword_6020C0

image-20241112204325405

开始看这个看蒙蔽了,怎么做?

涨知识了

这里有个align 8,align num是让后面的字节都对齐num,也就是这里都对齐8才对,中间补7个0。可是这里下一个数和上一个数明明间隔4而已!后来查了很多资料才发现是IDA自动把多个0判断成对齐操作了,这里align 8是因为前面dd 24h中本来是db 24 0 0 0 然后后面一个双字是dd 0 也就是db 0 0 0 0,IDA把这连着的7个0当成了间隔,那上一个数和下一个数间隔就是8了,所以IDA生成了align 8。我们只要鼠标右键undefine或把上面的dd 24改一下数据大小即可重定义align 8,重新生成数据了。(前面的align 20h 也是同样的道理)

其实也可以这样理解

align 8 是一种内存对齐指令,意思是将接下来的数据起始地址对齐到 8 字节边界。这意味着数据在内存中的地址将是 8 的倍数。

在汇编语言中,dddb 是定义数据的伪指令:

  1. db (Define Byte):用于定义一个字节(8 位)数据,即分配 1 字节的存储空间。例如:

    asm复制代码db 0x12         ; 定义一个字节,值为 0x12
    db 'A'          ; 定义一个字节,ASCII 值为 'A' (即 0x41)
    
  2. dd (Define Double Word):用于定义一个双字(32 位)数据,即分配 4 字节的存储空间。在 32 位系统上,这通常用来表示一个整数。例如:

    asm复制代码dd 0x12345678   ; 定义一个双字,值为 0x12345678
    dd 42           ; 定义一个双字,整数值 42
    

看左边的地址C0,C4,C8,C9,CA是不是跳了好几个?

原来应该是db 24h 0 0 0 0 0 0 0(也就是dd 24h)

db24h 0 0 0 db 0 0 0 0

我们可以发现规律了是三个三个跳着的我们要的就是24h,0h,36h……

对着byte_6020C0按两次快捷键D就行了,提取数据可以用idapython

start_addr = 0x00000000006020C0
end_addr = 0x000000000060213B

list = []

for addr in range(start_addr, end_addr + 1, 4):
    # 读取每4个字节的内容
    value = idaapi.get_dword(addr)
    list.append(value)
print(list)
# [36, 0, 5, 54, 101, 7, 39, 38, 45, 1, 3, 0, 13, 86, 1, 3, 101, 3, 45, 22, 2, 21, 3, 101, 0, 41, 68, 68, 1, 68, 43]

解密代码:

enc = [36, 0, 5, 54, 101, 7, 39, 38, 45, 1, 3, 0, 13, 86, 1, 3, 101, 3, 45, 22, 2, 21, 3, 101, 0, 41, 68, 68, 1, 68, 43]

key = 'L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t'

for i in range(len(enc)):
    print(key[enc[i]],end='')

ALEXCTF{W3_L0v3_C_W1th_CL45535}