从SRDI原理剖析再到PE2Shellcode的实现
字数 1963 2025-08-30 06:50:11

SRDI原理剖析与PE2Shellcode实现技术详解

一、RDI与SRDI技术概述

1.1 RDI(反射式DLL注入)技术

RDI(Reflective DLL Injection)是一种无文件落地的高级内存注入技术,其核心流程包括:

  1. 动态获取基址:通过回溯机制或当前位置+偏移计算基址
  2. 加载PE文件到内存
    • 申请RWX权限内存
    • 复制PE头到新内存
    • 按VirtualAddress字段展开各节到内存
  3. 修复导入表:遍历导入表,获取函数地址填入IAT
  4. 修复重定位表:修正硬编码的绝对地址
  5. 调整内存保护属性:根据节属性设置相应权限
  6. 执行TLS回调:处理DLL_PROCESS_ATTACH回调
  7. 执行入口点:调用DllMain或main函数

1.2 SRDI(Shellcode反射式DLL注入)技术

SRDI是RDI的进化形式,将ReflectLoader转换为位置无关的shellcode,使其能在内存直接执行。关键特性:

  • 将RDI置于PE文件头部或尾部形成整体
  • PE文件自带加载器,实现PE2Shellcode功能
  • 相比传统RDI具有更高的灵活性和隐蔽性

二、SRDI实现原理详解

2.1 加载PE文件到内存(LoadPEIntoMemory64)

; 约定:
; [rbp+8] = 旧DOS头地址(基址)
; [rbp+16] = 新DOS头地址(基址)
; [rbp+24] = 新NT头地址

; 关键偏移量:
; SizeOfImage: NT头偏移50h
; SizeOfHeaders: NT头偏移54h
; NumberOfSections: NT头偏移6
; SectionHeader.VirtualAddress: 节头偏移0Ch
; SectionHeader.PointerToRawData: 节头偏移14h
; SectionHeader.SizeOfRawData: 节头偏移10h

2.2 修复重定位表(FixRelocations)

; 关键数据结构:
; IMAGE_DATA_DIRECTORY (重定位目录)
; IMAGE_BASE_RELOCATION (重定位块)
; 重定位项(16位,高4位类型,低12位偏移)

; 处理流程:
1. 计算基址偏移量:Delta = NewBase - ImageBase
2. 定位重定位目录:NT头偏移0B0h
3. 遍历重定位块:
   - VirtualAddress=0时终止
4. 处理重定位项:
   - 类型为IMAGE_REL_BASED_DIR64(10)才处理
   - 偏移 = 项值 & 0FFFh
   - 修正地址 = 基址 + VirtualAddress + 偏移

2.3 解析导入表(ParseImportTable)

; 关键偏移量:
; 导入目录: NT头偏移90h
; IMAGE_IMPORT_DESCRIPTOR.Name: 导入描述符偏移0Ch
; OriginalFirstThunk(INT): 导入描述符偏移0
; FirstThunk(IAT): 导入描述符偏移10h

; 处理流程:
1. 遍历导入描述符数组(全零结构终止)
2. 加载DLL(通过Name字段)
3. 遍历导入函数:
   - 按序号导入(高位=1): 使用低16位序号
   - 按名称导入(高位=0): 使用IMAGE_IMPORT_BY_NAME
4. 将函数地址填入IAT

2.4 调整内存保护属性(AdjustMemProtect)

; 创新性权限映射方案:
1. 获取节属性Characteristics(节头偏移24h)
2. 保留第30-32位(执行/读/写标志)
3. 右移29位得到3位标志组合
4. 通过预定义的ProtectionTable映射到PAGE_*常量

; ProtectionTable定义:
db 00h, 01h, 02h, 03h, 04h, 05h, 06h, 07h
; 对应权限:
; 000b=0 PAGE_NOACCESS
; 001b=1 PAGE_EXECUTE
; 010b=2 PAGE_READONLY
; 011b=3 PAGE_EXECUTE_READ
; 100b=4 PAGE_WRITECOPY
; 101b=5 PAGE_EXECUTE_WRITECOPY
; 110b=6 PAGE_READWRITE
; 111b=7 PAGE_EXECUTE_READWRITE

2.5 执行TLS回调(ExecuteTLSCallbacks)

; 关键偏移量:
; TLS数据目录: NT头偏移0D0h
; AddressOfCallBacks: TLS目录偏移18h

; 处理流程:
1. 定位TLS数据目录
2. 获取回调函数数组地址
3. 遍历数组执行DLL_PROCESS_ATTACH回调

2.6 执行入口点(GoToEntry)

; 关键偏移量:
; Characteristics(文件类型): NT头偏移16h
; AddressOfEntryPoint: NT头偏移28h

; 处理逻辑:
1. 检查文件类型(EXE:010F, DLL:210E)
2. 为DLL入口预留32字节栈空间
3. 调用入口点函数

三、SRDI实现方案

3.1 前置式RDI(Front-Style)

特点

  • RDI位于PE文件之前
  • 需要引导程序(Bootstrap)
  • 支持EXE/DLL

引导程序关键逻辑

  1. 保存非易失性寄存器
  2. 计算DLL位置:当前IP + 固定偏移
  3. 切换堆栈并预留空间
  4. 调用ReflectiveLoader
  5. 恢复寄存器状态

注意事项

  • RSP对齐问题(需保持16字节对齐)
  • DLL入口需要预留32字节栈空间
  • 需正确处理返回地址

3.2 后置式RDI(Post-Style)

特点

  • RDI位于PE文件末尾
  • 修改DOS头作为stub
  • 支持EXE/DLL

stub关键逻辑

  1. 计算RDI位置(PE文件大小 + 固定偏移)
  2. 跳转到RDI执行
  3. 寄存器保护和恢复移到RDI内部

优势

  • 可消除部分PE特征
  • 不需要单独的引导程序

3.3 内嵌式RDI(Embed-Style)

特点

  • RDI作为DLL导出函数
  • 必须保留"MZ"签名
  • 仅支持DLL

关键技术

  1. 将"MZ"(4D5A)作为指令(pop r10)
  2. 导出函数ReflectiveLoader
  3. RVA到文件偏移转换公式:
    文件偏移 = PointerToRawData + (RVA - VirtualAddress)

四、关键技术要点总结

  1. PE结构掌握:深入理解PE文件各字段偏移量是关键基础
  2. 内存权限控制:创新的权限位映射方案大幅简化代码
  3. 位置无关代码:所有地址引用必须相对偏移,不能有绝对地址
  4. 调用约定遵守:x64调用约定和栈对齐要求必须严格遵守
  5. 动态API解析:通过hash算法动态获取API地址
  6. 调试技巧:Windbg动态调试是验证shellcode的关键手段

五、附录:关键PE结构偏移表

结构字段 偏移量
IMAGE_DOS_HEADER.e_lfanew 3Ch
IMAGE_OPTIONAL_HEADER64.SizeOfImage 50h
IMAGE_OPTIONAL_HEADER64.SizeOfHeaders 54h
IMAGE_FILE_HEADER.NumberOfSections 6
IMAGE_SECTION_HEADER.VirtualAddress 0Ch
IMAGE_SECTION_HEADER.PointerToRawData 14h
IMAGE_SECTION_HEADER.SizeOfRawData 10h
IMAGE_SECTION_HEADER.Characteristics 24h
重定位数据目录 0B0h
导入数据目录 90h
TLS数据目录 0D0h
IMAGE_FILE_HEADER.Characteristics 16h
OptionalHeader.AddressOfEntryPoint 28h
SRDI原理剖析与PE2Shellcode实现技术详解 一、RDI与SRDI技术概述 1.1 RDI(反射式DLL注入)技术 RDI(Reflective DLL Injection)是一种无文件落地的高级内存注入技术,其核心流程包括: 动态获取基址 :通过回溯机制或当前位置+偏移计算基址 加载PE文件到内存 : 申请RWX权限内存 复制PE头到新内存 按VirtualAddress字段展开各节到内存 修复导入表 :遍历导入表,获取函数地址填入IAT 修复重定位表 :修正硬编码的绝对地址 调整内存保护属性 :根据节属性设置相应权限 执行TLS回调 :处理DLL_ PROCESS_ ATTACH回调 执行入口点 :调用DllMain或main函数 1.2 SRDI(Shellcode反射式DLL注入)技术 SRDI是RDI的进化形式,将ReflectLoader转换为位置无关的shellcode,使其能在内存直接执行。关键特性: 将RDI置于PE文件头部或尾部形成整体 PE文件自带加载器,实现PE2Shellcode功能 相比传统RDI具有更高的灵活性和隐蔽性 二、SRDI实现原理详解 2.1 加载PE文件到内存(LoadPEIntoMemory64) 2.2 修复重定位表(FixRelocations) 2.3 解析导入表(ParseImportTable) 2.4 调整内存保护属性(AdjustMemProtect) 2.5 执行TLS回调(ExecuteTLSCallbacks) 2.6 执行入口点(GoToEntry) 三、SRDI实现方案 3.1 前置式RDI(Front-Style) 特点 : RDI位于PE文件之前 需要引导程序(Bootstrap) 支持EXE/DLL 引导程序关键逻辑 : 保存非易失性寄存器 计算DLL位置:当前IP + 固定偏移 切换堆栈并预留空间 调用ReflectiveLoader 恢复寄存器状态 注意事项 : RSP对齐问题(需保持16字节对齐) DLL入口需要预留32字节栈空间 需正确处理返回地址 3.2 后置式RDI(Post-Style) 特点 : RDI位于PE文件末尾 修改DOS头作为stub 支持EXE/DLL stub关键逻辑 : 计算RDI位置(PE文件大小 + 固定偏移) 跳转到RDI执行 寄存器保护和恢复移到RDI内部 优势 : 可消除部分PE特征 不需要单独的引导程序 3.3 内嵌式RDI(Embed-Style) 特点 : RDI作为DLL导出函数 必须保留"MZ"签名 仅支持DLL 关键技术 : 将"MZ"(4D5A)作为指令(pop r10) 导出函数ReflectiveLoader RVA到文件偏移转换公式: 文件偏移 = PointerToRawData + (RVA - VirtualAddress) 四、关键技术要点总结 PE结构掌握 :深入理解PE文件各字段偏移量是关键基础 内存权限控制 :创新的权限位映射方案大幅简化代码 位置无关代码 :所有地址引用必须相对偏移,不能有绝对地址 调用约定遵守 :x64调用约定和栈对齐要求必须严格遵守 动态API解析 :通过hash算法动态获取API地址 调试技巧 :Windbg动态调试是验证shellcode的关键手段 五、附录:关键PE结构偏移表 | 结构字段 | 偏移量 | |---------|-------| | IMAGE_ DOS_ HEADER.e_ lfanew | 3Ch | | IMAGE_ OPTIONAL_ HEADER64.SizeOfImage | 50h | | IMAGE_ OPTIONAL_ HEADER64.SizeOfHeaders | 54h | | IMAGE_ FILE_ HEADER.NumberOfSections | 6 | | IMAGE_ SECTION_ HEADER.VirtualAddress | 0Ch | | IMAGE_ SECTION_ HEADER.PointerToRawData | 14h | | IMAGE_ SECTION_ HEADER.SizeOfRawData | 10h | | IMAGE_ SECTION_ HEADER.Characteristics | 24h | | 重定位数据目录 | 0B0h | | 导入数据目录 | 90h | | TLS数据目录 | 0D0h | | IMAGE_ FILE_ HEADER.Characteristics | 16h | | OptionalHeader.AddressOfEntryPoint | 28h |