PE免杀 ---> PE加壳01

目录

什么是壳及其原理

壳的定义:

壳的原理(详细逻辑):

壳的知识点以及原理

壳本质上就是对PE文件上的一种应用

正常情况我们需要在源码加(壳代码)

核心概念匹配

也就是加密混淆的代码

程序开始运行的时候首先走到壳代码:

这是加壳的经典流程

额外知识:

PE文件的基本结构介绍

原理解释:

案例:

壳在PE文件中的作用

原理解释:

加壳过程对PE结构的修改

原理解释:

案例:

脱壳与反向工程

原理解释:


什么是壳及其原理

  • 壳是软件加壳技术,用于保护PE可执行文件。

  • 原理是附加一段自执行代码,控制原始代码的加载和执行。以下详细输出原理逻辑,补充缺失的部分如内存分配细节,并以文本模式画出通讯流程图和调用逻辑图。

    +---------------+ +---------------+
    | 系统加载器 | ----> | PE头部检查 |
    +---------------+ +---------------+
    | |
    v v
    +---------------+ +---------------+
    | 执行壳入口 | <---- | 解密/解压 |
    +---------------+ +---------------+
    | |
    v v
    +---------------+ +---------------+
    | 修复导入表 | ----> | 跳转OEP |
    +---------------+ +---------------+

壳的定义:

壳(Packer/Shell)是一种程序,附加到目标PE上,形成新PE,运行时先运行壳代码,处理原始内容后转移控制。

壳的原理(详细逻辑):

  1. 附加壳代码到PE新节或覆盖。

  2. 修改PE头ImageBase、EntryPoint指向壳。

  3. 运行时,壳分配内存,解压/解密原始镜像。

  4. 修复重定位、导入表(补充:使用GetProcAddress动态加载API)。

  5. 跳转到原始OEP执行。


壳的知识点以及原理

壳本质上就是对PE文件上的一种应用

  • 加密壳

  • 免杀壳

  • 虚拟化壳

  • 压缩壳

    • 反调试

    • 反虚拟机

正常情况我们需要在源码加(壳代码)

  • 如果我们是壳直接对exe程序直接的附加然后我们exe有附加的功能,就不需要直接在线程开一个tls不断监视是否被调试。

  • 壳的定义:壳是一段程序代码,它被加入到PE(Portable Executable)文件的结构中。

  • 功能:壳代码为原有程序"包裹"了一层,目的是保护原始代码,防止被直接查看或修改。

  • 执行过程

    • 当程序运行时,首先执行壳代码,然后壳代码会处理代码段解密或解压的操作,最后跳转到原始程序的入口点,继续执行原有程序的逻辑。

核心概念匹配

  • 在末尾节或者新节的部分加入新的代码

  • 是的,这是典型的加壳实现方式。PE文件(Windows的可执行文件格式)由多个节(Section)组成,加壳工具通常会:

    • 在现有节(如.text或.data)的末尾追加壳代码和加密后的原代码(如果空间足够)。

    • 或者添加一个全新的节(例如名为.UPX或自定义名称),用于存放壳代码和打包后的数据。

    • 这避免了直接修改原有节的内容,保持文件结构的完整性。


也就是加密混淆的代码

  • 加入的"新代码"主要是壳代码(shell code),它本身可能被混淆或加密,但更重要的是,壳代码负责处理原程序的加密/压缩部分。

  • 原程序的代码、资源等通常会被压缩(e.g., 使用LZMA、UPX算法)或加密(e.g., XOR、AES),然后存储在壳中。

  • 壳代码的目的是在运行时"脱壳"(unpack),恢复原内容。所以,不是所有新代码都只是"加密混淆",而是壳 + 加密后的原内容。

程序开始运行的时候首先走到壳代码

  • 加壳后,PE文件的入口点(Entry Point,在IMAGE_NT_HEADERS中的AddressOfEntryPoint字段)会被修改为指向壳代码的地址。

  • 这样,Windows加载器(loader)启动程序时,会先执行壳代码,而不是直接跳到原入口点(OEP - Original Entry Point)。

  • 壳代码运行完成后走到原始入口点 执行原有程序的代码

这是加壳的经典流程

  1. 分配内存。

  2. 解压缩/解密原代码和资源。

  3. 修复导入表(IAT - Import Address Table)、重定位等PE结构(因为解压后地址可能变化)。

  4. 跳转(jump)到OEP,继续执行原程序逻辑。

  5. 用户感觉上程序"正常运行",但实际上多了一个前置的脱壳过程。

    +---------------+ // 系统API调用加载PE
    | LoadLibrary |
    +---------------+
    |
    v
    +---------------+ // 检查PE签名,映射到内存
    | PE解析器 |
    +---------------+
    | // 如果加壳,入口指向壳
    v
    +---------------+ // 壳代码启动,分配额外内存
    | Shell_Init | <-- VirtualAlloc(SizeOfImage)
    +---------------+
    |
    v
    +---------------+ // 遍历节,XOR解密每个字节
    | DecryptSections | // 补充:检查Characteristics是否CODE/DATA
    +---------------+
    |
    v
    +---------------+ // 动态加载DLL,填充IAT
    | FixImports | <-- GetProcAddress(kernel32, "Function")
    +---------------+
    |
    v
    +---------------+ // 调整地址偏移
    | RelocateBase | // 补充:ImageBase + RVA计算
    +---------------+
    |
    v
    +---------------+ // 转移控制
    | JumpToOEP |
    +---------------+

额外知识

  • 加壳有不同类型,如压缩壳(UPX)、加密壳(ASPack)、保护壳(Armadillo)。

  • 有些壳还会添加反调试、反虚拟机检查,以增加破解难度。

  • 脱壳后,程序在内存中恢复原貌,但文件本身仍是被加壳的。

总体来说

  • 如果想深入,可以学习PE文件格式细节或试用工具如PEiD来分析加壳文件。

PE文件的基本结构介绍

原理解释:

  1. PE文件从DOS头开始,用于兼容旧系统。

  2. 跟随NT头,包含文件签名和头部信息。

  3. 然后是节头,描述每个节的位置和属性。

  4. 最后是节数据,如代码、数据等。

通俗来说,PE像一栋楼:DOS头是旧大门,NT头是总蓝图,节头是房间目录,节是实际房间。

案例:

  • 一个简单的exe文件,如notepad.exe,其PE结构可以通过工具如PEView查看:

  • DOS头偏移0x3C指向NT头,NT头有"PE\0\0"签名。

壳在PE文件中的作用

原理解释:

  1. 壳代码附加到PE末尾或新节中。

  2. 修改PE入口点到壳代码。

  3. 运行时,壳先执行,解开原始代码。

  4. 跳转到原始入口点(OEP)。

  • 通俗如包裹礼物:壳是外包装,打开后露出原物,但包装有锁(加密)。

  • 案例: 使用UPX壳压缩一个exe,文件大小变小,运行时自动解压。

加壳过程对PE结构的修改

原理解释:

  1. 添加新节存放壳代码。

  2. 更新节头数量和虚拟大小。

  3. 加密原始节数据。

  4. 重定位导入地址表(IAT)。

通俗比喻:像装修房子,加壳是加一层防护墙,调整门窗(入口和导入)。

案例:

  • 一个未加壳的hello.exe,加壳后节数从3增加到4,新节名为.UPX0含加密数据。

脱壳与反向工程

  • "脱壳是逆向壳过程,恢复原始PE"。

原理解释:

  1. 调试运行到壳解开时刻。

  2. 转储内存中的解开代码。

  3. 修复PE头和重定位。

  4. 保存为新PE文件。

通俗:像剥洋葱,层层去除壳,露出核心。

案例: 使用OllyDbg调试加壳exe,设置断点于跳转OEP,dump内存修复。