-
IDA打開之后按下
Shift + F12
找到字符串定位到之后找到下面的
cls
,這是系統清屏指令。定位這個指令(原因是程序里執行了這個指令(易知))看到了大規模的變量賦值指令。但是仔細看就會發現都是在變量
v281
中取值,因而只需要寫個基本的字典序翻譯程序 -
字典序翻譯
很容易看出來這是一個字典打印程序。這里對字典的序列進行了打印,而各個數組的值對應:whoisthestrongestpigbrainking?! canyouanswer1000questionscorrectly? nowstartdoingthequestions! pleaseenter nonono bingo! theansweris
所對應的值和對應行如下
//... sub_411154(); v282 = 0; v259 = v281[67]; // whoisthestrongestpigbrainking?! v252 = v281[66]; //... std::ostream::operator<<(v39, sub_4115F0); v260 = v281[66]; // canyouanswer1000questionscorrectly? v253 = v281[50]; //... while ( 1 ) { v261 = v281[67]; // nowstartdoingthequestions! v254 = v281[44]; //... if ( i >= 3 ) goto LABEL_10; v262 = v281[43]; // pleaseenter v255 = v281[30]; //... if ( v273 ) break; v264 = v281[40]; // nonono v257 = v281[39]; v251 = v281[40]; //... std::ostream::operator<<(v133, sub_4115F0); } v263 = v281[67]; // bingo! v256 = v281[40]; v250 = v281[32]; //... LABEL_10: *v278 = v277; if ( v277 ) { ++v280; } else { v265 = v281[44]; // theansweris v258 = v281[34]; v245 = v281[43]; //...
找到
theansweris
,else { v265 = v279[44]; v258 = v279[34]; v245 = v279[43]; v238 = v279[30]; v231 = v279[48]; v227 = v279[44]; v223 = v279[39]; v218 = v279[26]; v209 = v279[30]; v206 = v279[33]; v134 = sub_41121C(std::cout, v279[19]); v135 = sub_41121C(v134, v206); v136 = sub_41121C(v135, v209); v137 = sub_411474(v136, " "); v138 = sub_41121C(v137, v218); v139 = sub_41121C(v138, v223); v140 = sub_41121C(v139, v227); v141 = sub_41121C(v140, v231); v142 = sub_41121C(v141, v238); v143 = sub_41121C(v142, v245); v144 = sub_411474(v143, " "); v145 = sub_41121C(v144, v258); v146 = sub_41121C(v145, v265); sub_411474(v146, ":"); sub_4114BF(v266, v267); } Sleep(0); system("cls"); }
找到關鍵函數
int __thiscall sub_41CAE0(HANDLE *this) { //defs... struct _CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; // [esp+124h] [ebp-38h] BYREF HANDLE *v90; // [esp+144h] [ebp-18h] int v91; // [esp+158h] [ebp-4h] v90 = this; __CheckForDebuggerJustMyCode(&unk_42F035); GetConsoleScreenBufferInfo(v90[64], &ConsoleScreenBufferInfo); *((_WORD *)v90 + 136) = ConsoleScreenBufferInfo.dwCursorPosition.X; *((_WORD *)v90 + 137) = ConsoleScreenBufferInfo.dwCursorPosition.Y; if ( *((double *)v90 + 33) > 3330.0 ) { sub_4110AA(&unk_428DD6); v91 = 0; sub_411442(v88); v91 = -1; sub_411528(); //some output.... } v86 = sub_41146F(v87); v91 = 1; v56 = sub_4114AB(std::cout, v86); std::ostream::operator<<(v56); v91 = -1; return sub_411528(); }
-
根據偽代碼第603行的
//.. sub_4114BF(v266, v268); } Sleep(0xBB8u); system("cls"); }
估計程序中出現了
Sleep
延時。修改這段代碼去掉延時。定位到相應的匯編代碼:
將相應的硬編碼改掉,也就是改成
push 00000000h
換句話說
68 00 00 00 00
同理,修正下述位置:
D870h(FOA,下同)
FF FF 8B F4 68 00 00 00 00 FF 15 04 D0 42 00 3B
DBB0h
2D FF FF 8B F4 68 00 00 00 00 FF 15 04 D0 42 00
E040h
FF E8 79 28 FF FF 8B F4 68 00 00 00 00 FF 15 04
然后更改判斷的代碼,即第541行偽代碼
if ( v273 ) break;
對應的硬編碼
改為
jnz loc_41EA40
即(jnz的硬編碼是85)
DD80h:
0F 85 BA 00 00 00 8B F4 68 F0 15 41 00 B8 01 00
-
發現在答完1000道題之后仍然沒有flag,找到
*
號修改為0即可int __thiscall sub_41ADE0(char *this) { unsigned int v1; // eax int v2; // eax int v3; // eax int v5; // [esp-8h] [ebp-158h] int v6; // [esp-4h] [ebp-154h] int v7; // [esp+0h] [ebp-150h] int v8; // [esp+0h] [ebp-150h] int v9; // [esp+0h] [ebp-150h] int v10; // [esp+4h] [ebp-14Ch] int v11; // [esp+4h] [ebp-14Ch] char v12[36]; // [esp+1Ch] [ebp-134h] BYREF char v13[39]; // [esp+40h] [ebp-110h] BYREF bool v14; // [esp+67h] [ebp-E9h] unsigned int i; // [esp+130h] [ebp-20h] char *v16; // [esp+13Ch] [ebp-14h] int v17; // [esp+14Ch] [ebp-4h] v16 = this; __CheckForDebuggerJustMyCode(&unk_42F035); SetConsoleCursorPosition(*((HANDLE *)v16 + 64), *(COORD *)(v16 + 272)); for ( i = 0; ; ++i ) { sub_41146F(v13); v1 = sub_41118B(v7, v10); v14 = i < v1; sub_411528(v8, v11); if ( !v14 ) break; sub_411474(std::cout, "*"); } sub_41146F(v12); v17 = 0; v5 = sub_41118B(sub_4115F0, v7); v2 = sub_411474(std::cout, " "); v3 = std::ostream::operator<<(v2, v5, v6); std::ostream::operator<<(v3); v17 = -1; return sub_411528(v9, v10); }
對
sub_411474(std::cout, "*");
對應的硬編碼進行修正:
.rdata:00428DD4 ; const char Str[] .rdata:00428DD4 2A 00 Str db '*',0 ; DATA XREF: sub_41ADE0+E1↑o .rdata:00428DD6 00 unk_428DD6 db 0
-
最終輸入1000行隨機字符得到flag:
輸入方法:在notepad里輸入任意字符復制粘貼1000行,然后粘貼到控制台里就行
-
flag{YOU_ar3_The_k1ng_Of_pig_bra1n!}