题目:

buuctf-刮开有奖 Safe 第1张

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

 

 

 通过题目我们可以知道,我们能成功输入的值就是我们的flag

下载附件后,发现是一个可执行的文件,执行一下,发现:

buuctf-刮开有奖 Safe 第2张

 

输入值后,直接闪退啦!查壳发现无壳后拖入IDA(32bit)内,f5反编译进入主函数,发现

buuctf-刮开有奖 Safe 第3张

 

 

 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处地址就分别是字符串每个字符的地址

buuctf-刮开有奖 Safe 第4张

 所以,我们只需把每个对应的字符逆推出来,那么也就得到了我们的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]<<" ";
    }
}

运行结果为:

buuctf-刮开有奖 Safe 第5张

继续往下推,发现有 v4 = (const char *)sub_401000(&v26, strlen(&v26));v5 = (const char *)sub_401000(&v26, strlen(&v26));点进去sub_401000发现(图没截全)

buuctf-刮开有奖 Safe 第6张

点进去byte_407830发现

buuctf-刮开有奖 Safe 第7张

可知,结果是经过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}

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄