buu-刮开有奖

32位窗口程序,用IDA打开,定位到一个主要函数DialogFunc,对函数的变量名重命名了一下,然后为了方便观察生成了一些数组,最终伪代码整理如下

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int s[11]; // [esp+8h] [ebp-20030h] BYREF
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char temp[65536]; // [esp+10034h] [ebp-10004h] BYREF

  if ( a2 == 272 )
    return 1;
  if ( a2 != 273 )
    return 0;
  if ( a3 == 1001 )
  {
    memset(String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
    if ( strlen(String) == 8 )
    {
      s[0] = 'Z';
      s[1] = 'J';
      s[2] = 'S';
      s[3] = 'E';
      s[4] = 'C';
      s[5] = 'a';
      s[6] = 'N';
      s[7] = 'H';
      s[8] = '3';
      s[9] = 'n';
      s[10] = 'g';
      sub_4010F0(s, 0, 10);
      memset(temp, 0, 0xFFFFu);
      temp[0] = String[5];
      temp[2] = String[7];
      temp[1] = String[6];
      v4 = sub_401000(temp, strlen(temp));
      memset(temp, 0, 0xFFFFu);
      temp[1] = String[3];
      temp[0] = String[2];
      temp[2] = String[4];
      v5 = sub_401000(temp, strlen(temp));
      if ( String[0] == s[0] + 34
        && String[1] == s[4]
        && 4 * String[2] - 141 == 3 * s[2]
        && String[3] / 4 == 2 * (s[7] / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(v5, "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
    }
    return 0;
  }
  if ( a3 != 1 && a3 != 2 )
    return 0;
  EndDialog(hDlg, a3);
  return 1;
}

里面有个sub_4010F0函数,算法逻辑比较复杂,是对s字串进行处理(网上说是排序算法)要想得到处理后的结果可以有2种方法

  • 一种方法可以直接OD调试运行一下可以从内存单元中得到最终结果,没必要复现内部算法,
  • 也可以把伪代码修改成可运行的C代码,放到编译器运行一下

这2种方法我都进行了尝试。

先试试OD。一直单步运行到DialogFunc函数里后,执行那个函数之前有几处跳转语句,一旦触发跳转且会跳转到别处,我们就直接汇编成对应的反条件跳转指令,确保程序执行函数4010F0。
最后发现这个函数直接在栈内对字符串进行修改的,OD没有将其视作字符来处理(因为是对这些字符串的处理是以双字为单位进行操作,而非字节),所以直接数据窗口跟随可以看到最终结果。
在这里插入图片描述
另一种方法是把IDA反编译出来的代码扒拉下来(如下)放到IDE里运行也可以得出结果

#include<stdio.h>
using namespace std;

int sub_4010F0(char S[], int a, int b)
{
	int result; // eax
	int i; // esi
	int v5; // ecx
	int v6; // edx

	result = b;
	for (i = a; i <= b; a = i)
	{
		v5 = i;
		v6 = S[i];
		if (a < result && i < result)
		{
			do
			{
				if (v6 > S[result])
				{
					if (i >= result)  break;
					++i;
					S[v5] = S[result];
					if (i >= result)  break;
					while (S[i] <= v6)
					{
						if (++i >= result)
							goto LABEL_13;
					}
					if (i >= result)  break;
					v5 = i;
					S[result] = S[i];
				}
				--result;
			} while (i < result);
		}
	LABEL_13:
		S[result] = v6;
		sub_4010F0(S, a, i - 1);
		result = b;
		++i;
	}
	return result;
}

int main() {
	char  s[11] = { 'Z','J','S','E','C','a','N','H','3','n','g' };
	sub_4010F0(s, 0, 10);
	for (int i = 0; i < 11; i++)
	{
		printf("%c", s[i]);
	}
}

运行结果与OD的一致
在这里插入图片描述
最终得到3CEHJNSZagn,确实是对ASCII码进行了排序操作。👏👏👏

然后关键的函数是sub_401000
在这里插入图片描述
进去看看发现是base64编码
在这里插入图片描述
接下来分析完毕,整理一下exp

import base64
string=['' for i in range(8)]
key1='ak1w'
key2='V1Ax'
a=base64.b64decode(key1).decode('utf-8')
string[5]=a[0]
string[7]=a[2]
string[6]=a[1]
a=base64.b64decode(key2).decode('utf-8')
string[3]=a[1]
string[2]=a[0]
string[4]=a[2]

s='3CEHJNSZagn'
string[0]=chr(ord(s[0])+34)
string[1]=s[4]
string[2]=chr((3*ord(s[2])+141)//4)
flag=''
print('flag{'+flag.join(string)+'}')

在这里插入图片描述

flag{UJWP1jMp}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Em0s_Er1t

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值