【攻防世界】reverse | Mysterious 详细题解 WP

【攻防世界】reverse | Mysterious 详细题解 WP

下载附件

DialogFunc_0函数伪代码:

c 复制代码
int __stdcall DialogFunc_0(HWND hWnd, int a2, int a3, int a4)
{
  int v4; // eax
  char Source[260]; // [esp+50h] [ebp-310h] BYREF
  _BYTE Text[257]; // [esp+154h] [ebp-20Ch] BYREF
  __int16 v8; // [esp+255h] [ebp-10Bh]
  char v9; // [esp+257h] [ebp-109h]
  int Value; // [esp+258h] [ebp-108h]
  CHAR String[260]; // [esp+25Ch] [ebp-104h] BYREF

  memset(String, 0, sizeof(String));
  Value = 0;
  if ( a2 == 16 )
  {
    DestroyWindow(hWnd);
    PostQuitMessage(0);
  }
  else if ( a2 == 273 )
  {
    if ( a3 == 1000 )
    {
      GetDlgItemTextA(hWnd, 1002, String, 260);
      strlen(String);
      if ( strlen(String) > 6 )
        ExitProcess(0);
      v4 = atoi(String);
      Value = v4 + 1;
      if ( v4 == 122 && String[3] == 120 && String[5] == 122 && String[4] == 121 )
      {
        strcpy(Text, "flag");
        memset(&Text[5], 0, 0xFCu);
        v8 = 0;
        v9 = 0;
        _itoa(Value, Source, 10);
        strcat(Text, "{");
        strcat(Text, Source);
        strcat(Text, "_");
        strcat(Text, "Buff3r_0v3rf|0w");
        strcat(Text, "}");
        MessageBoxA(0, Text, "well done", 0);
      }
      SetTimer(hWnd, 1u, 0x3E8u, TimerFunc);
    }
    if ( a3 == 1001 )
      KillTimer(hWnd, 1u);
  }
  return 0;
}

WinMain函数伪代码:

c 复制代码
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DialogBoxParamA(hInstance, (LPCSTR)0x65, 0, (DLGPROC)DialogFunc, 0);
  return 0;
}

exp:

python 复制代码
def generate_flag(input_str: str) -> str:
    """
    复现DialogFunc_0的Flag生成逻辑
    :param input_str: 输入框字符串(需满足条件:122xyz)
    :return: 生成的Flag
    """
    # 步骤1:验证输入长度
    if len(input_str) > 6:
        raise ValueError("输入字符串长度不能超过6!")
    
    # 步骤2:转换为整数(模拟atoi)
    try:
        v4 = int(input_str[:3])  # atoi遇到非数字停止,取前3位转整数
    except ValueError:
        raise ValueError("输入字符串前3位必须是数字!")
    
    # 步骤3:验证核心条件
    if not (v4 == 122 and 
            len(input_str) >=6 and 
            input_str[3] == 'x' and 
            input_str[4] == 'y' and 
            input_str[5] == 'z'):
        raise ValueError("输入字符串不符合条件!需为122xyz")
    
    # 步骤4:计算Value
    value = v4 + 1
    
    # 步骤5:拼接Flag(模拟strcat逻辑)
    flag = f"flag{{{value}_Buff3r_0v3rf|0w}}"
    
    return flag

# 测试:输入符合条件的字符串
if __name__ == "__main__":
    # 满足条件的输入字符串
    valid_input = "122xyz"
    try:
        final_flag = generate_flag(valid_input)
        print(f"✅ 生成的Flag:{final_flag}")
    except ValueError as e:
        print(f"❌ 错误:{e}")

运行 exp 脚本:

复制代码
flag{123_Buff3r_0v3rf|0w}

【攻防世界】reverse | Mysterious 详细题解 WP 原理深度解析:

CTF 逆向实战:Mysterious 对话框程序 Flag 深度解析与解题方法论

一、题目背景与逆向目标

在 CTF 逆向领域,Windows 对话框程序是常见题型之一。这类程序通常通过对话框与用户交互,核心逻辑封装在回调函数中,Flag 生成往往依赖特定输入条件。本文以攻防世界 reverse 题目「Mysterious」为例,从逆向分析到 Flag 推导,全程还原解题思路,并提炼同类题目的通用解法。

二、程序结构初探:从入口到核心逻辑

2.1 程序入口定位

通过反编译工具(如 IDA Pro/Ghidra)分析程序,首先找到入口函数WinMain

c 复制代码
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DialogBoxParamA(hInstance, (LPCSTR)0x65, 0, (DLGPROC)DialogFunc, 0);
  return 0;
}

WinMain仅调用了DialogBoxParamA,这是 Windows 创建模态对话框的 API,其第四个参数DialogFunc为对话框回调函数(DLGPROC)------ 这是程序的核心逻辑所在,所有用户交互(如输入、按钮点击)的处理都在这里。

2.2 核心函数定位:DialogFunc_0

对话框回调函数DialogFunc_0负责处理所有对话框消息(如关闭窗口、按钮点击)。通过分析伪代码,我们发现其内部包含了 Flag 生成的关键逻辑。

三、DialogFunc_0 深度逆向:拆解 Flag 生成条件

3.1 变量与初始化逻辑

c 复制代码
int __stdcall DialogFunc_0(HWND hWnd, int a2, int a3, int a4)
{
  int v4; // 存储输入字符串转换的整数
  char Source[260]; // 存储Value的字符串形式
  _BYTE Text[257]; // 存储最终Flag
  int Value; // 存储v4+1的结果
  CHAR String[260]; // 存储用户输入的字符串

  memset(String, 0, sizeof(String)); // 初始化输入缓冲区
  Value = 0;
  // ... 消息处理逻辑
}

变量作用清晰:String接收用户输入,v4是输入字符串转换的整数,Value是计算结果,Text用于拼接 Flag。

3.2 消息处理:聚焦关键交互

对话框回调函数通过a2(消息 ID)区分不同事件:

  • a2 == 16:处理窗口关闭消息(WM_CLOSE),调用DestroyWindowPostQuitMessage退出程序,与 Flag 无关。
  • a2 == 273:处理按钮点击消息(BN_CLICKED),这是核心交互逻辑,其中a3表示按钮 ID。

3.3 核心逻辑:按钮 ID=1000 的处理流程

当点击 ID=1000 的按钮时,程序执行以下操作(按顺序解析):

步骤 1:读取用户输入
c 复制代码
GetDlgItemTextA(hWnd, 1002, String, 260);

通过GetDlgItemTextA读取 ID=1002 的输入框内容到String,最多 260 字节。

步骤 2:输入长度检查
c 复制代码
if (strlen(String) > 6) ExitProcess(0);

若输入长度超过 6,则直接退出程序。** 关键限制:输入长度必须≤6 **。

步骤 3:输入字符串转整数
c 复制代码
v4 = atoi(String);
Value = v4 + 1;

atoi函数将字符串转为整数,规则是「遇到非数字字符停止转换」。例如,输入 "122xyz" 时,atoi只会处理前 3 位 "122",得到v4=122

步骤 4:Flag 生成的核心条件

程序通过以下if语句判断是否生成 Flag:

c 复制代码
if (v4 == 122 && String[3] == 120 && String[5] == 122 && String[4] == 121)

拆解条件(结合 ASCII 码表):

  • v4 == 122:输入字符串的数字部分必须为 122(即前 3 位为 "122");
  • String[3] == 120:输入字符串第 4 个字符(索引 3)的 ASCII 码为 120 → 字符 'x';
  • String[4] == 121:输入字符串第 5 个字符(索引 4)的 ASCII 码为 121 → 字符 'y';
  • String[5] == 122:输入字符串第 6 个字符(索引 5)的 ASCII 码为 122 → 字符 'z'。
步骤 5:Flag 拼接逻辑

满足条件后,程序拼接 Flag:

c 复制代码
strcpy(Text, "flag");       // Text = "flag"
_itoa(Value, Source, 10);   // Source = "123"(因Value=122+1)
strcat(Text, "{");          // Text = "flag{"
strcat(Text, Source);       // Text = "flag{123"
strcat(Text, "_");          // Text = "flag{123_"
strcat(Text, "Buff3r_0v3rf|0w"); // Text = "flag{123_Buff3r_0v3rf|0w"
strcat(Text, "}");          // Text = "flag{123_Buff3r_0v3rf|0w}"
MessageBoxA(0, Text, "well done", 0); // 弹窗显示Flag

3.4 干扰逻辑排除

代码中包含SetTimerKillTimer(定时器相关),但这与 Flag 生成无关,属于干扰项。CTF 逆向中需学会过滤无关逻辑,聚焦MessageBoxAstrcat等与 Flag 直接相关的代码。

四、Flag 推导与验证

4.1 输入字符串确定

结合所有条件,输入字符串需满足:

  • 长度 = 6(因需包含索引 0-5 的字符);
  • 前 3 位:"122"(确保v4=122);
  • 后 3 位:索引 3='x'、索引 4='y'、索引 5='z'。

最终输入为:122xyz

4.2 Python 代码复现验证

编写代码模拟 Flag 生成逻辑,验证结果:

python 复制代码
def generate_flag(input_str: str) -> str:
    if len(input_str) > 6:
        raise ValueError("输入长度不能超过6")
    # 模拟atoi:取前3位数字
    try:
        v4 = int(input_str[:3])
    except:
        raise ValueError("前3位必须为数字")
    # 验证核心条件
    if not (v4 == 122 and len(input_str) == 6 
            and input_str[3] == 'x' 
            and input_str[4] == 'y' 
            and input_str[5] == 'z'):
        raise ValueError("输入不符合条件")
    # 生成Flag
    return f"flag{{{v4+1}_Buff3r_0v3rf|0w}}"

# 测试
print(generate_flag("122xyz"))  # 输出:flag{123_Buff3r_0v3rf|0w}

五、同类 CTF 题目解题方法论

5.1 题型特征识别

对话框程序逆向的典型特征:

  • 入口函数调用DialogBoxParamACreateDialogParamA
  • 存在回调函数(DLGPROC),参数包含HWND、消息 ID(a2)、控件 ID(a3);
  • 关键 API:GetDlgItemTextA(读输入)、MessageBoxA(显 Flag)、strcpy/strcat(字符串拼接)。

5.2 核心解题步骤

  1. 定位关键函数

    搜索MessageBoxAflag等关键词,快速定位 Flag 生成位置;通过GetDlgItemTextA找到输入处理逻辑。

  2. 解析输入验证规则

    • 关注长度限制(strlen);
    • 数值转换(atoi/itoa):注意atoi遇非数字截断的特性;
    • 字符位置校验(如String[i] == 0xXX):转换 ASCII 码为字符,推导输入格式。
  3. 过滤干扰逻辑

    忽略定时器(SetTimer)、绘图(DrawText)等与 Flag 无关的代码,聚焦条件判断(if)和字符串拼接。

  4. 动态调试验证

    若静态分析有歧义,用 x64dbg 在MessageBoxA处下断点,输入推测的字符串,直接查看弹窗内容。

5.3 工具链推荐

  • 静态分析:IDA Pro(伪代码清晰)、Ghidra(开源免费);
  • 动态调试 :x64dbg(断点MessageBoxA快速获取 Flag);
  • 辅助脚本:Python(复现字符串逻辑、验证输入条件)。

六、总结

本题通过分析对话框回调函数DialogFunc_0,提炼出输入验证的核心条件,最终推导出输入122xyz,生成 Flagflag{123_Buff3r_0v3rf|0w}。解题的关键在于:

  1. 快速定位 Flag 生成的核心逻辑(聚焦MessageBoxA和条件判断);
  2. 准确解析输入验证规则(长度、数值、字符位置);
  3. 过滤干扰代码,不被无关逻辑迷惑。

掌握这类方法后,面对同类对话框程序逆向题,可快速套用「定位关键函数→解析输入规则→验证生成 Flag」的流程,高效解题。

相关推荐
易天ETU1 小时前
FEC 功能与 DSP 芯片的关联性:解码信号处理高效协同核心
网络·信号处理·fec技术·800g光模块
赖small强1 小时前
【Linux C/C++ 开发】 GCC 编译过程深度解析指南
linux·c语言·c++·预处理·链接·编译·编译过程
BestOrNothing_20151 小时前
C++ 并发四件套:并发编程 / 原子性 / 数据竞争 / 内存模型 (全解析)
c++·多线程·并发编程·线程安全·内存模型·原子操作·数据竞争
陌路201 小时前
集群聊天室项目--muduo网络库中tcpserver中setConnectionCallback与setMessageCallback详解
网络
想唱rap1 小时前
C++之unordered_set和unordered_map
c++·算法·哈希算法
【建模先锋】1 小时前
高效对抗噪声!基于深度残差收缩网络(DRSN)的轴承故障诊断模型
网络·深度学习·信号处理·轴承故障诊断·降噪模型
Rock_yzh1 小时前
LeetCode算法刷题——54. 螺旋矩阵
数据结构·c++·学习·算法·leetcode·职场和发展·矩阵
shx66661 小时前
2.1.2 ROS2 C++ 示例
c++·ros2
從南走到北1 小时前
JAVA代驾小程序源码代驾跑腿APP源码
java·开发语言·微信·微信小程序·小程序