攻防世界--re2-cpp-is-awesome
测试文件:https://adworld.xctf.org.cn/media/task/attachments/c5802869b8a24033b4a80783a67c858b
1.准备
获取信息
- 64位文件
2.IDA打开
1 __int64 __fastcall main(int a1, char **a2, char **a3) 2 { 3 char *v3; // rbx 4 __int64 v4; // rax 5 __int64 v5; // rdx 6 __int64 v6; // rax 7 __int64 v7; // rdx 8 _BYTE *v8; // rax 9 __int64 i; // [rsp+10h] [rbp-60h] 10 char v11; // [rsp+20h] [rbp-50h] 11 char v12; // [rsp+4Fh] [rbp-21h] 12 __int64 v13; // [rsp+50h] [rbp-20h] 13 int v14; // [rsp+5Ch] [rbp-14h] 14 15 if ( a1 != 2 ) 16 { 17 v3 = *a2; 18 v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Usage: ", a3); 19 v6 = std::operator<<<std::char_traits<char>>(v4, v3, v5); 20 std::operator<<<std::char_traits<char>>(v6, " flag\n", v7); 21 exit(0); 22 } 23 std::allocator<char>::allocator(&v12, a2, a3); 24 std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v11, a2[1], &v12); 25 std::allocator<char>::~allocator(&v12); 26 v14 = 0; 27 for ( i = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::begin(&v11); ; sub_400D7A(&i) ) 28 { 29 v13 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::end(&v11); 30 if ( !(unsigned __int8)sub_400D3D(&i, &v13) ) 31 break; 32 v8 = (_BYTE *)sub_400D9A(&i); 33 if ( *v8 != off_6020A0[dword_6020C0[v14]] ) 34 sub_400B56(); 35 ++v14; 36 } 37 sub_400B73(); 38 std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v11); 39 return 0LL; 40 }
3.代码分析
实际上这堆代码,很大部分“垃圾代码”--不需要我们关注的
我们只需要关注26行代码以下部分即可
第27行代码,是一个for循环,没有结束条件,每次增加sub_400D7A(&i),即1字节
_QWORD *__fastcall sub_400D7A(_QWORD *a1) { ++*a1; return a1; }
for ( i = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::begin(&v11); ; sub_400D7A(&i) ) { v13 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::end(&v11); if ( !sub_400D3D((__int64)&i, (__int64)&v13) )// 循环结束条件 break; v8 = (_BYTE *)sub_400D9A((__int64)&i); // 进行某种赋值 if ( *v8 != off_6020A0[dword_6020C0[v14]] ) // 重点!这里实际上就是一个数组套着数组 sub_400B56(&i, &v13); ++v14; // 数组下标 }
3.1条件中找flag
通过对比sub_400B56(&i, &v13);和 sub_400B73(&i, &v13);函数,我们能够得到flag实际藏在if判断条件中
void __fastcall __noreturn sub_400B56(__int64 a1, __int64 a2, __int64 a3) { std::operator<<<std::char_traits<char>>(&std::cout, "Better luck next time\n", a3); exit(0); }
__int64 __fastcall sub_400B73(__int64 a1, __int64 a2, __int64 a3) { return std::operator<<<std::char_traits<char>>(&std::cout, "You should have the flag by now\n", a3); }
进入off_6020A0和dword_6020C0我们可以看到
.data:00000000006020A0 off_6020A0 dq offset aL3tMeT3llY0uS0 .data:00000000006020A0 ; DATA XREF: main+D1↑r .data:00000000006020A0 ; "L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{"... .data:00000000006020A8 align 20h
.rodata:0000000000400E58 aL3tMeT3llY0uS0 db 'L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t' .rodata:0000000000400E58 ; DATA XREF: .data:off_6020A0↓o
这实际上就是一段字符串
.data:00000000006020C0 dword_6020C0 dd 24h ; DATA XREF: main+DD↑r .data:00000000006020C4 align 8 .data:00000000006020C8 db 5 .data:00000000006020C9 db 0 .data:00000000006020CA db 0 .data:00000000006020CB db 0 .data:00000000006020CC db 36h ; 6 .data:00000000006020CD db 0 .data:00000000006020CE db 0 .data:00000000006020CF db 0 .data:00000000006020D0 db 65h ; e .data:00000000006020D1 db 0 .data:00000000006020D2 db 0 .data:00000000006020D3 db 0 .data:00000000006020D4 db 7 .data:00000000006020D5 db 0 .data:00000000006020D6 db 0 .data:00000000006020D7 db 0 .data:00000000006020D8 db 27h ; ' .data:00000000006020D9 db 0 .data:00000000006020DA db 0 .data:00000000006020DB db 0 .data:00000000006020DC db 26h ; & .data:00000000006020DD db 0 .data:00000000006020DE db 0 .data:00000000006020DF db 0 .data:00000000006020E0 db 2Dh ; - .data:00000000006020E1 db 0 .data:00000000006020E2 db 0 .data:00000000006020E3 db 0 .data:00000000006020E4 db 1 .data:00000000006020E5 db 0 .data:00000000006020E6 db 0 .data:00000000006020E7 db 0 .data:00000000006020E8 db 3 .data:00000000006020E9 db 0 .data:00000000006020EA db 0 .data:00000000006020EB db 0 .data:00000000006020EC db 0 .data:00000000006020ED db 0 .data:00000000006020EE db 0 .data:00000000006020EF db 0 .data:00000000006020F0 db 0Dh .data:00000000006020F1 db 0 .data:00000000006020F2 db 0 .data:00000000006020F3 db 0 .data:00000000006020F4 db 56h ; V .data:00000000006020F5 db 0 .data:00000000006020F6 db 0 .data:00000000006020F7 db 0 .data:00000000006020F8 db 1 .data:00000000006020F9 db 0 .data:00000000006020FA db 0 .data:00000000006020FB db 0 .data:00000000006020FC db 3 .data:00000000006020FD db 0 .data:00000000006020FE db 0 .data:00000000006020FF db 0 .data:0000000000602100 db 65h ; e .data:0000000000602101 db 0 .data:0000000000602102 db 0 .data:0000000000602103 db 0 .data:0000000000602104 db 3 .data:0000000000602105 db 0 .data:0000000000602106 db 0 .data:0000000000602107 db 0 .data:0000000000602108 db 2Dh ; - .data:0000000000602109 db 0 .data:000000000060210A db 0 .data:000000000060210B db 0 .data:000000000060210C db 16h .data:000000000060210D db 0 .data:000000000060210E db 0 .data:000000000060210F db 0 .data:0000000000602110 db 2 .data:0000000000602111 db 0 .data:0000000000602112 db 0 .data:0000000000602113 db 0 .data:0000000000602114 db 15h .data:0000000000602115 db 0 .data:0000000000602116 db 0 .data:0000000000602117 db 0 .data:0000000000602118 db 3 .data:0000000000602119 db 0 .data:000000000060211A db 0 .data:000000000060211B db 0 .data:000000000060211C db 65h ; e .data:000000000060211D db 0 .data:000000000060211E db 0 .data:000000000060211F db 0 .data:0000000000602120 db 0 .data:0000000000602121 db 0 .data:0000000000602122 db 0 .data:0000000000602123 db 0 .data:0000000000602124 db 29h ; ) .data:0000000000602125 db 0 .data:0000000000602126 db 0 .data:0000000000602127 db 0 .data:0000000000602128 db 44h ; D .data:0000000000602129 db 0 .data:000000000060212A db 0 .data:000000000060212B db 0 .data:000000000060212C db 44h ; D .data:000000000060212D db 0 .data:000000000060212E db 0 .data:000000000060212F db 0 .data:0000000000602130 db 1 .data:0000000000602131 db 0 .data:0000000000602132 db 0 .data:0000000000602133 db 0 .data:0000000000602134 db 44h ; D .data:0000000000602135 db 0 .data:0000000000602136 db 0 .data:0000000000602137 db 0 .data:0000000000602138 db 2Bh ; + .data:0000000000602139 db 0 .data:000000000060213A db 0 .data:000000000060213B db 0 .data:000000000060213B _data ends
这里就相当于是一连串的整数
因此我们可以分析得出,通过v15/v14作为内部数组下标,循环获到的整数再作为外部数组的下标,获取到需要的字符串。
这里值得注意的一点是,algn 8表示两个数之间间隔8位,相当于在两个数之间插了7个0,也就相当于在头两个数之间还有一个'0'
4.脚本获取flag
S = 'L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_' N = [0x24,0x0,0x5,0x36,0x65,0x7,0x27,0x26,0x2d,0x1,0x3,0x0,0x0d,0x56,0x1,0x3,0x65,0x3,0x2d,0x16,0x2,0x15,0x3,0x65,0x0,0x29,0x44,0x44,0x1,0x44,0x2b] x = '' for i in N: x += S[i] print(x)
5.get flag!
ALEXCTF{W3_L0v3_C_W1th_CL45535}