1.什么是DLL注入技术?
让进程主动加载指定DLL的技术
1.1常见的DLL注入技术容易被检测到
需要恶意DLL以文件的形式存在于目标主机,留痕容易被检测到
1.2反射式DLL注入的优点体现在什么方面?
恶意DLL可以通过Socket等方式直接传输到目标进程内存并加载,无文件落地
1.3根本区别在于常规的DLL注入中,恶意DLL会在目标主机上出现
而反射型DLL利用自编写的函数实现直接的内存映射,无额外的DLL落地
2.常规的DLL注入的实现思路
2.1实现思路
- 在被注入进程中创建线程进行DLL注入,使用到的API函数包括CreateRemoteThread()/NtCreateThread()/RtCreateUserThread()
- 实现思路如下:
-
-
-
- 获取被注入进程的PID
- 在被注入进程的访问令牌中开启SE_DEBUG_NAME权限(允许一个进程打开并访问其他进程调试信息的权限)
- 使用openOpenProcess()函数获取目标进程的句柄
- 使用VirtualAllocEx()函数在被注入进程内开辟缓冲区并使用WriteProcessMemory()函数写入DLL路径的字符串
- 使用GetProcAddress()函数在当前进程加载的kernel32.dll找到LoadLibraryA函数的地址
- 通过CreateRemoteThread()函数调用LoadLibraryA()函数,在被注入进程新启动一个新的线程,新的线程来加载恶意的DLL
-
-
-
- 劫持被注入进程已存在的线程加载DLL,使用到的API函数包括QueueUserAPC()/SetThreadContext()
- 设置钩子拦截事件,SetWindowsHookEx()
3反射型DLL的实现思路
3.1根本区别
反射式DLL注入自己实现了一个reflective loader()函数来代替系统kernel32.dll中 的LoadLibrary函数去加载DLL
3..2reflective loader的实现思路(内存映射)
-
-
- 获取被注入进程尚未解析的DLL的基地址
- 获取DLL句柄和函数
- 分配新内存去取解析DLL,将PE头和各个节复制到新内存中
- 修复导入表和重定向表
- 执行DLLMain()函数
-
4.反射型DLL的检测方法
4.1内存扫描-----扫描策略
1.Hook敏感API,当发生敏感API调用序列时,对注入进程和被注入进程进行内存扫描
2.内存完整性扫描,内存完整性校验或hash值比对
4.2可能的监测点
1.强特征匹配_ReturnAddress()函数
rule StrongFeature_ReturnAddress
{
strings:
$function = "ReturnAddress()"
condition:
$function
}
2.扫描DLL注入过程中特定的HASH函数和hash值
计算HASH值的工具
Hasher
3.整体检测DLL注入,检测DLL注入前后的PE文件
文件差异工具
WinMerge WinMerge - You will see the difference…
Beyond Compare 下载 | Beyond Compare 中文官方网站
5.反思
免杀方式和应对策略
1.避免调用直接的API,转向系统调用,成功绕过用户态HOOk
对于内核态的HOOK可以解决
2.不直接将权限全部放开,而是只修改为rx,成功了绕过对rwx权限修改的成功匹配
-
- 擦除nt头和dos头。这种免杀方式会直接让检测点4)影响较大,不能简单的校验pe头了,需要加入更精确的确定两个dll的文件,比如说,首先通过读取未解析的dll的SizeOfImage的大小,然后去找此大小的内存块,然后对比代码段是否一致,去判断是否为同一pe文件。
- 抹除未解析pe文件的内存。这种免杀方式会导致检测点4)彻底失效,这种情况下我们只能对reflectiveloader()函数进行检测。
- 抹除reflectiveloader()函数的内存。这里就比较难检测了。但是也是有检测点的,这里关键是如何确定这块内存是pe结构,重建pe结构之后,我们可以通过导出表去看导出函数是否被抹除。
参考文献:深入理解反射式dll注入技术 - SecPulse.COM | 安全脉搏
https://www.youtube.com/watch?v=p-ufU9W1i7Q&list=RDLVp-ufU9W1i7Q&index=2