一、查壳
二、IDA分析
1 int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 2 { 3 DialogBoxParamA(hInstance, (LPCSTR)0x67, 0, DialogFunc, 0); 4 return 0; 5 }
关键函数为DialogFunc,进入该函数分析
1 BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4) 2 { 3 const char *v4; // esi 4 const char *v5; // edi 5 int v7; // [esp+8h] [ebp-20030h] 6 int v8; // [esp+Ch] [ebp-2002Ch] 7 int v9; // [esp+10h] [ebp-20028h] 8 int v10; // [esp+14h] [ebp-20024h] 9 int v11; // [esp+18h] [ebp-20020h] 10 int v12; // [esp+1Ch] [ebp-2001Ch] 11 int v13; // [esp+20h] [ebp-20018h] 12 int v14; // [esp+24h] [ebp-20014h] 13 int v15; // [esp+28h] [ebp-20010h] 14 int v16; // [esp+2Ch] [ebp-2000Ch] 15 int v17; // [esp+30h] [ebp-20008h] 16 CHAR String; // [esp+34h] [ebp-20004h] 17 char v19; // [esp+35h] [ebp-20003h] 18 char v20; // [esp+36h] [ebp-20002h] 19 char v21; // [esp+37h] [ebp-20001h] 20 char v22; // [esp+38h] [ebp-20000h] 21 char v23; // [esp+39h] [ebp-1FFFFh] 22 char v24; // [esp+3Ah] [ebp-1FFFEh] 23 char v25; // [esp+3Bh] [ebp-1FFFDh] 24 char v26; // [esp+10034h] [ebp-10004h] 25 char v27; // [esp+10035h] [ebp-10003h] 26 char v28; // [esp+10036h] [ebp-10002h] 27 28 if ( a2 == 272 ) 29 return 1; 30 if ( a2 != 273 ) 31 return 0; 32 if ( (_WORD)a3 == 1001 ) 33 { 34 memset(&String, 0, 0xFFFFu); 35 GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF); 36 if ( strlen(&String) == 8 ) 37 { 38 v7 = 90; 39 v8 = 74; 40 v9 = 83; 41 v10 = 69; 42 v11 = 67; 43 v12 = 97; 44 v13 = 78; 45 v14 = 72; 46 v15 = 51; 47 v16 = 110; 48 v17 = 103; 49 sub_4010F0((int)&v7, 0, 10); 50 memset(&v26, 0, 0xFFFFu); 51 v26 = v23; 52 v28 = v25; 53 v27 = v24; 54 v4 = sub_401000((int)&v26, strlen(&v26)); 55 memset(&v26, 0, 0xFFFFu); 56 v27 = v21; 57 v26 = v20; 58 v28 = v22; 59 v5 = sub_401000((int)&v26, strlen(&v26)); 60 if ( String == v7 + 34 61 && v19 == v11 62 && 4 * v20 - 141 == 3 * v9 63 && v21 / 4 == 2 * (v14 / 9) 64 && !strcmp(v4, "ak1w") 65 && !strcmp(v5, "V1Ax") ) 66 { 67 MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0); 68 } 69 } 70 return 0; 71 } 72 if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 ) 73 return 0; 74 EndDialog(hDlg, (unsigned __int16)a3); 75 return 1; 76 }
通过第36行代码知道String是我们输入的flag,长度应该是8。
第49行函数sub_4010F0在对v9~v19操作,进入sub_4010F0函数再次分析,把该函数的操作写成C,将数组代入后输出数值。基本上就是将该函数之间复制,再令其输出。
1 #include2 #include 3 #include 4 5 using namespace std; 6 7 int __cdecl sub_4010F0(char *a1, int a2, int a3) 8 { 9 int result; // eax 10 int i; // esi 11 int v5; // ecx 12 int v6; // edx 13 14 result = a3; 15 for (i = a2; i <= a3; a2 = i) 16 { 17 v5 = i; 18 v6 = a1[i]; 19 if (a2 < result && i < result) 20 { 21 do 22 { 23 if (v6 > a1[result]) 24 { 25 if (i >= result) 26 break; 27 ++i; 28 a1[v5] = a1[result]; 29 if (i >= result) 30 break; 31 while (a1[i] <= v6) 32 { 33 if (++i >= result) 34 goto LABEL_13; 35 } 36 if (i >= result) 37 break; 38 v5 = i; 39 a1[result] = a1[i]; 40 } 41 --result; 42 } while (i < result); 43 } 44 LABEL_13: 45 a1[result] = v6; 46 sub_4010F0(a1, a2, i - 1); 47 result = a3; 48 ++i; 49 } 50 return result; 51 } 52 int main(){ 53 char a[20] = {90, 74, 83, 69, 67, 97, 78, 72, 51, 110, 103}; 54 cout << a << endl; 55 sub_4010F0(a, 0, 10); 56 cout << a << endl; 57 return 0; 58 }
输出为:
第54、56行代码对v23、v25、v24 , v21、v20、v22的字符串进行了函数 sub_401000的操作
v23对应的是var_1FFFF,v25是var_1FFFD,v24是var_1FFFE
v21对应的是var_20001,v20对应的是var_20002,v22对应的是var_20000
进入sub_401000分析 这六个字符对应的是v2-v4,v5-v7
1 _BYTE *__cdecl sub_401000(int a1, int a2) 2 { 3 int v2; // eax 4 int v3; // esi 5 size_t v4; // ebx 6 _BYTE *v5; // eax 7 _BYTE *v6; // edi 8 int v7; // eax 9 _BYTE *v8; // ebx 10 int v9; // edi 11 signed int v10; // edx 12 int v11; // edi 13 signed int v12; // eax 14 signed int v13; // esi 15 _BYTE *result; // eax 16 _BYTE *v15; // [esp+Ch] [ebp-10h] 17 _BYTE *v16; // [esp+10h] [ebp-Ch] 18 int v17; // [esp+14h] [ebp-8h] 19 int v18; // [esp+18h] [ebp-4h] 20 21 v2 = a2 / 3; 22 v3 = 0; 23 if ( a2 % 3 > 0 ) 24 ++v2; 25 v4 = 4 * v2 + 1; 26 v5 = malloc(v4); 27 v6 = v5; 28 v15 = v5; 29 if ( !v5 ) 30 exit(0); 31 memset(v5, 0, v4); 32 v7 = a2; 33 v8 = v6; 34 v16 = v6; 35 if ( a2 > 0 ) 36 { 37 while ( 1 ) 38 { 39 v9 = 0; 40 v10 = 0; 41 v18 = 0; 42 do 43 { 44 if ( v3 >= v7 ) 45 break; 46 ++v10; 47 v9 = *(unsigned __int8 *)(v3++ + a1) | (v9 << 8); 48 } 49 while ( v10 < 3 ); 50 v11 = v9 << 8 * (3 - v10); 51 v12 = 0; 52 v17 = v3; 53 v13 = 18; 54 do 55 { 56 if ( v10 >= v12 ) 57 { 58 *((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F; 59 v8 = v16; 60 } 61 else 62 { 63 *((_BYTE *)&v18 + v12) = 64; 64 } 65 *v8++ = byte_407830[*((char *)&v18 + v12)]; 66 v13 -= 6; 67 ++v12; 68 v16 = v8; 69 } 70 while ( v13 > -6 ); 71 v3 = v17; 72 if ( v17 >= a2 ) 73 break; 74 v7 = a2; 75 } 76 v6 = v15; 77 } 78 result = v6; 79 *v8 = 0; 80 return result; 81 }
发现有 byte_407830数组,
.rdata:00407830 ; char byte_407830[] .rdata:00407830 byte_407830 db 41h ; DATA XREF: sub_401000+C0↑r .rdata:00407831 aBcdefghijklmno db 'BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',0
查看该数组认定该函数是在做base64加密
再结合正确flag的条件可知,v5,v6,v7 base64之后,等于'ak1w',v2,v3,v4加密之后等于'V1Ax'
分析正确flag的条件
if ( String == v7 + 34 //String == '3'+34 为'U'
&& v19 == v11 //v11为‘J’
&& 4 * v20 - 141 == 3 * v9 && v21 / 4 == 2 * (v14 / 9) //('E'*3+141)/4 为'W'
&& !strcmp(v4, "ak1w") //'ak1w'解码为jMp
&& !strcmp(v5, "V1Ax") ) //'V1Ax'解码为WP1
拼一下即
三、flag
flag{UJWP1jMp}