Self-Modified Code

简介

自修改代码(Self-Modified Code)是一类特殊的代码技术,即在运行时修改自身代码,从而使得程序实际行为与反汇编结果不符,同时修改前的代码段数据也可能非合法指令,从而无法被反汇编器识别,这加大了软件逆向工程的难度。

基本原理

SMC的基本原理是在编译可执行文件时,将需要加密的代码区段(例如函数、代码块等)单独编译成一个section(段),并将其标记为可读、可写、不可执行(readable, writable, non-executable),然后通过某种方式在程序运行时将这个section解密为可执行代码,并将其标记为可读、可执行、不可写(readable, executable, non-writable)。这样,攻击者就无法在内存中找到加密的代码,从而无法直接执行或修改加密的代码。

VirtualProtect 函数 (memoryapi.h) - Win32 apps | Microsoft Learn是 Windows 操作系统中的一个 API 函数,它允许应用程序改变一个内存页的保护属性(每次保护常量)。

1
2
3
4
5
6
BOOL VirtualProtect(
LPCVOID lpAddress, // 要改变保护属性的内存页的起始地址
SIZE_T dwSize, // 内存页的大小
DWORD flNewProtect, // 新的保护属性
PDWORD lpflOldProtect // 存储旧的保护属性
);

实现方式

  • SMC的实现方式有很多种:

    • 通过修改PE文件的Section Header

    • 使用API Hook实现代码加密和解密

    • 使用VMProtect等第三方加密工具等

破解方式

  • 自修改代码破解方式:
    • 通过IDA动调,程序始终要根据正确代码来运行,我们就在程序正确的时候,再分析
    • 通过分析加密逻辑,来还原程序
    • 通过Ollydug来dump下正确的逻辑

实例

[MoeCTF2023]SMC

PixPin_2025-03-20_17-08-17

发现VirtualProtect函数,修改了loc_4014D0()权限

PixPin_2025-03-20_17-10-37

双击进入loc_4014D0,发现IDA识别不了

PixPin_2025-03-20_17-16-29

写idapython脚本还原

1
2
3
4
5
for ( i = 0; i < 122; ++i )
{
*((_BYTE *)sub_4014D0 + i) ^= 0x66u;
result = i + 1;
}

PixPin_2025-03-20_17-20-26

选中loc_4014D0(D0到F2),按C转化为汇编代码(force强制),再按选中loc_4014D0:按P创建函数,按F5反编译即可

PixPin_2025-03-20_17-22-34

接着提取byte_40A000[]数据,解密

EXP

1
2
3
4
5
6
7
8
9
enc = [
0x9F, 0x91, 0xA7, 0xA5, 0x94, 0xA6, 0x8D, 0xB5, 0xA7, 0x9C,
0xA6, 0xA1, 0xBF, 0x91, 0xA4, 0x53, 0xA6, 0x53, 0xA5, 0xA3,
0x94, 0x9B, 0x91, 0x9E, 0x8F]
flag = ''
for i in range(len(enc)):
flag += chr((enc[i] ^ 0x39) - 57)
print(flag)
# moectf{Self_Mod1f1cation}

参考链接

探究SMC局部代码加密技术以及在CTF中的运用 - SecPulse.COM | 安全脉搏

CTF Reverse逆向学习之SMC动态代码加密技术-逆向 smc-CSDN博客

文章 - CTF Reverse逆向学习之SMC动态代码加密技术 - 先知社区

【reverse】手把手带你基于dll实现多次SMC - 吾爱破解 - 52pojie.cn

文章 - SMC in CTF - 先知社区

CTF-SMC 逆向练习_ctf smc-CSDN博客