DLL转shellcode研究
昨天重新看到了dll转shellcode的文章想分析一下原理,所以
有了这篇文章。
实现DLL加载两个方法
1.从DIRECTORY_ENTRY_EXPORT寻找ReflectiveLoader函数,修补之后利用该函数加载DLL
2.实现一段LoadPE的shellcode,DLL跟在后面
DLL加载原理
启动一个可执行模块的时候,操作系统的加载程序会先为进程创建虚拟地址空间,接着把可执行模块映射到进程的地址空间中.之后加载程序会检查可执行模块的导入段, 试图对所需的DLL进行定位并将它们映射到进程的地址空间中. 由于导入段只包含DLL的名称,不包含DLL的路径,因此加载程序必须在用户的磁盘上搜索DLL. 下面是加载程序的搜索顺序: (1) 包含可执行文件的目录; (2) Windows的系统目录; GetSystemDirctory (3) 16位的系统目录, 即Windows/System (4) Windows目录 GetWindowsDirectory (5) 进程的当前目录; (6) PATH 环境变量中所列出的目录;
工具的使用
import-module \.ConvertTo-Shellcode.ps1
$c=ConvertTo-Shellcode .\test.dll
$d=$c |%{write-output ([system.string]::format('{0:X2}',$_))}
$d -join "" | Out-File shellcode.txt
得到shellcode.txt py转换一下直接执行shellcode或者把得到的十六进制用010editor十六进制写入到某文件嵌套到资源里读取执行
shellcode执行测试
原理分析
它的原理是在不改变MZ标志的情况下把整个dll文件修补成可被当作shellcode加载的格式,具体的操作为在dll内导出自加载函数(ReflectiveLoader)然后讲MZ头起始字节修改成执行ReflectiveLoader函数的硬编码
WBG的描述:
其实所谓的修补反射dll其实就是修改dll头部让其变成汇编指令去调用ReflectiveLoader函数然后ReflectiveLoader函数会经过一系列处理最后会调用DllMain。这时这个dll就像shellcode一样可以直接执行,其实我们所做的就是解析dll找到ReflectiveLoader函数并将其地址硬编码写到Dll头部然后call
自己实现具体过程:
- 定位DLL文件在内存中的基址
- 获取所需的系统API
- 分配一片用来装载DLL的空间
- 复制PE文件头和各个节
- 处理DLL的引入表
- 对DLL进行重定位
- 调用DLL入口点
目前网上的版本有两种:
* 带解压缩的版本:先把dll压缩然后在构造一段解压数据的C编译后提取ASM,然后将DLL拼接到后面 ->看雪那个就是这样
* 不带压缩版本:直接修补,去掉MZ头
两个版本的都看了分析一下
带压缩版本的:利用RtlGetCompressionWorkSpaceSize和RtlCompressBuffer实现数据压缩,然后修补DLL
WBG版本的修补:
* 从DIRECTORY_ENTRY_EXPORT寻找ReflectiveLoader函数,修补之后利用该函数加载DLL
ConvertTo-Shellcode.py分析
->读取DLL数据,传入ConvertToShellcode() -> 中间调用了一个HashFunctionName函数计算arguments.function_name
HashFunction函数
(计算函数hash)
ConvertToShellcode函数
->判断DLL是否为64位
->根据对应的位数取LoadPE的shellcode
->bootstrap拼接对应的指令
->bootstrap + rdiShellcode + dllBytes + userData
大概如下:
call <xxx>
pop eax
push ebp
mov ebp,esp
mov edx,eax
add eax,<DLL偏移量>
add edx,<DLL偏移量>+<DLL大小>
push <flags>
push 0
push edx
push <functionHash>
push eax
call <DLL>
add esp,0x14
leave
ret
.............
<LOADPE_ShellCode>
.............
<DLLBytest>
指定dll生成bin,丢golink生成exe
入口点:
dword_401C04是DLL bytes
->从PEB里寻找ntdll.dll的LdrLoadDLL函数
->从PEB里寻找ntdll.dll的LdrGetProcAddress函数
->利用LdrLoadDLL加载Kernel32.dll
->加载VirtuaLLoc函数
->加载VirtualProtect函数
->加载FlushInstructionCache函数
->加载GetNativeSysteminfo函数
->加载Sleep函数
->加载RtlAddFunctionTable函数
->加载LoadlibraryA函数
->判断对应的DLL函数是否加载成功
->DLL各个区段赋值变量
->调用GetNativeSystemInfo函数
->Virtualloc修改内存可读可写
->复制PE文件头和各个节
->处理DLL的引入表
->对DLL进行重定位
->调用FlushInstructionCache刷新内存
->加载DLLMain函数
最后的启动顺序
(图片来源WBG)
参考链接
参考链接:
https://wbglil.github.io/2020/03/27/%E5%85%B3%E4%BA%8E%E5%8F%8D%E5%B0%84dll%E4%BF%AE%E8%A1%A5/
https://www.ired.team/offensive-security/code-injection-process-injection/reflective-shellcode-dll-injection
https://idiotc4t.com/defense-evasion/reflectivedllinjection-variation
https://www.cnblogs.com/h2zZhou/p/7721797.html
现成工具:
https://github.com/monoxgas/sRDI/blob/7889036a75e3aca65a2c01ee8f5549ed779a4c1f/PowerShell/ConvertTo-Shellcode.ps1
https://github.com/stephenfewer/ReflectiveDLLInjection - 划重点
WBG的项目:
https://github.com/WBGlIl/ReflectiveDLL_Patch/blob/master/ReflectiveDLL_Patch.py
https://github.com/WBGlIl/go-ReflectiveDLL
看雪的项目:https://github.com/killeven/DllToShellCode/tree/master/DllToShellCode
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
文章标题:DLL转shellcode研究
本文作者:九世
发布时间:2021-09-09, 17:18:53
最后更新:2021-09-09, 17:41:31
原始链接:http://jiushill.github.io/posts/8f26af05.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。