BUUCTF 刮開有獎 WriteUp


題目鏈接

https://buuoj.cn/challenges#%E5%88%AE%E5%BC%80%E6%9C%89%E5%A5%96

題解

用IDA打開,按F5反編譯,雙擊進入DialogFunc函數。

1

代碼如下:

 1 BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
 2 {
 3   const char *v4; // esi
 4   const char *v5; // edi
 5   int v7; // [esp+8h] [ebp-20030h]
 6   int v8; // [esp+Ch] [ebp-2002Ch]
 7   int v9; // [esp+10h] [ebp-20028h]
 8   int v10; // [esp+14h] [ebp-20024h]
 9   int v11; // [esp+18h] [ebp-20020h]
 10   int v12; // [esp+1Ch] [ebp-2001Ch]
 11   int v13; // [esp+20h] [ebp-20018h]
 12   int v14; // [esp+24h] [ebp-20014h]
 13   int v15; // [esp+28h] [ebp-20010h]
 14   int v16; // [esp+2Ch] [ebp-2000Ch]
 15   int v17; // [esp+30h] [ebp-20008h]
 16   CHAR String; // [esp+34h] [ebp-20004h]
 17   char v19; // [esp+35h] [ebp-20003h]
 18   char v20; // [esp+36h] [ebp-20002h]
 19   char v21; // [esp+37h] [ebp-20001h]
 20   char v22; // [esp+38h] [ebp-20000h]
 21   char v23; // [esp+39h] [ebp-1FFFFh]
 22   char v24; // [esp+3Ah] [ebp-1FFFEh]
 23   char v25; // [esp+3Bh] [ebp-1FFFDh]
 24   char v26; // [esp+10034h] [ebp-10004h]
 25   char v27; // [esp+10035h] [ebp-10003h]
 26   char v28; // [esp+10036h] [ebp-10002h]
 27 
 28   if ( a2 == 272 )
 29     return 1;
 30   if ( a2 != 273 )
 31     return 0;
 32   if ( (_WORD)a3 == 1001 )
 33   {
 34     memset(&String, 0, 0xFFFFu);
 35     GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
 36     if ( strlen(&String) == 8 )
 37     {
 38       v7 = 90;
 39       v8 = 74;
 40       v9 = 83;
 41       v10 = 69;
 42       v11 = 67;
 43       v12 = 97;
 44       v13 = 78;
 45       v14 = 72;
 46       v15 = 51;
 47       v16 = 110;
 48       v17 = 103;
 49       sub_4010F0((int)&v7, 0, 10);
 50       memset(&v26, 0, 0xFFFFu);
 51       v26 = v23;
 52       v28 = v25;
 53       v27 = v24;
 54       v4 = sub_401000((int)&v26, strlen(&v26));
 55       memset(&v26, 0, 0xFFFFu);
 56       v27 = v21;
 57       v26 = v20;
 58       v28 = v22;
 59       v5 = sub_401000((int)&v26, strlen(&v26));
 60       if ( String == v7 + 34
 61         && v19 == v11
 62         && 4 * v20 - 141 == 3 * v9
 63         && v21 / 4 == 2 * (v14 / 9)
 64         && !strcmp(v4, "ak1w")
 65         && !strcmp(v5, "V1Ax") )
 66       {
 67         MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
 68       }
 69     }
 70     return 0;
 71   }
 72   if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
 73     return 0;
 74   EndDialog(hDlg, (unsigned __int16)a3);
 75   return 1;
 76 }

35行讀取輸入,36行說明flag長度為8。

進入49行的sub_4010F0函數,並修改為可以運行的C語言格式。代碼如下:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int __cdecl sub_4010F0(char *a1, int a2, int a3) // int a1
  4 {
  5   int result; // eax
  6   int i; // esi
  7   int v5; // ecx
  8   int v6; // edx
  9 
 10   result = a3;
 11   for ( i = a2; i <= a3; a2 = i )
 12   {
 13     v5 = i; //v5 = 4 * i 這一行為什么要改?求大佬指教 
 14     v6 = a1[i]; //v6 = *(_DWORD *)(4 * i + a1)
 15     if ( a2 < result && i < result )
 16     {
 17       do
 18       {
 19         if ( v6 > a1[result] ) //v6 > *(_DWORD *)(a1 + 4 * result)
 20         {
 21           if ( i >= result )
 22             break;
 23           ++i;
 24           a1[v5] = a1[result]; //*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result)
 25           if ( i >= result )
 26             break;
 27           while ( a1[i] <= v6 ) // *(_DWORD *)(a1 + 4 * i) <= v6
 28           {
 29             if ( ++i >= result )
 30               goto LABEL_13;
 31           }
 32           if ( i >= result )
 33             break;
 34           v5 = i; //v5 = 4 * i 這一行為什么要改?求大佬指教 
 35           a1[result] = a1[i]; // *(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1)
 36         }
 37         --result;
 38       }
 39       while ( i < result );
 40     }
 41 LABEL_13:
 42     a1[result] = v6; //*(_DWORD *)(a1 + 4 * result) = v6
 43     sub_4010F0(a1, a2, i - 1);
 44     result = a3;
 45     ++i;
 46   }
 47   return result;
 48 }
 49 
 50 char str[20] = {90,74,83,69,67,97,78,72,51,110,103};
 51 
 52 int main()
 53 {
 54     cout << str << endl;
 55     sub_4010F0(str,0,10);
 56     cout << str << endl;
 57 }

這里50行我們定義的字符串見DialogFunc函數中第38到48行。運行結果:

4

我們再回到DialogFuc函數。

6

通過觀察變量v7到v25定義時的地址(或者雙擊變量名),我們知道它們在地址中是相鄰的,實際上如下圖:

5

那么可以理解,DialogFunc函數中第51~54行,是把經過sub_4010F0處理后的字符串的倒數第3~倒數第1位賦給v4,而第56~59行,是將倒數第6~倒數第4位賦給v5。

接下來我們研究sub_401000函數。代碼如下:

  1 _BYTE *__cdecl sub_401000(int a1, int a2)
  2 {
  3   int v2; // eax
  4   int v3; // esi
  5   size_t v4; // ebx
  6   _BYTE *v5; // eax
  7   _BYTE *v6; // edi
  8   int v7; // eax
  9   _BYTE *v8; // ebx
 10   int v9; // edi
 11   signed int v10; // edx
 12   int v11; // edi
 13   signed int v12; // eax
 14   signed int v13; // esi
 15   _BYTE *result; // eax
 16   _BYTE *v15; // [esp+Ch] [ebp-10h]
 17   _BYTE *v16; // [esp+10h] [ebp-Ch]
 18   int v17; // [esp+14h] [ebp-8h]
 19   int v18; // [esp+18h] [ebp-4h]
 20 
 21   v2 = a2 / 3;
 22   v3 = 0;
 23   if ( a2 % 3 > 0 )
 24     ++v2;
 25   v4 = 4 * v2 + 1;
 26   v5 = malloc(v4);
 27   v6 = v5;
 28   v15 = v5;
 29   if ( !v5 )
 30     exit(0);
 31   memset(v5, 0, v4);
 32   v7 = a2;
 33   v8 = v6;
 34   v16 = v6;
 35   if ( a2 > 0 )
 36   {
 37     while ( 1 )
 38     {
 39       v9 = 0;
 40       v10 = 0;
 41       v18 = 0;
 42       do
 43       {
 44         if ( v3 >= v7 )
 45           break;
 46         ++v10;
 47         v9 = *(unsigned __int8 *)(v3++ + a1) | (v9 << 8);
 48       }
 49       while ( v10 < 3 );
 50       v11 = v9 << 8 * (3 - v10);
 51       v12 = 0;
 52       v17 = v3;
 53       v13 = 18;
 54       do
 55       {
 56         if ( v10 >= v12 )
 57         {
 58           *((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
 59           v8 = v16;
 60         }
 61         else
 62         {
 63           *((_BYTE *)&v18 + v12) = 64;
 64         }
 65         *v8++ = byte_407830[*((char *)&v18 + v12)];
 66         v13 -= 6;
 67         ++v12;
 68         v16 = v8;
 69       }
 70       while ( v13 > -6 );
 71       v3 = v17;
 72       if ( v17 >= a2 )
 73         break;
 74       v7 = a2;
 75     }
 76     v6 = v15;
 77   }
 78   result = v6;
 79   *v8 = 0;
 80   return result;
 81 }

進入第65行的byte_407830

7

懷疑sub_401000是base64加密。

再回到DialogFuc函數,研究flag的格式:

  if ( String == v7 + 34                    // 第一位等於經過sub_4010F0處理后的字符串的第一位('3')51+34=85('U')
        && v19 == v11                           // 第二位等於v11,即經過sub_4010F00處理后的字符串的第5位'J'
        && 4 * v20 - 141 == 3 * v9              // 經過計算,第三位等於(3 * 69('E') + 141) / 4 = 87('W')
        && v21 / 4 == 2 * (v14 / 9)             // 第四位等於2 * ( 90('Z') / 9 ) * 4 = 80('P')
        && !strcmp(v4, "ak1w")                  // 第六、七、八位經過base64加密后等於'ak1w'
        && !strcmp(                             // 第三、四、五位經過base64加密后等於'V1Ax'
              v5,
              "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }

將’ak1w’、’V1Ax’進行base64解密,再連上前兩位拼接起來,加上flag{}格式,即可得到flag:

flag{UJWP1jMp}

參考

BUUCTF--刮開有獎

Open Live Writer 安裝

open live writer 安裝 markdown 插件

博客高亮代碼及使用OpenLiveWriter修改之前博客

其他

一開始用openlivewriter插入markdown代碼總是報錯

2

解決辦法是取消勾選語言。


3


免責聲明!

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



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