GFSJ0418-【gametime】
简单游戏逆向
题目简介
Premise - A game that requires a user to type either space ('s'), 'm' or 'x' when prompted. If they are fast enough, they get the key. Warnings - Everything should be statically compiled. I tested on two different Win8.1 VMs with no problem. If someone gets DLL loading errors, they most likely need to download Microsoft's Visual C Runtime Library.
能看到是一个游戏输入空格或者mx 通关就给flag
我们去查看 其实这类游戏有一个简单的方法 就是找失败点 我整局游戏都不会失败 那我肯定就会通关 尤其是游戏没有加其他东西的时候
main函数 这个是我经过简单命名的 main函数 能看到有两处失败点
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edi
unsigned int v4; // eax
void (__stdcall *v5)(DWORD); // ebx
int v6; // esi
int v7; // esi
int v8; // esi
int v9; // esi
int v10; // esi
int i; // edi
int v12; // esi
_WORD *v13; // esi
int v14; // ebx
int v15; // esi
int v16; // eax
int v17; // esi
int v18; // eax
char v19; // cl
int v20; // eax
int v22; // [esp+10h] [ebp-20h]
char v23; // [esp+1Bh] [ebp-15h]
_WORD v24[3]; // [esp+1Ch] [ebp-14h] BYREF
int v25; // [esp+22h] [ebp-Eh]
int v26; // [esp+26h] [ebp-Ah]
__int16 v27; // [esp+2Ah] [ebp-6h]
strcpy((char *)v24, " ");
*(_DWORD *)&v24[1] = 0;
v25 = 0;
v26 = 0;
v27 = 0;
v3 = 0;
v22 = 0;
printf("\r\tZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\r\tZOMGZOMG ZOMGZOMG\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\r\tZOMGZOMG TAP TAP REVOLUTION!!!!!!! ZOMGZOMG\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\r\tZOMGZOMG ZOMGZOMG\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\r\tZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n\n\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\r\t R U READDY?!\n\n\n");
printf("\tkey is %s (%s)");
printf_s();
printf("\rThe game is starting in...\n");
v4 = _time64(nullptr);
srand(v4);
printf_d();
printf_play(0xC8u);
if ( !error(32, 0x1F4u, 10) )
return 0;
if ( !error(120, 0x12Cu, 8) )
return 0;
if ( !error(109, 0x12Cu, 5) )
return 0;
printf("key is %s (%s)");
printf("\rTRAINING COMPLETE! \n");
v5 = Sleep;
v6 = 20;
do
{
Sleep(0xC8u);
printf("\n");
--v6;
}
while ( v6 );
printf("key is %s (%s)");
printf("\rNow you know everything you need to know");
v7 = 4;
do
{
printf(".");
Sleep(0x3E8u);
--v7;
}
while ( v7 );
printf("\n\n\nfor the rest of your life!\n");
v8 = 20;
do
{
Sleep(0xC8u);
printf("\n");
--v8;
}
while ( v8 );
printf("LETS PLAY !\n");
v9 = 20;
do
{
Sleep(0xC8u);
printf("\n");
--v9;
}
while ( v9 );
printf_d();
printf_play(0x64u);
if ( !error_0(32, 5, 0xC8u) )
return 0;
if ( !error_0(120, 2, 0xC8u) )
return 0;
if ( !error_0(109, 1, 0xC8u) )
return 0;
printf("key is %s (%s)");
printf_s();
printf("\rooooh, you fancy!!!\n");
if ( !error_0(109, 5, 0xC8u) || !error_0(120, 2, 0xC8u) || !error_0(32, 1, 0xC8u) )
return 0;
printf("key is %s (%s)");
printf("\b\b");
printf("NIIICE JOB)!!!!\n");
v10 = 20;
do
{
Sleep(0x32u);
printf("\n");
--v10;
}
while ( v10 );
v23 = 1;
do
{
if ( v3 % 3 == 1 )
{
printf("key is %s (%s)");
printf_s();
printf("\rTURBO TIME! \n");
for ( i = 0; i < 20; ++i )
{
v5(0x32u);
printf("\n");
if ( i == 19 )
{
v12 = sub_40141D();
sub_401D02(v24, v12 - 5514);
dword_41A1F8 = (int)v24;
dword_41A1FC = v12 - 5498;
sub_401AA5();
sub_401CC9();
printf("key is %s (%s)");
printf("\b\b");
v13 = v24;
v14 = 16;
do
{
printf("%02x");
v13 = (_WORD *)((char *)v13 + 1);
--v14;
}
while ( v14 );
printf(")\n\n");
v5 = Sleep;
}
}
v15 = 0;
while ( 1 )
{
v16 = rand();
if ( !error_0(byte_417B08[v16 % 3], 1, 0x64u) )
break;
if ( ++v15 >= 10 )
goto LABEL_33;
}
v23 = 0;
LABEL_33:
v3 = v22;
}
v17 = 0;
while ( 1 )
{
v18 = rand();
v19 = v23;
v20 = v18 % 3;
if ( v23 )
break;
LABEL_38:
if ( ++v17 >= 10 )
goto LABEL_41;
}
if ( error_0(byte_417B08[v20], v20 + 3, 0x64u) )
{
v19 = v23;
goto LABEL_38;
}
v19 = 0;
v23 = 0;
LABEL_41:
if ( v3 == 1337 )
{
sub_4012F6();
v19 = v23;
}
v22 = ++v3;
}
while ( v19 );
return 0;
}
一处
char __fastcall error(int a1, DWORD a2, int a3)
{
int v5; // edi
printf("key is %s (%s)");
printf_s();
printf("\rZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n");
if ( a1 == 32 )
printf("\nWhen you see an 's', press the space bar\n\n");
else
printf("\nWhen you see an '%c', press the '%c' key\n\n");
printf("key is %s (%s)");
printf_s();
printf("\rZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n");
printf_play(a2);
v5 = a3;
if ( a3 > 0 )
{
do
{
printf(".");
Sleep(0xC8u);
--v5;
}
while ( v5 );
}
if ( (unsigned __int8)sub_401260(a1, 100000) )
return 1;
printf("key is %s (%s)\r");
printf_s();
printf("\rUDDER FAILURE! http://imgur.com/4Ajx21P \n");
return 0;
}
另一处
char __fastcall error_0(int a1, int a2, DWORD dwMilliseconds)
{
printf("key is %s (%s)");
printf_s();
printf("\r \r");
if ( a2 > 0 )
{
do
{
printf(".");
Sleep(dwMilliseconds);
--a2;
}
while ( a2 );
}
if ( (unsigned __int8)sub_401260(a1, 500 * dwMilliseconds) )
return 1;
printf("key is %s (%s)\r");
printf("UDDER FAILURE! http://imgur.com/4Ajx21P \n");
return 0;
}
然后查看汇编 能看到有一个jnz 那改成jz 不就行了 这样就不会失败了
.text:00401551 loc_401551: ; CODE XREF: error_0+31↑j
.text:00401551 imul edx, edi, 1F4h
.text:00401557 mov ecx, ebx
.text:00401559 call sub_401260
.text:0040155E pop edi
.text:0040155F pop esi
.text:00401560 pop ebx
.text:00401561 test al, al
.text:00401563 jnz short loc_401586
.text:00401565 push [ebp+arg_4]
.text:00401568 push [ebp+arg_8]
.text:0040156B push offset aKeyIsSS_1 ; "key is %s (%s)\r"
.text:00401570 call printf
.text:00401575 push offset aUdderFailureHt_0 ; "UDDER FAILURE! http://imgur.com/4Ajx21P"...
.text:0040157A call printf
.text:0040157F add esp, 10h
.text:00401582 xor al, al
.text:00401584 pop ebp
.text:00401585 retn
也就是这样
然后直接运行等一会就会给flag
flag
no5c30416d6cf52638460377995c6a8cf5
评论