首页
社区
课程
招聘
[原创]压缩壳的简单实现
发表于: 2026-7-10 15:55 2320

[原创]压缩壳的简单实现

2026-7-10 15:55
2320

实现一个压缩壳,需要做三步操作,三步过程涉及比较深入的PE结构理解,最终的实现目标如下图所示

其中过程分为以下三步

1、对原有数据压缩

对源程序使用算法进行压缩,并将数据放至目标程序的节表数据二的位置

2、对原有数据还原

编写壳代码,对自身节表二的数据进行压缩算法还原,并将生成的PE文件放至内存或者节表数据一的位置

3、对还原后的数据加载至内存并运行

编写LoadPE加载程序,对加载至内存的代码进行加载

需要编写一个工具程序,将源目标程序变为目标程序的样子,该程序可以为控制台,也可以为其他程序,本文为了方便,编写为MFC程序

1、创建MFC程序

此处选择基于对话框的设计,使用MFC选择在静态库中使用MFC,使用静态库可以将其他库打包进入该程序,相对于共享链接DLL更干净,迁移更方便

2、添加对应的窗体功能

Mfc Edit Browser Control组件,用于选择打开的文件路径,ID此处命名为MEDIT_FILE_PATH

Button Control,用于加壳的入口,此处命名为BTN_PACK,并右键该按钮,添加点击事件

3、添加窗体代码

对传入的文件进行解析,并将其存入变量

使用WinAPI的Compress函数对原始数据进行压缩,得到压缩数据m_pComData

壳代码主要做两件事

完成PE的解压缩

进行PE的加载

创建的PE文件,可能有基址随机化,无重定位修正机制等问题,为了提升壳代码的健壮性,需要用地址无关代码。

我们需要做以下几步

进程在加载时,FS寄存器指向当前活动线程的TEB结构,通过TEB的[0x30]获取到对应的TEB结构,再通过TEB拿到加载的Kernel32的基址

此处为了使用方便,建了一个函数指针的结构体

Kernel32函数基址和想要的名称我们有了,剩下的就是找到对应的函数,需要用到导出表的知识

进行函数调用

首先需要获取当前程序的模块基址,和Kernel32的模块基址获取类似,通过TEB找到PEB,再通过PEB找到模块基址

获取完用户的基址后,再对数据节的代码进行解压缩

LoadPE是模仿操作系统将PE文件按照特定格式加载进内存的操作,并将EIP执行新PE的入口点

PE加载分为两种,一种为进程镂空操作,另一种为反射式加载,这边采用反射式加载的方式,申请一块新内存,并手动解析PE,将其运行。

LoadPE分为以下几步

解析完成后,获取到对应的ImageSize,并使用VirtualAlloc分配内存,尝试使用PE自带的ImageBase,如果能分配成功,则分配至该内存,否则随机分配

基于新的PE基址,算出偏移值和新的入口点地址

通过NTHeader和导入表地址算出导出节表头

进行导入表修复

最后跳转至入口点

写一个壳代码的PE文件分为以下几步

使用WinAPI直接创建即可

PE头主要关注PE内容和对应的写入长度,需要对原始PE文件做解析,获取原始的Header大小和原始的PE文件

同时需要对新的PE头进行修改部分数据

空节无数据,需要在PE头将其内存映射准备好即可

将0x03节的压缩数据放至该节,并使用文件对其的方式进行对齐

壳代码需要将0x04章节的数据生成干净的代码

需要做以下步骤,确保代码入口点为自己的入口代码

最终的代码节如图所示

将生成的代码拷贝为C++代码

完成后,即可完成一个简单的加壳程序

节数量

数据目录表

节表

有三个节,分别为代码节,数据节和壳节

节数据有两个节

1、数据节(原始PE的压缩数据)

2、代码节(壳代码)

内存布局

EIP指针指向.PackSec的入口

参照源码进行对照,前两个为初始化环境变量和获取用户模块基址

跟进初始换环境变量函数

获取kernel32模块基址

跟进调试,成功获取Kernel32基址

将局部变量存入栈

下边获取各个函数地址

GetProcAddress

LoadLibrary

VirtualAlloc

VirtualProtect

使用LoadLibrary加载cabinet库

获取CreateDecompressor函数

获取Decompress函数

下一步获取模块基址

内存如图所示

下一步解析PE数据,找到压缩数据入口和对应的大小,并对压缩数据进行解压缩

DosHeader + 3C的位置得到NTHeader

通过NTHeader的可选头位置+可选头大小得到节表起始位置

获取压缩数据的起始位置,大小

使用函数分配内存,并使用解压函数,将解压后的数据放至内存

成功分配内存,内存地址为0x001D0000

该内存暂时为空数据

后边分别调用创建解压器工具和进行解压操作

DeCompressor创建成功

下一步调用DeCompress函数,将数据段中的数据解压缩至0x001D0000位置处

下一步为模拟操作系统进行加载PE操作

加载PE分为一下几步

1、分配内存

首先尝试在原始PE的ImageBase上分配内存,分配失败则自动分配

调试中,发现需要分配的内存地址为0x00400000


传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!

收藏
免费 1
打赏
分享
最新回复 (2)
雪    币: 204
活跃值: (157)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
源代码程序,欢迎各位大牛指导!
上传的附件:
2026-7-10 16:25
0
雪    币: 9332
活跃值: (4219)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
都用什么软件了,看着挺好看
2026-7-11 16:27
0
游客
登录 | 注册 方可回帖
返回