BUUCTF[刮开有奖]

BUUCTF[刮开有奖]

下载附件后,拖进die分析

image-20240801111138182

32位无壳,直接拖进ida分析

shift+f12查看字符串

image-20240801112349375

发现可疑字符串,双击进去发现包含它的函数

image-20240801112441134

双击函数名后按Tab/F5反编译查看函数

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
  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 )
    {
      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_4010F0(v7, 0, 10);
      memset(v18, 0, 0xFFFFu);
      v18[0] = String[5];
      v18[2] = String[7];
      v18[1] = String[6];
      v4 = (const char *)sub_401000(v18, strlen(v18));
      memset(v18, 0, 0xFFFFu);
      v18[1] = String[3];
      v18[0] = String[2];
      v18[2] = String[4];
      v5 = (const char *)sub_401000(v18, strlen(v18));
      if ( String[0] == v7[0] + 34
        && String[1] == v10
        && 4 * String[2] - 141 == 3 * v8
        && String[3] / 4 == 2 * (v13 / 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);
  return 1;
}
DialogFunc()函数

DialogFunc()函数的作用通常是处理对话框的创建和消息传递。这个函数通常与图形用户界面(GUI)编程有关,特别是在使用 Windows API 或类似库时。它处理由对话框窗口接收的所有消息,例如按钮点击、文本输入等。

memset函数

memset() 函数是 C 标准库中的一个函数,用于将一块内存区域的内容设置为指定的值。它通常用于初始化或重置内存中的数据。

GetDlgItemTextA()函数

GetDlgItemTextA() 函数是 Windows API 中的一个函数,用于从指定的对话框控件(例如编辑框、静态文本控件等)中检索文本。这个函数是 GetDlgItemText() 函数的 ANSI 版本(带有 A 后缀),用于处理 ANSI 字符集。

加密逻辑分析

首先看这一部分

image-20240801114808738

10h-08h=08h,一个int四个字节,正好对应v7两个值的内存

14h-10h=04h,也是一个int类型的4个字节

即v7-v16为一个数组的值

继续往下看,发现加密函数sub_4010F0()

继续往下看

image-20240801115202797

发现v4,v5是分别在string对v18赋值后再经过sub_401000()函数

并将最后的结果v4与ak1w比较,v5与V1Ax比较

所以加密的逻辑为,v7数组先经过sub_4010F0()函数得到新的数组值,再将新的数组值赋值给v4,v5。v4,v5经过函数sub_401000()再与给出的两个字符串做比较。所以我们的重心便是分析两个加密函数

sub_401000()函数

首先看sub_401000()

image-20240801115736605

观察函数发现是典型的base64加密,再看byte_407830发现是基础的base表

image-20240801115903299

那么将已得到的字符串进行base64解密

分别得到string的第2,3,4个字符(v5比较的字符串base64解密)为:WP1

image-20240801120121328

string的第5,6,7个字符(v4比较的字符串base64解密)为:jMp

image-20240801120301763

sub_4010F0()函数

进入分析,就是一个加密的算法,直接将函数整个复制下来

其中的 _DWORD 对应的就是无符号字符类型

image-20240801123552756

再根据这四个判断还原出string的前四个字符

#include <bits/stdc++.h>  //竞赛编程中常用头文件,包含所有c++标准库头文件
#define _DWORD unsigned char
using namespace std;

char v7[15] = {90, 74, 83, 69, 67, 97, 78, 72, 51, 110, 103};
char string[10];

int sub_4010F0(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 *)(i + a1);
        if (a2 < result && i < result)
        {
            do
            {
                if (v6 > *(_DWORD *)(a1 + result))
                {
                    if (i >= result)
                        break;
                    ++i;
                    *(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + result);
                    if (i >= result)
                        break;
                    while (*(_DWORD *)(a1 + i) <= v6)
                    {
                        if (++i >= result)
                            goto LABEL_13;
                    }
                    if (i >= result)
                        break;
                    v5 = i;
                    *(_DWORD *)(a1 + result) = *(_DWORD *)(i + a1);
                }
                --result;
            } while (i < result);
        }
    LABEL_13:
        *(_DWORD *)(a1 + result) = v6;
        sub(a1, a2, i - 1);
        result = a3;
        ++i;
    }
    return result;
}

int main()
{
    sub_4010F0(v7, 0, 10);
    cout << v7 << endl;
    string[0] = v7[0] + 34;
    string[1] = v7[4];
    string[2] = (3 * v7[2] + 141) / 4;
    string[3] = 8 * (v7[7] / 9);
    cout << string << endl;
}

运行代码得到

image-20240801123910874

再去前文得到的string2,3,4,5,6,7组合得到flag

flag{UJWp1jMp}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ep0ch

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

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

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

打赏作者

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

抵扣说明:

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

余额充值