免杀基础-peloader
字数 1882 2025-08-29 08:30:18
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文件加载到执行的完整流程,包括各种特殊情况处理和免杀相关技术。