浅析新时代的wasm逆向思路-由源鲁杯入门题和N1junior零解题开始
字数 1423 2025-08-23 18:31:18

WebAssembly逆向工程实战指南

1. WebAssembly简介

WebAssembly(简称Wasm)是一种新兴的低级字节码格式,设计用于提升Web应用程序的性能和效率。主要特点包括:

  • 接近原生代码的执行速度
  • 跨平台特性(浏览器、服务器、嵌入式设备)
  • 紧凑的二进制格式
  • 内存安全沙箱环境

Wasm逆向工程已成为CTF竞赛和实际安全研究中的重要技能。

2. Wasm逆向工程方法论

2.1 工具链准备

必备工具:

  • WABT工具包(WebAssembly Binary Toolkit):
    • wasm2wat:将.wasm转换为可读的.wat文本格式
    • wasm2c:将.wasm转换为C代码

反编译工具:

  1. IDA Pro 9.0+

    • 支持Wasm反汇编
    • 目前缺乏反编译功能(截至2024年)
  2. Ghidra + Wasm插件

    • 提供完整的反编译支持
    • 插件地址:https://github.com/nneonneo/ghidra-wasm-plugin/
  3. 动态分析工具

    • Chrome开发者工具
    • VSCode + Node.js插件

2.2 逆向流程

方法一:WABT + IDA组合

$ ./wasm2wat wasm.wasm -o wasm.wat  # 转换为文本格式
$ ./wasm2c wasm.wasm -o wasm.c      # 转换为C代码

优势:利用IDA强大的分析能力
劣势:流程较为繁琐

方法二:Ghidra插件"一把梭"

优势:

  • 安装简单
  • 快速反编译
  • 适合快速分析

劣势:

  • 反编译质量有时不理想
  • 复杂代码处理能力有限

方法三:动态调试

  • Chrome开发者工具:
    • 支持设置断点
    • 实时查看内存和调用栈
  • 参考资源:https://panda0s.top/2021/05/14/WebAssembly-Reverse/

3. 实战案例分析

3.1 2024源鲁杯Round2 Wasm题目分析

题目特征:

  • 提供单个wasm文件
  • 使用Ghidra插件直接反编译

关键函数分析:

undefined4 unnamed_function_7(void) {
    // 变量声明和初始化
    gzflag = unnamed_function_14("GZCTF_FLAG");
    length = unnamed_function_20(gzflag);
    
    // 处理换行符
    if ((length != 0) && (*(char *)(gzflag + length -1) == '\n')) {
        *(undefined *)(gzflag + length -1) = 0;
    }
    
    // 第一轮处理:字符转换
    for (i = 0; *(char *)(gzflag + i) != '\0'; i++) {
        if (是小写字母) {
            转换为大写;
            应用模运算: (char - 0x3a) % 0x1a + 'A';
        } else if (是大写字母) {
            转换为小写;
            应用模运算: (char - 0x5a) % 0x1a + 'a';
        }
    }
    
    // 第二轮处理:输出校验
    for (i = 0; *(char *)(gzflag + i) != '\0'; i++) {
        local_20[0] = (int)*(char *)(gzflag + i);
        unnamed_function_15(0x43a, local_20);
    }
    return 0;
}

解题脚本:

def decrypt_flag(gzflag):
    decrypted = []
    for char in gzflag:
        if 'A' <= chr(char) <= 'Z':
            # 大写字母处理
            char = char - ord('A')
            char = char - 0x20
            char = (char - ord('A') + 0x5a) % 26 + ord('a')
        elif 'a' <= chr(char) <= 'z':
            # 小写字母处理
            char = char - ord('a')
            char = char + 0x20
            char = (char - ord('a') + 0x3a) % 26 + ord('A')
        decrypted.append(chr(char))
    return ''.join(decrypted)

# 测试数据
gzflag = [0x66, 0x73, 0x6a, 0x61, 0x6d, 0x7b, 0x48, 0x31, 0x30, 0x49, 0x38, 
          0x33, 0x30, 0x37, 0x2d, 0x36, 0x35, 0x4c, 0x4b, 0x2d, 0x34, 0x4c, 
          0x35, 0x36, 0x2d, 0x49, 0x30, 0x37, 0x39, 0x2d, 0x30, 0x31, 0x32, 
          0x37, 0x38, 0x4b, 0x4d, 0x49, 0x30, 0x32, 0x31, 0x4b, 0x7d]
print(decrypt_flag(gzflag))

3.2 2024 N1junior Wasm题目分析

题目特征:

  • 使用Ghidra插件分析
  • 关键函数:main.slice

反编译关键代码:

undefined4 main.slice(int param1, ...) {
    // 多层嵌套的字符检查
    if (*(char *)uVar5 == 'Y') {
        if (*(char *)((int)uVar5 + 1) == '3') {
            if (*(char *)((int)uVar5 + 2) == 'R') {
                // ... 省略多层检查 ...
                if (*(char *)((int)uVar5 + 0x2e) == 'Z') {
                    // 验证通过
                }
            }
        }
    }
}

解题思路:

  1. 提取所有被检查的字符位置和对应值
  2. 组合成疑似Base64编码的字符串
  3. Base64解码获取flag

提取的Base64字符串:

Y3RmcHVua3tXQVNNXzY2NjY2NjZfR09BTE5HXzY2NjY2NjZ9

解码结果:

ctfpunk{WASM_6666666_GOALNG_6666666}

4. 最佳实践建议

  1. 工具选择

    • 快速分析:优先使用Ghidra+Wasm插件
    • 深度分析:结合wasm2c和IDA Pro
    • 动态调试:Chrome开发者工具
  2. 分析技巧

    • 注意内存操作函数(如unnamed_function_14可能是malloc)
    • 关注字符串操作和字符转换逻辑
    • 识别常见的加密模式(如凯撒变种、Base64等)
  3. 效率提升

    • 建立Wasm分析模板
    • 熟悉常见Wasm运行时函数
    • 结合静态分析和动态调试
  4. 常见模式识别

    • 字符转换循环(如大小写转换)
    • 模运算加密(常见于CTF题目)
    • 多层嵌套判断(可能是简单比对)

5. 总结

WebAssembly逆向工程在2024年已经发展出成熟的方法论:

  • Ghidra插件显著降低了入门门槛
  • 静态分析结合动态调试是最佳实践
  • Wasm题目常包含字符操作和简单加密
  • Base64编码在Wasm题目中频繁出现

随着Wasm应用越来越广泛,掌握其逆向技术将成为安全研究人员的必备技能。

WebAssembly逆向工程实战指南 1. WebAssembly简介 WebAssembly(简称Wasm)是一种新兴的低级字节码格式,设计用于提升Web应用程序的性能和效率。主要特点包括: 接近原生代码的执行速度 跨平台特性(浏览器、服务器、嵌入式设备) 紧凑的二进制格式 内存安全沙箱环境 Wasm逆向工程已成为CTF竞赛和实际安全研究中的重要技能。 2. Wasm逆向工程方法论 2.1 工具链准备 必备工具: WABT工具包 (WebAssembly Binary Toolkit): wasm2wat:将.wasm转换为可读的.wat文本格式 wasm2c:将.wasm转换为C代码 反编译工具: IDA Pro 9.0+ : 支持Wasm反汇编 目前缺乏反编译功能(截至2024年) Ghidra + Wasm插件 : 提供完整的反编译支持 插件地址:https://github.com/nneonneo/ghidra-wasm-plugin/ 动态分析工具 : Chrome开发者工具 VSCode + Node.js插件 2.2 逆向流程 方法一:WABT + IDA组合 优势:利用IDA强大的分析能力 劣势:流程较为繁琐 方法二:Ghidra插件"一把梭" 优势: 安装简单 快速反编译 适合快速分析 劣势: 反编译质量有时不理想 复杂代码处理能力有限 方法三:动态调试 Chrome开发者工具: 支持设置断点 实时查看内存和调用栈 参考资源:https://panda0s.top/2021/05/14/WebAssembly-Reverse/ 3. 实战案例分析 3.1 2024源鲁杯Round2 Wasm题目分析 题目特征: 提供单个wasm文件 使用Ghidra插件直接反编译 关键函数分析: 解题脚本: 3.2 2024 N1junior Wasm题目分析 题目特征: 使用Ghidra插件分析 关键函数:main.slice 反编译关键代码: 解题思路: 提取所有被检查的字符位置和对应值 组合成疑似Base64编码的字符串 Base64解码获取flag 提取的Base64字符串: Y3RmcHVua3tXQVNNXzY2NjY2NjZfR09BTE5HXzY2NjY2NjZ9 解码结果: ctfpunk{WASM_6666666_GOALNG_6666666} 4. 最佳实践建议 工具选择 : 快速分析:优先使用Ghidra+Wasm插件 深度分析:结合wasm2c和IDA Pro 动态调试:Chrome开发者工具 分析技巧 : 注意内存操作函数(如unnamed_ function_ 14可能是malloc) 关注字符串操作和字符转换逻辑 识别常见的加密模式(如凯撒变种、Base64等) 效率提升 : 建立Wasm分析模板 熟悉常见Wasm运行时函数 结合静态分析和动态调试 常见模式识别 : 字符转换循环(如大小写转换) 模运算加密(常见于CTF题目) 多层嵌套判断(可能是简单比对) 5. 总结 WebAssembly逆向工程在2024年已经发展出成熟的方法论: Ghidra插件显著降低了入门门槛 静态分析结合动态调试是最佳实践 Wasm题目常包含字符操作和简单加密 Base64编码在Wasm题目中频繁出现 随着Wasm应用越来越广泛,掌握其逆向技术将成为安全研究人员的必备技能。