一道CTF解题之旅
字数 949 2025-08-15 21:30:57

CTF解题教学:nsPack壳脱壳与异或加密逆向分析

1. 题目概况

  • 来源:攻防世界Reserve:040
  • 难度:★★★
  • 保护措施:nsPack压缩壳
  • 程序类型:Win32控制台程序
  • 加密方式:异或加密

2. 脱壳过程详解

2.1 侦壳

使用侦壳工具确认程序使用了nsPack压缩壳。

2.2 使用OllyDbg(OD)脱壳

  1. 初始加载

    • 使用OD载入程序
    • 观察压缩壳标志性指令pushad
    • 按F8单步两步,注意只有ESP寄存器发生变化
  2. ESP定律脱壳法

    • 在ESP所在的内存地址下硬件访问断点
    • 按F9运行程序
    • 程序会在popfd指令处停下(与前面的pushad对应)
    • 观察下方的jmp指令,这是跳回程序原始入口点(OEP)的指令
  3. Dump内存

    • 到达OEP后,右键选择"dump内存"
    • 点击"获取EIP作为OEP"
    • 重要:记录修正后的地址,后续修复导入表需要
  4. 修复导入表

    • 使用导入表修复工具
    • 选择之前保存的脱壳文件
    • 按照工具指引完成修复

2.3 脱壳总结

脱nsPack压缩壳的三个关键步骤:

  1. 找到OEP地址
  2. dump内存
  3. 修复导入表

3. 逆向分析

3.1 IDA静态分析

  1. 输入验证:

    • 输入字符串长度必须大于0x2A(42)字节
  2. 加密方式:

    • 使用异或加密
    • 加密后需要再次异或相同值才能解密

3.2 OD动态调试

  1. 关键数据:
    • 异或使用的密钥字符串:"this_is_not_flag"
    • 比较的密文字符串:正好0x2A(42)字节

4. 解题脚本

void DecodeCTF40() {
    char Str[] = { 
        0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A, 
        0x10, 0x67, 0x00, 0x41, 0x00, 0x01, 0x46, 0x5A, 0x44, 0x42, 
        0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 
        0x02, 0x01, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68, 
        0x5B, 0x12 
    };
    
    char keyStr[] = "this_is_not_flag";
    int keyCount = 0;
    
    for(int i = 0; i <= 0x2A; ++i) {
        keyCount = i % 16;
        Str[i] ^= keyStr[keyCount];
        printf("%c", Str[i]);
    }
}

脚本解析:

  1. 密文数据:42字节的加密数据
  2. 密钥:"this_is_not_flag"(16字节)
  3. 解密逻辑
    • 循环处理每个密文字节
    • 使用i % 16循环使用密钥的每个字符
    • 密文字节与密钥字符异或得到明文
    • 直接输出解密结果

5. 关键知识点总结

  1. nsPack壳特征

    • 标志性指令pushad
    • 使用ESP定律是最有效的脱壳方法
  2. 脱壳三要素

    • 准确找到OEP
    • 完整dump内存
    • 正确修复导入表
  3. 异或加密特点

    • 可逆性:A ^ B ^ B = A
    • 密钥循环使用:当密钥比明文短时,通常会循环使用
  4. CTF解题技巧

    • 静态分析与动态调试结合
    • 注意程序对输入长度的验证
    • 识别加密模式(本例为简单的异或加密)
CTF解题教学:nsPack壳脱壳与异或加密逆向分析 1. 题目概况 来源:攻防世界Reserve:040 难度:★★★ 保护措施:nsPack压缩壳 程序类型:Win32控制台程序 加密方式:异或加密 2. 脱壳过程详解 2.1 侦壳 使用侦壳工具确认程序使用了nsPack压缩壳。 2.2 使用OllyDbg(OD)脱壳 初始加载 : 使用OD载入程序 观察压缩壳标志性指令 pushad 按F8单步两步,注意只有ESP寄存器发生变化 ESP定律脱壳法 : 在ESP所在的内存地址下硬件访问断点 按F9运行程序 程序会在 popfd 指令处停下(与前面的 pushad 对应) 观察下方的 jmp 指令,这是跳回程序原始入口点(OEP)的指令 Dump内存 : 到达OEP后,右键选择"dump内存" 点击"获取EIP作为OEP" 重要 :记录修正后的地址,后续修复导入表需要 修复导入表 : 使用导入表修复工具 选择之前保存的脱壳文件 按照工具指引完成修复 2.3 脱壳总结 脱nsPack压缩壳的三个关键步骤: 找到OEP地址 dump内存 修复导入表 3. 逆向分析 3.1 IDA静态分析 输入验证: 输入字符串长度必须大于0x2A(42)字节 加密方式: 使用异或加密 加密后需要再次异或相同值才能解密 3.2 OD动态调试 关键数据: 异或使用的密钥字符串:"this_ is_ not_ flag" 比较的密文字符串:正好0x2A(42)字节 4. 解题脚本 脚本解析: 密文数据 :42字节的加密数据 密钥 :"this_ is_ not_ flag"(16字节) 解密逻辑 : 循环处理每个密文字节 使用 i % 16 循环使用密钥的每个字符 密文字节与密钥字符异或得到明文 直接输出解密结果 5. 关键知识点总结 nsPack壳特征 : 标志性指令 pushad 使用ESP定律是最有效的脱壳方法 脱壳三要素 : 准确找到OEP 完整dump内存 正确修复导入表 异或加密特点 : 可逆性:A ^ B ^ B = A 密钥循环使用:当密钥比明文短时,通常会循环使用 CTF解题技巧 : 静态分析与动态调试结合 注意程序对输入长度的验证 识别加密模式(本例为简单的异或加密)