PE 虚拟壳框架,项目用于学习软件保护、PE 加壳、压缩脱壳、IAT 修复和简单虚拟机保护流程。
- 支持一键加壳和一键脱壳。
- 支持 x32/x64,不同平台使用不同压缩库:x32 使用 LZ4,x64 使用 QuickLZ。
- 支持压缩原始区段、清理数据目录和区段文件偏移、运行时解压并修复 IAT。
- x64 包含简单 VM 示例,用于演示代码片段加密、指令解析、分发和上下文维护思路。
代码入口主要参考 MasterWindows::OnBnClickedButton1():
- 拖入目标 PE,
OnDropFiles()记录目标路径,并生成同目录的FileName_CombatShellData.dat路径。 NewSection()调用AddSection添加.VMP区段,用于放入壳代码。CompressionData::CompressSectionData()压缩原 PE 区段数据,新增.UPX区段保存压缩数据,并记录原始数据目录、区段大小、区段偏移和 OEP。studData::LoadLibraryStud()加载CombatShell.dll,定位壳入口。studData::RepairReloCationStud()修复壳代码重定位。studData::CopyStud()将壳代码拷贝到.VMP,并把入口点改到壳入口。- 成功后生成加壳后的目标文件,同时保留
old_原文件名作为备份。
一键加壳成功后,目标文件同目录会生成:
FileName_CombatShellData.dat
该文件用于脱壳恢复,内容包含压缩区段记录、被清理的数据目录、原区段文件信息和原始 OEP。当前实现为了简化流程将这些数据保存到本地文件,后续也可以扩展为写入新增区段。
压缩区段大小记录 | 数据目录记录(16项) | 原区段 SizeOfRawData/PointerToRawData | 原始 OEP
壳入口在 CombatShell/CombatShell.cpp 中:
CombatShellEntry()解析kernel32/user32等必要 API。CreateWind()创建隐藏窗口和辅助线程。ProcessCallBack()触发解压流程;窗口不可用时直接执行解压和跳转。UnCompression()恢复数据目录、区段文件信息,并解压.UPX中的原始区段数据。RepairTheIAT()重新加载导入模块并修复 IAT。- 最后跳转到
ImageBase + 原始 OEP继续执行原程序。
代码入口主要参考 MasterWindows::OnBnClickedButton2():
- 拖入已加壳程序。
UnShell::UnShellEx()读取加壳 PE 和本地FileName_CombatShellData.dat。UnShell::RepCompressionData()根据记录解压.UPX中的原始区段数据。UnShell::DeleteSectionInfo()删除.VMP和.UPX区段信息,恢复数据目录、区段文件偏移、区段大小和 OEP。UnShell::SaveUnShell()重新保存 PE,并替换当前目标文件。
虚拟机目前主要用于 x64 代码片段保护示例,重点是展示 VM 设计思路,而不是完整商业级虚拟化保护。
- 加壳时记录需要 VM 处理的代码偏移、长度和加密后的指令数据。
- 运行时由
VmEntry()进入 VM,读取加密后的代码片段并解密。 VmOpcodeAnalHlper()解析指令语义,例如mov/xor/add/sub/call/jmp。VmCodetoExecDispath()将解析出的指令分发到对应 handler。- handler 维护寄存器和栈上下文,模拟原始指令效果。
项目中的 VM 没有高级算法,只是用于说明 VM 指令解析、分发和上下文维护过程。CompressionData::VmcodeEntry() 中仍有硬编码的 VM 指令行数,后续可以通过反汇编自动分析优化。
注意:当前 VM 示例只覆盖部分指令映射,不是完整指令集。
本项目仅用于学习和研究 PE 结构、软件保护、压缩壳、IAT 修复和虚拟机保护思路,不提供正式 Release 版本。






