JQCTF2025 Customize Virtual Machine复现
字数 2178 2025-08-29 22:41:24

JQCTF2025 Customize Virtual Machine 逆向分析与解题教程

1. 题目概述

这是一个基于自定义虚拟机(VM)的逆向工程挑战,主要涉及自修改代码(SMC)和虚拟机逆向分析技术。题目要求参赛者解密并分析一段被混淆的代码,最终获取隐藏的flag。

2. 题目核心逻辑

2.1 基本流程

  1. 输入一个长度为50的字符串作为flag
  2. 将flag的每一位与长度为50的fun_list对应位置的字节数组进行异或操作
  3. 实现SMC(自修改代码)功能,解密函数
  4. 使用自定义虚拟机执行解密后的opcode并调用这些函数

2.2 关键数据结构

  • fun_list: 包含50个字节数组,每个数组对应flag的一个字符
  • data[i]: 对应第i个函数,内容是要参与异或的字节数据

3. 解题思路分析

3.1 SMC解密策略

由于题目使用SMC技术,我们需要通过以下特征来判断解密是否正确:

  1. 合法函数特征:解密后的函数代码应该是有效的汇编指令
  2. 非法指令排除:有效函数不应包含特定非法指令

3.2 非法指令列表

合法函数中通常不会包含以下指令(或极其罕见):

指令 原因
hlt 中止CPU,常用于内核或异常终止
cli, sti 中断控制,通常为内核态指令
in, out, ins, outs 端口IO操作,只用于驱动程序或内核
lgdt, lidt, ltr, lmsw 修改全局或中断表,仅限系统级代码
rdmsr, wrmsr, rdtsc 访问CPU特权寄存器,仅限特定应用
vm*, svm* 虚拟化指令,仅虚拟机/Hypervisor使用
ud2 故意制造非法指令,常用于崩溃测试或反调试
lock前缀的原子指令 除非是多线程同步函数

3.3 常见合法指令

解密后的函数可能包含以下常见指令:

  • push, pop
  • mov
  • sub, add
  • cmp, test
  • xor, and, or
  • lea
  • imul
  • jmp, jcc条件跳转
  • call, ret

3.4 Flag格式限制

题目明确说明flag格式为:

  • 字符集:0-9, a-z_
  • 长度:固定50个字符

4. 解题步骤详解

4.1 数据提取

  1. 从题目提供的文件中提取fun_list数据
  2. 确保每个data[i]对应第i个函数,内容是要参与异或的字节

4.2 爆破策略

由于flag字符集有限且长度固定,可以采用逐字符爆破的方法:

  1. 对每个位置i (0 ≤ i < 50)
  2. 尝试所有可能的字符c (0-9, a-z, _)
  3. 用c与fun_list[i]进行异或解密
  4. 检查解密结果是否为合法汇编代码

4.3 使用Capstone反汇编引擎

Capstone是一个强大的反汇编框架,可用于验证解密后的代码是否合法:

from capstone import *

# 初始化Capstone引擎
md = Cs(CS_ARCH_X86, CS_MODE_32)

# 对解密后的字节进行反汇编
for i in md.disasm(decrypted_bytes, 0x1000):
    print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))

4.4 爆破代码实现

关键步骤:

  1. 遍历每个flag位置
  2. 尝试所有可能的字符
  3. 解密并反汇编
  4. 检查第一条指令是否合法
  5. 记录所有可能的候选字符
def brute_force_char(pos):
    possible_chars = []
    for c in ALLOWED_CHARS:  # 0-9a-z_
        decrypted = xor(fun_list[pos], ord(c))
        # 使用Capstone反汇编第一条指令
        instr = next(md.disasm(decrypted[:15], 0), None)
        if instr and is_valid_instruction(instr):
            possible_chars.append(c)
    return possible_chars

4.5 特殊处理

题目提示:

  • 前15个函数都是全部解密
  • 后35个函数留了最后一个字节未修改(可能是ret指令,0xC3)

因此可以推测:

  • 最后一个字节异或0xC3可以得到flag对应位置的字符

5. 工具与技术

5.1 Capstone反汇编引擎

Capstone是一个轻量级、多平台、多架构的反汇编框架:

  • 官网: https://github.com/aquynh/capstone
  • 支持架构: Arm, Arm64 (AArch64/Armv8), Mips, PPC, Sparc, SystemZ, XCore, X86 (包括X86-64)
  • 绑定语言: C/C++, Python, Java, Go等

安装方法:

pip install capstone

5.2 其他技巧

  1. 指令长度分析:通过观察解密后代码的指令长度分布辅助判断
  2. 函数序言分析:合法函数通常以push ebp; mov ebp, esp开头
  3. 交叉验证:对多个候选字符的解密结果进行比较,选择最合理的

6. 完整解题流程

  1. 提取fun_list数据
  2. 对每个位置进行字符爆破:
    • 前15个位置:完整解密并验证
    • 后35个位置:假设最后一个字节是ret(0xC3)
  3. 组合所有位置的解得到完整flag
  4. 验证flag的正确性

7. 经验总结

  1. SMC分析:理解自修改代码的工作原理是关键
  2. 指令特征:掌握合法与非法指令的区别能大幅提高效率
  3. 工具使用:熟练使用反汇编工具如Capstone是逆向工程的基础
  4. 爆破策略:在有限字符集情况下,爆破是有效手段
  5. 题目提示:注意题目给出的所有提示信息(如flag格式、函数处理差异等)

8. 扩展思考

  1. 如何防御这种基于指令特征的爆破攻击?

    • 增加合法但罕见的指令
    • 使用多层加密
    • 加入反调试技术
  2. 更高效的解题方法?

    • 结合动态分析,在解密后直接运行代码
    • 使用符号执行技术
    • 应用机器学习分类器识别合法代码
  3. 实际应用场景:

    • 恶意代码分析
    • 软件保护技术研究
    • 虚拟机逃逸漏洞挖掘
JQCTF2025 Customize Virtual Machine 逆向分析与解题教程 1. 题目概述 这是一个基于自定义虚拟机(VM)的逆向工程挑战,主要涉及自修改代码(SMC)和虚拟机逆向分析技术。题目要求参赛者解密并分析一段被混淆的代码,最终获取隐藏的flag。 2. 题目核心逻辑 2.1 基本流程 输入一个长度为50的字符串作为flag 将flag的每一位与长度为50的 fun_list 对应位置的字节数组进行异或操作 实现SMC(自修改代码)功能,解密函数 使用自定义虚拟机执行解密后的opcode并调用这些函数 2.2 关键数据结构 fun_list : 包含50个字节数组,每个数组对应flag的一个字符 data[i] : 对应第i个函数,内容是要参与异或的字节数据 3. 解题思路分析 3.1 SMC解密策略 由于题目使用SMC技术,我们需要通过以下特征来判断解密是否正确: 合法函数特征 :解密后的函数代码应该是有效的汇编指令 非法指令排除 :有效函数不应包含特定非法指令 3.2 非法指令列表 合法函数中通常 不会 包含以下指令(或极其罕见): | 指令 | 原因 | |------|------| | hlt | 中止CPU,常用于内核或异常终止 | | cli , sti | 中断控制,通常为内核态指令 | | in , out , ins , outs | 端口IO操作,只用于驱动程序或内核 | | lgdt , lidt , ltr , lmsw 等 | 修改全局或中断表,仅限系统级代码 | | rdmsr , wrmsr , rdtsc 等 | 访问CPU特权寄存器,仅限特定应用 | | vm* , svm* | 虚拟化指令,仅虚拟机/Hypervisor使用 | | ud2 | 故意制造非法指令,常用于崩溃测试或反调试 | | lock 前缀的原子指令 | 除非是多线程同步函数 | 3.3 常见合法指令 解密后的函数可能包含以下常见指令: push , pop mov sub , add cmp , test xor , and , or lea imul jmp , jcc 条件跳转 call , ret 3.4 Flag格式限制 题目明确说明flag格式为: 字符集: 0-9 , a-z 和 _ 长度:固定50个字符 4. 解题步骤详解 4.1 数据提取 从题目提供的文件中提取 fun_list 数据 确保每个 data[i] 对应第i个函数,内容是要参与异或的字节 4.2 爆破策略 由于flag字符集有限且长度固定,可以采用逐字符爆破的方法: 对每个位置i (0 ≤ i < 50) 尝试所有可能的字符c (0-9, a-z, _ ) 用c与 fun_list[i] 进行异或解密 检查解密结果是否为合法汇编代码 4.3 使用Capstone反汇编引擎 Capstone是一个强大的反汇编框架,可用于验证解密后的代码是否合法: 4.4 爆破代码实现 关键步骤: 遍历每个flag位置 尝试所有可能的字符 解密并反汇编 检查第一条指令是否合法 记录所有可能的候选字符 4.5 特殊处理 题目提示: 前15个函数都是全部解密 后35个函数留了最后一个字节未修改(可能是 ret 指令,0xC3) 因此可以推测: 最后一个字节异或 0xC3 可以得到flag对应位置的字符 5. 工具与技术 5.1 Capstone反汇编引擎 Capstone是一个轻量级、多平台、多架构的反汇编框架: 官网: https://github.com/aquynh/capstone 支持架构: Arm, Arm64 (AArch64/Armv8), Mips, PPC, Sparc, SystemZ, XCore, X86 (包括X86-64) 绑定语言: C/C++, Python, Java, Go等 安装方法: 5.2 其他技巧 指令长度分析 :通过观察解密后代码的指令长度分布辅助判断 函数序言分析 :合法函数通常以 push ebp; mov ebp, esp 开头 交叉验证 :对多个候选字符的解密结果进行比较,选择最合理的 6. 完整解题流程 提取 fun_list 数据 对每个位置进行字符爆破: 前15个位置:完整解密并验证 后35个位置:假设最后一个字节是 ret (0xC3) 组合所有位置的解得到完整flag 验证flag的正确性 7. 经验总结 SMC分析 :理解自修改代码的工作原理是关键 指令特征 :掌握合法与非法指令的区别能大幅提高效率 工具使用 :熟练使用反汇编工具如Capstone是逆向工程的基础 爆破策略 :在有限字符集情况下,爆破是有效手段 题目提示 :注意题目给出的所有提示信息(如flag格式、函数处理差异等) 8. 扩展思考 如何防御这种基于指令特征的爆破攻击? 增加合法但罕见的指令 使用多层加密 加入反调试技术 更高效的解题方法? 结合动态分析,在解密后直接运行代码 使用符号执行技术 应用机器学习分类器识别合法代码 实际应用场景: 恶意代码分析 软件保护技术研究 虚拟机逃逸漏洞挖掘