简单游戏逆向

题目简介

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+31j
.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

也就是这样

image

然后直接运行等一会就会给flag

image

flag

no5c30416d6cf52638460377995c6a8cf5