免杀基础-peloader
字数 1882 2025-08-29 08:30:18

PE Loader 免杀基础教学文档

1. PE文件加载概述

PE文件不同于shellcode,不能直接执行,需要经过以下步骤加载:

  1. 内存映射PE文件
  2. 修复重定位表
  3. 修复导入表
  4. 修正内存权限
  5. 执行OEP(原始入口点)

2. 内存映射PE文件

2.1 PE文件拉伸

  • 读取PE文件到内存中并拉伸
  • 需要解析PE头部结构,包括DOS头、NT头和节表
  • 根据节表信息将各节数据映射到内存中正确位置

3. 修复重定位表

3.1 重定位表作用

  • 当加载内存基址不同于ImageBase时,需要修复重定位表
  • 重定位表中的每一项包含原始地址和需要修正的偏移量

3.2 重定位表结构

  • 使用BASE_RELOCATION_ENTRY结构
  • 后4位Type表示重定位类型
  • 前12位是偏移量

4. 修复导入表(IAT)

4.1 导入表修复原理

  • IAT中的地址也是基于ImageBase的
  • 需要根据实际加载基址重新计算导入函数地址
  • 需要解析IMAGE_DIRECTORY_ENTRY_IMPORT目录项

5. 修正内存权限

5.1 内存权限设置

  • 初始拉伸PE使用RW(读写)权限的内存
  • 根据节表(IMAGE_SECTION_HEADER)的Characteristics属性设置正确权限
  • 可执行代码段需要设置可执行权限

6. 执行OEP

  • 调用PE文件的原始入口点(OEP)开始执行
  • 需要正确处理调用约定和参数传递

7. 修复异常表(64位系统)

7.1 异常表处理

  • 64位PE文件如果涉及SEH(结构化异常处理),需要修复异常表
  • IMAGE_DIRECTORY_ENTRY_EXCEPTION包含多个RUNTIME_FUNCTION结构
  • 使用RtlAddFunctionTable函数添加到动态函数表列表

8. 修复TLS(线程局部存储)

8.1 TLS回调处理

  • TLS回调运行在PE入口点之前
  • 需要解析IMAGE_DIRECTORY_ENTRY_TLS目录项
  • 正确处理TLS回调函数

9. 参数处理

9.1 命令行参数处理

  • 跟进invoke_main函数可以找到__p___argv__p___argv(来自ucrtbase.dll)
  • 通过交叉引用找到common_configure_argv_char_
  • 进一步找到__acrt_initialize_command_line
  • 最终在Kernelbase.dll中找到KernelBaseBaseDllInitialize
  • 可以直接修改PEB->ProcessParameters.CommandLine来设置命令行参数

10. DLL加载特殊处理

10.1 执行DllMain

  • 与EXE类似,但需要调用DllMain函数
  • 需要正确处理DLL_PROCESS_ATTACH等通知

10.2 执行导出函数

  • 需要解析导出表获取函数地址
  • 使用GetProcAddress或手动解析导出表
  • 创建线程执行目标导出函数

11. 关键数据结构

11.1 PE结构相关

  • IMAGE_DOS_HEADER
  • IMAGE_NT_HEADERS
  • IMAGE_SECTION_HEADER
  • IMAGE_DATA_DIRECTORY

11.2 重定位相关

  • IMAGE_BASE_RELOCATION
  • BASE_RELOCATION_ENTRY

11.3 导入表相关

  • IMAGE_IMPORT_DESCRIPTOR
  • IMAGE_THUNK_DATA

11.4 导出表相关

  • IMAGE_EXPORT_DIRECTORY

12. 关键API函数

  • VirtualAlloc/VirtualProtect - 内存分配和权限设置
  • RtlAddFunctionTable - 添加异常处理表
  • GetProcAddress - 获取函数地址
  • CreateThread - 创建执行线程

13. 实现注意事项

  1. 正确处理PE文件对齐和内存对齐差异
  2. 确保所有指针和地址计算都考虑实际加载基址
  3. 处理可能存在的资源段和调试信息
  4. 考虑ASLR(地址空间布局随机化)的影响
  5. 处理可能存在的反调试和反虚拟机技术

14. 免杀相关技巧

  1. 使用不常见的内存分配方式
  2. 动态计算关键API地址而非直接导入
  3. 混淆或加密关键代码段
  4. 延迟加载非必要模块
  5. 模拟正常程序的内存访问模式

以上是PE Loader实现的关键知识点和技术细节,涵盖了从PE文件加载到执行的完整流程,包括各种特殊情况处理和免杀相关技术。

PE Loader 免杀基础教学文档 1. PE文件加载概述 PE文件不同于shellcode,不能直接执行,需要经过以下步骤加载: 内存映射PE文件 修复重定位表 修复导入表 修正内存权限 执行OEP(原始入口点) 2. 内存映射PE文件 2.1 PE文件拉伸 读取PE文件到内存中并拉伸 需要解析PE头部结构,包括DOS头、NT头和节表 根据节表信息将各节数据映射到内存中正确位置 3. 修复重定位表 3.1 重定位表作用 当加载内存基址不同于ImageBase时,需要修复重定位表 重定位表中的每一项包含原始地址和需要修正的偏移量 3.2 重定位表结构 使用 BASE_RELOCATION_ENTRY 结构 后4位Type表示重定位类型 前12位是偏移量 4. 修复导入表(IAT) 4.1 导入表修复原理 IAT中的地址也是基于ImageBase的 需要根据实际加载基址重新计算导入函数地址 需要解析IMAGE_ DIRECTORY_ ENTRY_ IMPORT目录项 5. 修正内存权限 5.1 内存权限设置 初始拉伸PE使用RW(读写)权限的内存 根据节表(IMAGE_ SECTION_ HEADER)的Characteristics属性设置正确权限 可执行代码段需要设置可执行权限 6. 执行OEP 调用PE文件的原始入口点(OEP)开始执行 需要正确处理调用约定和参数传递 7. 修复异常表(64位系统) 7.1 异常表处理 64位PE文件如果涉及SEH(结构化异常处理),需要修复异常表 IMAGE_ DIRECTORY_ ENTRY_ EXCEPTION包含多个RUNTIME_ FUNCTION结构 使用 RtlAddFunctionTable 函数添加到动态函数表列表 8. 修复TLS(线程局部存储) 8.1 TLS回调处理 TLS回调运行在PE入口点之前 需要解析IMAGE_ DIRECTORY_ ENTRY_ TLS目录项 正确处理TLS回调函数 9. 参数处理 9.1 命令行参数处理 跟进 invoke_main 函数可以找到 __p___argv 和 __p___argv (来自ucrtbase.dll) 通过交叉引用找到 common_configure_argv_char_ 进一步找到 __acrt_initialize_command_line 最终在Kernelbase.dll中找到 KernelBaseBaseDllInitialize 可以直接修改PEB->ProcessParameters.CommandLine来设置命令行参数 10. DLL加载特殊处理 10.1 执行DllMain 与EXE类似,但需要调用DllMain函数 需要正确处理DLL_ PROCESS_ ATTACH等通知 10.2 执行导出函数 需要解析导出表获取函数地址 使用 GetProcAddress 或手动解析导出表 创建线程执行目标导出函数 11. 关键数据结构 11.1 PE结构相关 IMAGE_ DOS_ HEADER IMAGE_ NT_ HEADERS IMAGE_ SECTION_ HEADER IMAGE_ DATA_ DIRECTORY 11.2 重定位相关 IMAGE_ BASE_ RELOCATION BASE_ RELOCATION_ ENTRY 11.3 导入表相关 IMAGE_ IMPORT_ DESCRIPTOR IMAGE_ THUNK_ DATA 11.4 导出表相关 IMAGE_ EXPORT_ DIRECTORY 12. 关键API函数 VirtualAlloc / VirtualProtect - 内存分配和权限设置 RtlAddFunctionTable - 添加异常处理表 GetProcAddress - 获取函数地址 CreateThread - 创建执行线程 13. 实现注意事项 正确处理PE文件对齐和内存对齐差异 确保所有指针和地址计算都考虑实际加载基址 处理可能存在的资源段和调试信息 考虑ASLR(地址空间布局随机化)的影响 处理可能存在的反调试和反虚拟机技术 14. 免杀相关技巧 使用不常见的内存分配方式 动态计算关键API地址而非直接导入 混淆或加密关键代码段 延迟加载非必要模块 模拟正常程序的内存访问模式 以上是PE Loader实现的关键知识点和技术细节,涵盖了从PE文件加载到执行的完整流程,包括各种特殊情况处理和免杀相关技术。