自举的代码幽灵——反射DLL注入(Reflective DLL Injection)
字数 1912 2025-08-29 08:30:19

反射DLL注入(Reflective DLL Injection)技术详解

一、技术概述

反射DLL注入是一种高级的库注入技术,它不依赖Windows提供的LoadLibraryA函数,而是让目标进程主动加载指定的DLL。这种技术通过自实现PE文件映射到内存的过程,规避了传统DLL注入留下的磁盘痕迹,具有优秀的免杀效果。

技术特点:

  1. 不依赖LoadLibraryA函数
  2. DLL以内存形式存在,不留下磁盘痕迹
  3. 绕过传统安全产品的"进程-文件-注册表"三维检测框架
  4. 是现代C2(Command and Control)框架的标配技术

二、注入器(Inject)实现原理

注入流程步骤:

  1. 打开DLL文件,获取文件大小
  2. 创建本地堆空间作为缓冲区
  3. 读取文件内容到缓冲区
  4. 打开目标进程,获取句柄
  5. 在目标进程中申请RWX内存空间并写入DLL
  6. 获取ReflectiveLoader函数在目标进程中的地址
  7. 调用ReflectiveLoader函数

关键技术点:

1. RVA到文件偏移转换

由于DLL以磁盘文件形式存在于内存中,需要将RVA转换为文件偏移:

文件偏移 = 节区文件起始地址(PointerToRawData) + (RVA - 节区虚拟起始地址(VirtualAddress))

2. GetProcAddrByName函数实现

遍历导出表获取ReflectiveLoader函数地址:

  • 解析PE头部定位导出表
  • 遍历导出函数名与目标函数名比对
  • 返回匹配函数的地址

三、反射加载器(ReflectiveLoader)实现原理

主要执行流程:

  1. 暴力搜索DLL基址
  2. 获取所需Windows API
  3. 加载PE文件节到内存
  4. 修复重定位表
  5. 修复导入表
  6. 获取并执行DllMain

1. 暴力搜索DLL基址

  • 从ReflectiveLoader函数地址向前搜索
  • 验证DOS头("MZ")和NT头("PE\0\0")签名
  • 定位有效的PE头部结构

2. 获取所需Windows API

实现GetApiAddressByName函数:

  1. 获取PEB地址
  2. 遍历LDR模块列表查找目标DLL
  3. 解析DLL导出表定位目标API
  4. 返回函数地址

辅助函数:

  • my_towlower: 宽字符转小写
  • MyCompareStringW: 不区分大小写的宽字符串比较
  • MyCompareStringA: ASCII字符串比较
  • ExtractDllName: 从完整路径提取DLL名称

3. 加载PE文件节到内存

  • 使用VirtualAlloc申请RWX内存(SizeOfImage大小)
  • 复制所有头部信息(SizeOfHeaders大小)
  • 映射各节区到内存:
    • 源:PointerToRawData + SizeOfRawData
    • 目标:VirtualAddress + VirtualSize

4. 修复重定位表

重定位表结构:

  • 由多个重定位块组成
  • 每个块对应一个内存页(4KB)
  • 块头为IMAGE_BASE_RELOCATION结构
  • 后跟多个16位重定位项(TypeOffset)

修复过程:

  1. 计算基址偏移量:实际基址 - 预期基址
  2. 定位重定位表(数据目录索引5)
  3. 遍历重定位块和条目
  4. 修正地址:原地址 + 基址偏移量

5. 修复导入表

导入表结构:

  • 由多个IMAGE_IMPORT_DESCRIPTOR组成
  • 每个描述符对应一个导入DLL
  • 包含INT(导入名称表)和IAT(导入地址表)

修复过程:

  1. 遍历导入描述符
  2. 使用LoadLibraryA加载目标DLL
  3. 解析INT获取函数名/序号
  4. 使用GetProcAddress获取函数地址
  5. 将地址写入IAT对应位置

6. 执行DllMain

  • 从PE头部获取EntryPoint地址
  • 调用DllMain函数完成初始化

四、技术变种与优化

  1. 有阶段Beacon:可参考oldboy21/RflDllOb项目实现
  2. 传递参数:通过CreateRemoteThread向ReflectiveLoader传递DLL基址
  3. TLS回调:可添加执行TLS回调函数的步骤
  4. 延迟导入:可添加修复延迟导入表的步骤

五、防御建议

  1. 监控异常内存属性(RWX)
  2. 检测PE头自修改行为
  3. 分析进程中的异常模块加载
  4. 监控API调用序列异常

六、参考资源

  1. stephenfewer/ReflectiveDLLInjection (原始实现)
  2. oldboy21/RflDllOb (Bella实现)
  3. rapid7/ReflectiveDLLInjection (改进版本)
  4. 深入理解反射式dll注入技术 - FreeBuf
  5. 反射DLL注入原理解析 - 先知社区

附录:关键数据结构

// 重定位块头
typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;
    DWORD   SizeOfBlock;
} IMAGE_BASE_RELOCATION;

// 导入描述符
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;
        DWORD   OriginalFirstThunk; // INT RVA
    };
    DWORD   TimeDateStamp;
    DWORD   ForwarderChain;
    DWORD   Name;                   // DLL名称RVA
    DWORD   FirstThunk;             // IAT RVA
} IMAGE_IMPORT_DESCRIPTOR;

通过本文详细解析,读者可以全面理解反射DLL注入技术的原理和实现细节,为安全研究和防御提供技术基础。

反射DLL注入(Reflective DLL Injection)技术详解 一、技术概述 反射DLL注入是一种高级的库注入技术,它不依赖Windows提供的LoadLibraryA函数,而是让目标进程主动加载指定的DLL。这种技术通过自实现PE文件映射到内存的过程,规避了传统DLL注入留下的磁盘痕迹,具有优秀的免杀效果。 技术特点: 不依赖LoadLibraryA函数 DLL以内存形式存在,不留下磁盘痕迹 绕过传统安全产品的"进程-文件-注册表"三维检测框架 是现代C2(Command and Control)框架的标配技术 二、注入器(Inject)实现原理 注入流程步骤: 打开DLL文件,获取文件大小 创建本地堆空间作为缓冲区 读取文件内容到缓冲区 打开目标进程,获取句柄 在目标进程中申请RWX内存空间并写入DLL 获取ReflectiveLoader函数在目标进程中的地址 调用ReflectiveLoader函数 关键技术点: 1. RVA到文件偏移转换 由于DLL以磁盘文件形式存在于内存中,需要将RVA转换为文件偏移: 2. GetProcAddrByName函数实现 遍历导出表获取ReflectiveLoader函数地址: 解析PE头部定位导出表 遍历导出函数名与目标函数名比对 返回匹配函数的地址 三、反射加载器(ReflectiveLoader)实现原理 主要执行流程: 暴力搜索DLL基址 获取所需Windows API 加载PE文件节到内存 修复重定位表 修复导入表 获取并执行DllMain 1. 暴力搜索DLL基址 从ReflectiveLoader函数地址向前搜索 验证DOS头("MZ")和NT头("PE\0\0")签名 定位有效的PE头部结构 2. 获取所需Windows API 实现GetApiAddressByName函数: 获取PEB地址 遍历LDR模块列表查找目标DLL 解析DLL导出表定位目标API 返回函数地址 辅助函数: my_ towlower: 宽字符转小写 MyCompareStringW: 不区分大小写的宽字符串比较 MyCompareStringA: ASCII字符串比较 ExtractDllName: 从完整路径提取DLL名称 3. 加载PE文件节到内存 使用VirtualAlloc申请RWX内存(SizeOfImage大小) 复制所有头部信息(SizeOfHeaders大小) 映射各节区到内存: 源:PointerToRawData + SizeOfRawData 目标:VirtualAddress + VirtualSize 4. 修复重定位表 重定位表结构: 由多个重定位块组成 每个块对应一个内存页(4KB) 块头为IMAGE_ BASE_ RELOCATION结构 后跟多个16位重定位项(TypeOffset) 修复过程: 计算基址偏移量:实际基址 - 预期基址 定位重定位表(数据目录索引5) 遍历重定位块和条目 修正地址:原地址 + 基址偏移量 5. 修复导入表 导入表结构: 由多个IMAGE_ IMPORT_ DESCRIPTOR组成 每个描述符对应一个导入DLL 包含INT(导入名称表)和IAT(导入地址表) 修复过程: 遍历导入描述符 使用LoadLibraryA加载目标DLL 解析INT获取函数名/序号 使用GetProcAddress获取函数地址 将地址写入IAT对应位置 6. 执行DllMain 从PE头部获取EntryPoint地址 调用DllMain函数完成初始化 四、技术变种与优化 有阶段Beacon :可参考oldboy21/RflDllOb项目实现 传递参数 :通过CreateRemoteThread向ReflectiveLoader传递DLL基址 TLS回调 :可添加执行TLS回调函数的步骤 延迟导入 :可添加修复延迟导入表的步骤 五、防御建议 监控异常内存属性(RWX) 检测PE头自修改行为 分析进程中的异常模块加载 监控API调用序列异常 六、参考资源 stephenfewer/ReflectiveDLLInjection (原始实现) oldboy21/RflDllOb (Bella实现) rapid7/ReflectiveDLLInjection (改进版本) 深入理解反射式dll注入技术 - FreeBuf 反射DLL注入原理解析 - 先知社区 附录:关键数据结构 通过本文详细解析,读者可以全面理解反射DLL注入技术的原理和实现细节,为安全研究和防御提供技术基础。