re学习(23)BUUCTF 刮开有奖(中间变量的获取)

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[2]; // [esp+8h] [ebp-20030h] BYREF 虽然看名称不连续,但是通过看偏移地址,可知,这些变量在内存中是连续的,以v7为首
  int v8; // [esp+10h] [ebp-20028h]
  int v9; // [esp+14h] [ebp-20024h]
  int v10; // [esp+18h] [ebp-20020h]
  int v11; // [esp+1Ch] [ebp-2001Ch]
  int v12; // [esp+20h] [ebp-20018h]
  int v13; // [esp+24h] [ebp-20014h]
  int v14; // [esp+28h] [ebp-20010h]
  int v15; // [esp+2Ch] [ebp-2000Ch]
  int v16; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

  if ( a2 == 272 )
    return 1;
  if ( a2 != 273 )
    return 0;
  if ( (_WORD)a3 == 1001 )
  {
    memset(String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
    if ( strlen(String) == 8 )                  // 输入的flag,可知为8位
    {
      v7[0] = 90;
      v7[1] = 74;
      v8 = 83;
      v9 = 69;
      v10 = 67;
      v11 = 97;
      v12 = 78;
      v13 = 72;
      v14 = 51;
      v15 = 110;
      v16 = 103;
      sub_8210F0((int)v7, 0, 10);               // 在v7原来内存中进行修改,修改为3CEHJNSZagn
      memset(v18, 0, 0xFFFFu);
      v18[0] = String[5];
      v18[2] = String[7];
      v18[1] = String[6];
      v4 = sub_821000((int)v18, strlen(v18));   // 字符串678位
      memset(v18, 0, 0xFFFFu);
      v18[1] = String[3];
      v18[0] = String[2];
      v18[2] = String[4];
      v5 = sub_821000((int)v18, strlen(v18));   // 字符串的345位
      if ( String[0] == v7[0] + 34              // string[0]=chr(ord('3')+34)='U'
        && String[1] == v10                     // string[1]='J'
        && 4 * String[2] - 141 == 3 * v8        // string[2]=chr((3*ord('E')+141)//4)='W',注意这里直接除除不尽,需要向下取整
        && String[3] / 4 == 2 * (v13 / 9)       // string[3]=chr((2*(ord('Z')//9))*4)=‘P’,同样用到了向下取整
        && !strcmp(v4, "ak1w")                  // base64解密后678位:jMp
        && !strcmp(
              v5,
              "V1Ax") )
      {                                         // base64解密后345位:WP1
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);// 显示对话框,即成功
      }
    }                                           // 最后string为:UJWP1jMp
    return 0;
  }
  if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    return 0;
  EndDialog(hDlg, (unsigned __int16)a3);
  return 1;
}

上图是主要分析的代码(思路:获取中间变量+倒推)

下图代码用于获得中间变量:(逆向功能:算法分析)

需要修改的地方:
1.在伪代码中,有a1+ 4 * i,a1+4 *result,这样的字符。int占四个字节,所以需要*4.如果是char类型,就不需要.

2.我们知道a1+4*i,也就是a1【i】,a1+4 * result,也就是a1【result】。

将伪代码的寻址方式改为数组寻址,然后将*(_DWORD*) 删掉,因为这是汇编的表示。

所以伪代码变成了C语言代码。

上代码:


#include 
int  sub_8210F0(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 = i[a1];
    if ( a2 < result && i < result )
    {
      do
      {
        if ( v6 > a1[result])
        {
          if ( i >= result )
            break;
          ++i;
          a1[v5] = a1[result];
          if ( i >= result )
            break;
          while ( a1[i]<= v6 )
          {
            if ( ++i >= result )
              goto LABEL_13;
          }
          if ( i >= result )
            break;
          v5 =i;
          a1[result] = a1[i];
        }
        --result;
      }
      while ( i < result );
    }
LABEL_13:
    a1[result] = v6;
    sub_8210F0(a1, a2, i - 1);
    result = a3;
    ++i;
  }
  return result;
}

int main()
{
	char str[]="ZJSECaNH3ng"; 
	sub_8210F0(str,0,10);
	printf("%s",str);
	return 0;
} 

re学习(23)BUUCTF 刮开有奖(中间变量的获取)_第1张图片

 flag{UJWP1jMp}

你可能感兴趣的:(#,IDA,reverse,算法)