[DASCTF Sept 2021]pig_brain_king


  1. IDA打開之后按下Shift + F12找到字符串

    image

    定位到之后找到下面的cls,這是系統清屏指令。定位這個指令(原因是程序里執行了這個指令(易知))

    image

    看到了大規模的變量賦值指令。但是仔細看就會發現都是在變量v281中取值,因而只需要寫個基本的字典序翻譯程序

  2. 字典序翻譯
    很容易看出來這是一個字典打印程序。這里對字典的序列進行了打印,而各個數組的值對應:

    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();
    }
    
  3. 根據偽代碼第603行的

    //..
          sub_4114BF(v266, v268);
        }
        Sleep(0xBB8u);
        system("cls");
      }
    

    估計程序中出現了Sleep延時。修改這段代碼去掉延時。定位到相應的匯編代碼:
    image

    將相應的硬編碼改掉,也就是改成

    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;
    

    對應的硬編碼
    image

    改為

    jnz loc_41EA40
    

    即(jnz的硬編碼是85)

    DD80h:

    0F 85 BA 00 00 00 8B F4 68 F0 15 41 00 B8 01 00
    
  4. 發現在答完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
    

    image

  5. 最終輸入1000行隨機字符得到flag:

    輸入方法:在notepad里輸入任意字符復制粘貼1000行,然后粘貼到控制台里就行

    image

  6. flag{YOU_ar3_The_k1ng_Of_pig_bra1n!}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM