-
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!}