buuctf-刮開有獎


題目:

 

 

 通過題目我們可以知道,我們能成功輸入的值就是我們的flag

下載附件后,發現是一個可執行的文件,執行一下,發現:

 

輸入值后,直接閃退啦!查殼發現無殼后拖入IDA(32bit)內,f5反編譯進入主函數,發現

 

 

 DialogBoxParamA函數里的DialogFunc參數就很像網絡編程中基於消息的WSAAsyncSelect模型里的消息處理函數,點進去后發現

 

 

  if ( (_WORD)a3 == 1001 )
  {
    memset(&String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);#這里要輸入字符串
    if ( strlen(&String) == 8 )#長度為八
    {
      v7 = 90;
      v8 = 74;
      v9 = 83;
      v10 = 69;
      v11 = 67;
      v12 = 97;
      v13 = 78;
      v14 = 72;
      v15 = 51;
      v16 = 110;
      v17 = 103;
      sub_4010F0(&v7, 0, 10);#這里對v7字符串進行了處理
      memset(&v26, 0, 0xFFFFu);
      v26 = v23;
      v28 = v25;
      v27 = v24;
      v4 = (const char *)sub_401000(&v26, strlen(&v26));#這里可以推出以v23為首地址的字符串(長度為3)
      memset(&v26, 0, 0xFFFFu);
      v27 = v21;
      v26 = v20;
      v28 = v22;
      v5 = (const char *)sub_401000(&v26, strlen(&v26));#這里可以推出以v20為首地址的字符串(長度為3)
      if ( String == v7 + 34
        && v19 == v11
        && 4 * v20 - 141 == 3 * v9
        && v21 / 4 == 2 * (v14 / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(v5, "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
    }
    return 0;
  }
  if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    return 0;
  EndDialog(hDlg, (unsigned __int16)a3);

 通過大概的分析程序,我們可以發現,我們輸入的字符串的長度為8字節,通過點進去v19、v20,發現v18處地址對應的就是我們輸入字符串的首地址,v19、v20、...v25處地址就分別是字符串每個字符的地址

 所以,我們只需把每個對應的字符逆推出來,那么也就得到了我們的flag啦。

開始逆推:

首先我們知道從v7至v17這11個變量的值,往后碰到 sub_4010F0(&v7, 0, 10)函數,點進去發現有對以v7為首地址的字符進行了處理,直接粘貼,用C語言解出處理后對應的值

#include<stdio.h>
#include<iostream>

using namespace std;

int  sub(char a1[], int a2, int a3)
{
  int result; // eax
  int i; // esi
  int v5; // ecx
  int v6; // edx

  result = a3;
  for ( i = a2; i <= a3; a2 = i )
  {
    v5 = i;
    //v6 = *(DWORD *)(4 * i + a1);
    v6 = a1[i];
    if ( a2 < result && i < result )
    {
      do
      {
        //if ( v6 > *(DWORD *)(a1 + 4 * result) )
        if ( v6 > a1[result] )
        {
          if ( i >= result )
            break;
          ++i;
          //*(DWORD *)(v5 + a1) = *(DWORD *)(a1 + 4 * result);
          a1[v5] = a1[result];
          if ( i >= result )
            break;
          //while ( *(DWORD *)(a1 + 4 * i) <= v6 )
          while ( a1[i] <= v6 )
          {
            if ( ++i >= result )
              goto LABEL_13;
          }
          if ( i >= result )
            break;
          v5 = i;
          //*(DWORD *)(a1 + 4 * result) = *(DWORD *)(4 * i + a1);
          a1[result] = a1[i];
        }
        --result;
      }
      while ( i < result );
    }
LABEL_13:
    //*(DWORD *)(a1 + 4 * result) = v6;
    a1[result]= v6;
    sub(a1, a2, i - 1);
    result = a3;
    ++i;
  }
  return result;
}

int main()
{
    char a[11]={90,74,83,69,67,97,78,72,51,110,103};
    cout<<">>>>sub"<<endl;
    sub(a,0,10);
    for (int i=0;i<11;i++)
    {
        cout<<"a["<<i+7<<"]"<<a[i]<<" "<<int(a[i])<<endl;
        //cout<<a[i]<<" ";
    }
}

運行結果為:

繼續往下推,發現有 v4 = (const char *)sub_401000(&v26, strlen(&v26));v5 = (const char *)sub_401000(&v26, strlen(&v26));點進去sub_401000發現(圖沒截全)

點進去byte_407830發現

可知,結果是經過base64編碼得到的。

然后,我們繼續往后推

if ( String == v7 + 34 && v19 == v11 && 4 * v20 - 141 == 3 * v9 && v21 / 4 == 2 * (v14 / 9) && !strcmp(v4, "ak1w") && !strcmp(v5, "V1Ax") ) { MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0); }

通過這里,我們知道

string(v18)=v7+34=51+34=86='U'

V19='J'

v20='W'

v21='P'

又因為v4='ak1w',v5='V1Ax',通過base64解碼分別得,v4='jMp',v5='WP1',因此可知,v20='W',v21='P',v22='1'(v5);v23='j',v24='M',v25='p'(v4)

這樣我們就得到我們的flag啦!!!即flag{UJWP1jMp}

 


免責聲明!

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



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