一、简介
通过该技术可以不使用 LoadLibrary
将 dll 加载到内存。实现该技术的经典项目:stephenfewer/ReflectiveDLLInjection。
git clone https://github.com/stephenfewer/ReflectiveDLLInjection.git
仓库中有两个项目:dll、inject,dll 项目实现了 ReflectiveLoader
函数并导出,该函数内部实现了将 PE 字节加载到内存的过程。inject 项目展示了如何在目标进程中调用 ReflectiveLoader
实现远程 LoadLibrary
。
二、ReflectiveLoader 实现
ReflectiveLoader 实现过程共分 8 步:
2.1 计算 PE 镜像基址
这里使用了 VS 中提供的内部指令 _ReturnAddress
获取到一个镜像区域中的内存地址(caller 函数调用的下一条指令地址),然后向前查找直到找到 PE 头标志:
caller
定义:
参考:MSDN
2.2 从进程 PEB 中获取几个必要的函数地址
后面加载 IAT、修复重定向时必须要用到的几个函数:
LoadLibraryA
:动态加载 dllGetProcAddress
:获取 API 地址VirtualAlloc
:分配内存NtFlushInstructionCache
:修复重定向之后,需要刷新指令缓存
这几个函数分别在 kernel32.dll
和 ntdll.dll
中,一般进程都会加载这两个 dll,所以直接从当前进程中获取这几个函数的地址:
首先先获取 PEB 基址:
获取模块列表,并计算每个模块名字的 hash:
如果是 KERNEL32
模块,则读取模块的函数导出目录信息:
通过 hash 确定 LoadLibraryA
、GetProcAddress
、VirtualAlloc
三个 API 函数的地址:
如果是 NTDLL
模块,一样的方式找到 NtFlushInstructionCache
函数地址:
2.3 载入镜像到新分配的内存
从 PE 头中获取镜像大小,然后分配同等大小的 RWX
内存,将 PE 头逐字节复制到新的内存位置:
这步感觉没有必要,原区域已经是 RWX
权限了,而且直接分配 RWX
权限内存是非常敏感的操作,最好是先 RW
,写入之后再改成 RX
,而且只有 .text
扇区是需要 RX
权限的。
2.4 将所有节复制到新分配的内存
从 PE 头读取节地址信息,依次复制到新内存:
2.5 处理导入表
获取导入表地址,并使用 uiValueC
变量遍历导入项:
使用前面获取的 LoadLibraryA
函数依次导入模块:
接下来修复 IAT
表中的导入函数地址,如果是通过序号导入则手动解析模块导出函数地址,否则直接使用 GetProcAddress
函数得到地址:
2.6 修复重定向
将镜像新的内存基址修复到 relocation
节:
2.7 调用 DLLMain
从 OptionalHeader
中得到 DLLMain
地址,在修复过基址之后要调用 NtFlushInstructionCache
函数刷新指令缓存,然后再执行 DLLMain
函数:
2.8 返回 DLLMain 地址
非必须的一步,将 DLLMain
地址作为 ReflectiveLoader
的返回值:
三、LoadRemoteLibraryR 实现
在 inject
项目中,main
函数通过调用 LoadRemoteLibraryR
将 ReflectiveLoaderDLL
注入到目标进程:
LoadRemoteLibraryR
实现相对简单,通过普通的 dll 注入手法,利用 VirtualAllocEx
函数在目标进程内存空间分配 RWX
内存,调用 WriteProcessMemory
函数将 dll 写入到目标进程中,调用 CreateRemoteThread
创建远程线程执行 ReflectiveLoader
:
四、内存特征
内存区域为 RWX
权限,并且区域开头为标准的 PE 头,即以 MZ
开头:
五、参考链接
- https://github.com/stephenfewer/ReflectiveDLLInjection
- https://docs.microsoft.com/zh-tw/cpp/c-runtime-library/reference/rotl-rotl64-rotr-rotr64?view=msvc-160
- https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress?view=msvc-160
- https://www.ired.team/offensive-security/code-injection-process-injection/reflective-dll-injection
- https://github.com/volatilityfoundation/volatility/wiki/Command-Reference-Mal