Test file: https://adworld.xctf.org.cn/media/task/attachments/c5802869b8a24033b4a80783a67c858b
1. Prepare
getting information
- 64 files
2.IDA Open
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. Code Analysis
In fact, this pile of code, much of "junk code '- does not need our attention
We need to focus on only 26 lines of code to the following sections
The first 27 lines of code, is a for loop, there is no end condition, each increase sub_400D7A (& i), i.e., 1 byte
_QWORD *__fastcall sub_400D7A(_QWORD *a1) { ++*a1; return a1; }
for (I = STD :: :: __ cxx11 the basic_string < char , char_traits STD :: < char >, the allocator STD :: < char >> :: the begin (& V11);; sub_400D7A (& I)) { V13 = STD :: the basic_string :: __cxx11 < char , char_traits STD :: < char >, the allocator STD :: < char >> :: End (& V11); IF (! sub_400D3D ((__ Int64) & I, (the __int64) & V13)) // cycle end condition BREAK ; v8 = (_BYTE *) sub_400D9A ((__ int64) & i); // some kind of assignment IF (* = v8 off_6020A0 [dword_6020C0 [V14]]!) // Key! Here it is actually an array of sets of the array sub_400B56 (& I, & V13); ++ V14; // array subscript }
3.1 conditions to find flag
By contrast sub_400B56 (& i, & v13); and sub_400B73 (& i, & v13); function, we can get the actual hidden flag if the judge conditions
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); }
Enter off_6020A0 and we can see 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
This is in fact a string
.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
Here is the equivalent of a series of integer
Therefore, we can analyze the results, by v15 / v14 array as an internal standard, and then the cycle is eligible to an integer array is used as the external standard, to obtain the desired string.
It is worth to note is, algn 8 8 represents an interval between the two numbers, corresponding to the number of interpolation between two seven zero, there is also equivalent to a '0' between the first two numbers
4. The script gets the 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}