題目:

通過題目我們可以知道,我們能成功輸入的值就是我們的flag
下載附件后,發現是一個可執行的文件,執行一下,發現:

輸入值后,直接閃退啦!查殼發現無殼后拖入IDA(32bit)內,f5反編譯進入主函數,發現

DialogBoxParamA函數里的DialogFunc參數就很像網絡編程中基於消息的WSAAsyncSelect模型里的消息處理函數,點進去后發現
if ( (_WORD)a3 == 1001 ) { memset(&String, 0, 0xFFFFu); GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);#這里要輸入字符串 if ( strlen(&String) == 8 )#長度為八 { v7 = 90; v8 = 74; v9 = 83; v10 = 69; v11 = 67; v12 = 97; v13 = 78; v14 = 72; v15 = 51; v16 = 110; v17 = 103; sub_4010F0(&v7, 0, 10);#這里對v7字符串進行了處理 memset(&v26, 0, 0xFFFFu); v26 = v23; v28 = v25; v27 = v24; v4 = (const char *)sub_401000(&v26, strlen(&v26));#這里可以推出以v23為首地址的字符串(長度為3) memset(&v26, 0, 0xFFFFu); v27 = v21; v26 = v20; v28 = v22; v5 = (const char *)sub_401000(&v26, strlen(&v26));#這里可以推出以v20為首地址的字符串(長度為3) if ( String == v7 + 34 && v19 == v11 && 4 * v20 - 141 == 3 * v9 && v21 / 4 == 2 * (v14 / 9) && !strcmp(v4, "ak1w") && !strcmp(v5, "V1Ax") ) { MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0); } } return 0; } if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 ) return 0; EndDialog(hDlg, (unsigned __int16)a3);
通過大概的分析程序,我們可以發現,我們輸入的字符串的長度為8字節,通過點進去v19、v20,發現v18處地址對應的就是我們輸入字符串的首地址,v19、v20、...v25處地址就分別是字符串每個字符的地址

所以,我們只需把每個對應的字符逆推出來,那么也就得到了我們的flag啦。
開始逆推:
首先我們知道從v7至v17這11個變量的值,往后碰到 sub_4010F0(&v7, 0, 10)函數,點進去發現有對以v7為首地址的字符進行了處理,直接粘貼,用C語言解出處理后對應的值
#include<stdio.h> #include<iostream> using namespace std; int sub(char a1[], int a2, int a3) { int result; // eax int i; // esi int v5; // ecx int v6; // edx result = a3; for ( i = a2; i <= a3; a2 = i ) { v5 = i; //v6 = *(DWORD *)(4 * i + a1); v6 = a1[i]; if ( a2 < result && i < result ) { do { //if ( v6 > *(DWORD *)(a1 + 4 * result) ) if ( v6 > a1[result] ) { if ( i >= result ) break; ++i; //*(DWORD *)(v5 + a1) = *(DWORD *)(a1 + 4 * result); a1[v5] = a1[result]; if ( i >= result ) break; //while ( *(DWORD *)(a1 + 4 * i) <= v6 ) while ( a1[i] <= v6 ) { if ( ++i >= result ) goto LABEL_13; } if ( i >= result ) break; v5 = i; //*(DWORD *)(a1 + 4 * result) = *(DWORD *)(4 * i + a1); a1[result] = a1[i]; } --result; } while ( i < result ); } LABEL_13: //*(DWORD *)(a1 + 4 * result) = v6; a1[result]= v6; sub(a1, a2, i - 1); result = a3; ++i; } return result; } int main() { char a[11]={90,74,83,69,67,97,78,72,51,110,103}; cout<<">>>>sub"<<endl; sub(a,0,10); for (int i=0;i<11;i++) { cout<<"a["<<i+7<<"]"<<a[i]<<" "<<int(a[i])<<endl; //cout<<a[i]<<" "; } }
運行結果為:

繼續往下推,發現有 v4 = (const char *)sub_401000(&v26, strlen(&v26));和v5 = (const char *)sub_401000(&v26, strlen(&v26));點進去sub_401000發現(圖沒截全)

點進去byte_407830發現

可知,結果是經過base64編碼得到的。
然后,我們繼續往后推
if ( String == v7 + 34 && v19 == v11 && 4 * v20 - 141 == 3 * v9 && v21 / 4 == 2 * (v14 / 9) && !strcmp(v4, "ak1w") && !strcmp(v5, "V1Ax") ) { MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0); }
通過這里,我們知道
string(v18)=v7+34=51+34=86='U'
V19='J'
v20='W'
v21='P'
又因為v4='ak1w',v5='V1Ax',通過base64解碼分別得,v4='jMp',v5='WP1',因此可知,v20='W',v21='P',v22='1'(v5);v23='j',v24='M',v25='p'(v4)
這樣我們就得到我們的flag啦!!!即flag{UJWP1jMp}
