反射型DLL注入

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()
    • 实现思路如下:
        1. 获取被注入进程的PID
        2. 在被注入进程的访问令牌中开启SE_DEBUG_NAME权限(允许一个进程打开并访问其他进程调试信息的权限)
        3. 使用openOpenProcess()函数获取目标进程的句柄
        4. 使用VirtualAllocEx()函数在被注入进程内开辟缓冲区并使用WriteProcessMemory()函数写入DLL路径的字符串
        5. 使用GetProcAddress()函数在当前进程加载的kernel32.dll找到LoadLibraryA函数的地址
        6. 通过CreateRemoteThread()函数调用LoadLibraryA()函数,在被注入进程新启动一个新的线程,新的线程来加载恶意的DLL

    • 劫持被注入进程已存在的线程加载DLL,使用到的API函数包括QueueUserAPC()/SetThreadContext()
    • 设置钩子拦截事件,SetWindowsHookEx()

3反射型DLL的实现思路

3.1根本区别

反射式DLL注入自己实现了一个reflective loader()函数来代替系统kernel32.dll中 的LoadLibrary函数去加载DLL

3..2reflective loader的实现思路(内存映射)

      1. 获取被注入进程尚未解析的DLL的基地址
      2. 获取DLL句柄和函数
      3. 分配新内存去取解析DLL,将PE头和各个节复制到新内存中
      4. 修复导入表和重定向表
      5. 执行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权限修改的成功匹配

    1. 擦除nt头和dos头。这种免杀方式会直接让检测点4)影响较大,不能简单的校验pe头了,需要加入更精确的确定两个dll的文件,比如说,首先通过读取未解析的dll的SizeOfImage的大小,然后去找此大小的内存块,然后对比代码段是否一致,去判断是否为同一pe文件。
    2. 抹除未解析pe文件的内存。这种免杀方式会导致检测点4)彻底失效,这种情况下我们只能对reflectiveloader()函数进行检测。
    3. 抹除reflectiveloader()函数的内存。这里就比较难检测了。但是也是有检测点的,这里关键是如何确定这块内存是pe结构,重建pe结构之后,我们可以通过导出表去看导出函数是否被抹除。

参考文献:深入理解反射式dll注入技术 - SecPulse.COM | 安全脉搏

https://www.youtube.com/watch?v=p-ufU9W1i7Q&list=RDLVp-ufU9W1i7Q&index=2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当涉及到 DLL 注入反射注入方法时可以使用 C 语言编写一个程序来实现。下是一个示例程序,它演示了如何使用反射注入DLL 注入到目标进程中: ```c #include <stdio.h> #include <windows.h> // 反射注入 DLL 的函数 BOOL ReflectiveDllInjection(LPVOID lpDllBuffer) { // 获取当前进程的基址 HMODULE hModule = GetModuleHandle(NULL); // 获取当前进程的 DOS 头 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; // 获取当前进程的 NT 头 PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + pDosHeader->e_lfanew); // 获取当前进程的映像基址 LPVOID pImageBase = (LPVOID)pNtHeaders->OptionalHeader.ImageBase; // 获取当前进程的入口点函数地址 LPVOID pEntryPoint = (LPVOID)((DWORD_PTR)pImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint); // 为反射注入分配内存 LPVOID pRemoteImageBase = VirtualAllocEx(GetCurrentProcess(), NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 将当前进程的映像基址复制到目标进程中 WriteProcessMemory(GetCurrentProcess(), pRemoteImageBase, pImageBase, pNtHeaders->OptionalHeader.SizeOfImage, NULL); // 将 DLL 缓冲区写入到目标进程中 WriteProcessMemory(GetCurrentProcess(), (LPVOID)((DWORD_PTR)pRemoteImageBase + ((PIMAGE_NT_HEADERS)lpDllBuffer)->OptionalHeader.ImageBase), lpDllBuffer, ((PIMAGE_NT_HEADERS)lpDllBuffer)->OptionalHeader.SizeOfImage, NULL); // 更新目标进程的导入表 PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)pRemoteImageBase + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (pImportDesc->Name != 0) { HMODULE hDll = LoadLibraryA((LPCSTR)((DWORD_PTR)pRemoteImageBase + pImportDesc->Name)); PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)pRemoteImageBase + pImportDesc->FirstThunk); while (pThunk->u1.Function != 0) { DWORD_PTR pFunc = (DWORD_PTR)GetProcAddress(hDll, (LPCSTR)pThunk->u1.Function); WriteProcessMemory(GetCurrentProcess(), &pThunk->u1.Function, &pFunc, sizeof(DWORD_PTR), NULL); pThunk++; } pImportDesc++; } // 创建远程线程来运行目标进程的入口点函数 HANDLE hThread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, (LPTHREAD_START_ROUTINE)pEntryPoint, pRemoteImageBase, 0, NULL); if (hThread == NULL) { return FALSE; } WaitForSingleObject(hThread, INFINITE); // 清理内存 VirtualFreeEx(GetCurrentProcess(), pRemoteImageBase, 0, MEM_RELEASE); return TRUE; } int main() { // 读取 DLL 文件 FILE* fp = fopen("dll_template.dll", "rb"); if (fp == NULL) { printf("无法打开 DLL 文件!\n"); return 1; } // 获取 DLL 文件的大小 fseek(fp, 0, SEEK_END); long fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); // 分配内存来存储 DLL 文件数据 LPVOID lpDllBuffer = malloc(fileSize); // 读取 DLL 文件数据到内存中 fread(lpDllBuffer, fileSize, 1, fp); // 关闭文件 fclose(fp); // 执行反射注入 if (ReflectiveDllInjection(lpDllBuffer)) { printf("DLL 注入成功!\n"); } else { printf("DLL 注入失败!\n"); } // 释放内存 free(lpDllBuffer); return 0; } ``` 上述示例程序中,你需要将要注入DLL 文件命名为 "dll_template.dll",并与程序放在同一目录下。然后编译并运行程序,它将尝试将该 DLL 注入到目标进程中。 请注意,反射注入的程序需要具有管理员权限才能成功运行。此外,反射注入可能会受到一些安全软件的检测,因为它使用了一些与恶意软件类似的技术。 希望这个示例程序能帮助到你!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tntlbb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值