JCTF 2014 小菜兩碟

測試文件:https://static2.ichunqiu.com/icq/resources/fileupload//CTF/JCTF2014/re200函數

 

參考文章:https://blog.csdn.net/chenlycly/article/details/53378196測試

 

1.程序分析

 

 

檢測時發現不是PE文件,可是打開16進制卻發現了MZ標識,所以咱們可以判斷文件中存在錯誤。spa

 

1.1 第一處錯誤

經過觀察,發現指向PE文件頭的地址爲E9,可是實際的地址倒是E8。.net

 

1.2 第二處錯誤

將地址修改正確以後,在010Editor打開文件,導入EXE模板code

能夠看到,正確的PE文件標識應該是0x00004550,可是文件中是0x00FF4550,修改FF爲00blog

 

將修改後的文件保存爲EXE文件遊戲

 

2.IDA打開

定位到main函數ci

  1 __int64 __cdecl main_0()
  2 {
  3   int v0; // eax
  4   __int64 v1; // rax
  5   int v2; // eax
  6   int v3; // ST08_4
  7   int v4; // eax
  8   int v5; // eax
  9   int v6; // eax
 10   int v7; // eax
 11   int v8; // eax
 12   int v9; // eax
 13   int v11; // [esp-10h] [ebp-170h]
 14   int v12; // [esp-Ch] [ebp-16Ch]
 15   char *v13; // [esp-8h] [ebp-168h]
 16   int v14; // [esp-4h] [ebp-164h]
 17   int *v15; // [esp+Ch] [ebp-154h]
 18   int k; // [esp+D4h] [ebp-8Ch]
 19   int j; // [esp+E0h] [ebp-80h]
 20   int i; // [esp+ECh] [ebp-74h]
 21   char v19; // [esp+FBh] [ebp-65h]
 22   int v20; // [esp+104h] [ebp-5Ch]
 23   int Dst; // [esp+108h] [ebp-58h]
 24   int v22; // [esp+10Ch] [ebp-54h]
 25   int v23; // [esp+110h] [ebp-50h]
 26   int v24; // [esp+114h] [ebp-4Ch]
 27   int v25; // [esp+118h] [ebp-48h]
 28   char Str1; // [esp+14Ch] [ebp-14h]
 29   int v27; // [esp+14Dh] [ebp-13h]
 30   int v28; // [esp+151h] [ebp-Fh]
 31   char v29; // [esp+155h] [ebp-Bh]
 32 
 33   v0 = sub_411154(std::cout, "歡迎來到數字遊戲 請輸入9個數字");
 34   std::basic_ostream<char,std::char_traits<char>>::operator<<(v0, std::endl);
 35   Str1 = 0;
 36   v27 = 0;
 37   v28 = 0;
 38   v29 = 0;
 39   v20 = 0;
 40   j_memset(&Dst, 0, 0x3Cu);
 41   for ( i = 0; i < 9; ++i )
 42     std::basic_istream<char,std::char_traits<char>>::operator>>(std::cin, &v20 + i);// v20中輸入9個數字
 43   if ( v22 * Dst * v20 / 11 != 106 )            // 須要知足條件1
 44     goto LABEL_31;
 45   if ( (Dst ^ v20) != v22 - 4 )                 // 須要知足條件2
 46     goto LABEL_31;
 47   HIDWORD(v1) = (v22 + Dst + v20) % 100;        // v1的計算表達式,反向推倒,須要知足條件3
 48   if ( HIDWORD(v1) != 34 )                      // v1 = 34
 49     goto LABEL_31;
 50   if ( v23 == 80 )                              // v23=80
 51   {
 52     for ( j = 0; j < 3; ++j )
 53     {
 54       HIDWORD(v1) = (j + 1) % 3;
 55       for ( *(&Str1 + j) = *((_BYTE *)&v20 + 4 * HIDWORD(v1)) + *(&v20 + j % 3); ; *(&Str1 + j) /= 2 )
 56       {
 57         while ( *(&Str1 + j) < 33 )
 58         {
 59           HIDWORD(v1) = j;
 60           *(&Str1 + j) *= 2;
 61         }
 62         if ( *(&Str1 + j) <= 126 )
 63           break;
 64         v1 = *(&Str1 + j);
 65       }
 66     }
 67     if ( v24 == 94 && v25 == 98 )               // v24=94,v25=98
 68     {
 69       for ( k = 3; k < 9; ++k )
 70       {
 71         for ( *(&Str1 + k) = *(&Str1 + (k + 1) % 3) + *(&Str1 + k % 3); ; *(&Str1 + k) /= 2 )
 72         {
 73           while ( *(&Str1 + k) < 33 )
 74             *(&Str1 + k) *= 2;
 75           if ( *(&Str1 + k) <= 126 )
 76             break;
 77         }
 78       }
 79       if ( !j_strcmp(&Str1, "*&8P^bP^b") )
 80       {
 81         v2 = sub_411154(std::cout, "success!");
 82         std::basic_ostream<char,std::char_traits<char>>::operator<<(v2, std::endl);
 83         v14 = std::endl;                        // 換行
 84         v13 = "abc}";
 85         v12 = v22;
 86         v11 = Dst;
 87         v3 = v20;
 88         v15 = &v11;
 89         v4 = sub_411154(std::cout, "jlflag{");
 90         v5 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v4, v3);
 91         v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, v11);
 92         v7 = std::basic_ostream<char,std::char_traits<char>>::operator<<(v6, v12);
 93         v8 = sub_411154(v7, v13);
 94         std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, v14);// 以上輸出的組合爲v4 v3 v11 v12 v13 v14
 95         sub_4112D0(std::cin, &v19);
 96         goto LABEL_32;
 97       }
 98 LABEL_31:
 99       v9 = sub_411154(std::cout, "please try again!");
100       std::basic_ostream<char,std::char_traits<char>>::operator<<(v9, std::endl);
101       goto LABEL_32;
102     }
103   }
104 LABEL_32:
105   v14 = HIDWORD(v1);
106   v13 = 0;
107   return *(_QWORD *)&v13;
108 }

 

2.1 代碼分析

經過第90~94行代碼,咱們知道正確的flag爲組合[v4 v3 v11 v12 v13 v14],其中v4="jlflag{",v13="abc}",v14=std::endlv8

所以咱們只須要求出v3,v11,v12便可,經過第85~87行代碼,咱們知道v12 = v22;v11 = Dst;v3 = v20;get

咱們可以經過這三個變量知足的三個表示,求出三個數的值。

 

3.腳本獲取

for v22 in range(100):
    for dst in range(100):
        for v20 in range(100):
            if v22*dst*v20//11 == 106 and (v22 + dst + v20) % 100 == 34:
                if (dst^v20) == v22 - 4:
                    if (v22 + dst + v20) % 100 == 34:
                        print("jlflag{%d%d%dabc}"%(v22, dst, v20), end='\n')

jlflag{61315abc}
jlflag{61513abc}
jlflag{13615abc}
jlflag{13156abc}
jlflag{15613abc}
jlflag{15136abc}

將這6組獲得的flag一組一組試,就能獲得正確flag。(記得去掉jl

 

4.get flag!

flag{15613abc}

相關文章
相關標籤/搜索