Injection Method
R3 Dll 注入方式总结
1. SetWindowsHookEx 方法
该方法主要通过注册 指定线程(dwThreadId) 的 Windows 消息事件(idHook)的回调函数(lpfn)来进行注入 当 dwThreadId 设为 0 或者不是由当前进程创建的线程时,该 hook 函数(lpfn)必须存在于 指定的 dll (hMod)中 eg. SetWindowsHookEx(WH_CBT, MyHookProc, MyDll, 0)
,当系统中有线程触发 WH_CBT事件后,系统自动将 MyDll载入该线程中,并执行 MyHookProc,以此实现 Dll 注入
2. CreateRemoteThread 方法
该方法在CreateRemoteThread 在目标进程中创建一个线程,再通过 新创建的线程进行dll注入 获取函数 LoadLibrary 在内存中的地址
在目标进程空间给将要注入的dll路径字符串(形如“c:\my.dll”)分配空间
将dll路径 写入目标进程空间
创建远程线程
通过该方法创建的线程,其创建进程和父进程均为 目标进程 !
另:还可以通过RtlCreateUserThread 和 NtCreateThread 函数进行注入,但这两个函数没有从ntdll.dll导出,因此需要手动寻找这两个函数的地址。注入原理和 CreateRemoteThread非常相似,只是替换了CreateRemoteThread 来在目标进程中创建线程,因此将它们归为一类
2.5 Reflective Dll Injection
该方法依然使用线程创建函数在目标进程中创建线程, 但不是通过使线程执行 LoadLibrary 来载入线程
具体过程比较复杂,简述如下:
将需要载入的dll的文件内容读入内存中(读入其二进制代码)
搜索其PE头,查找该dll 的入口地址(EntryPoint:DllMain) (关键一步)
将其入口地址(DllMain)直接作为 线程创建函数的线程起始地址(lpStartAddress)
创建远程线程
3. QueueUserApc 方法
该方法和 CreateRemoteThread 类似,将实现注入功能的函数(pfnAPC)加入目标线程的 APC 队列中,当目标线程(hThread)通过 SleepEx、WaitForSingleObject 、WaitForMultipleObject 等过程 变为 Alertable 状态 时,该线程将依次调用其APC队列中的函数,并以dwData作为传入参数,以此实现dll注入
和 CreateRemoteThread相同,pfnAPC 指向 LoadLibrary 的内存地址,dwData则为需要注入的dll的 路径
(目标线程的状态必须为 Alertable,否则不会执行 APC )
4. SetThreadContext 方法
该方法原理是 通过 SetThreadContext 函数更改 目标进程上下文中的指令指针(EIP for x86),跳转到目标进程中我们写入的内存区域,并开始执行,以此实现dll注入或任意代码执行。
由于该方法无法传递参数,因此需要在目标进程中写入一段 汇编代码 用于处理参数并调用 LoadLibrary,然后将EIP指向该段代码起始地址,汇编码如下所示:
(写入内容实际是汇编代码对应的机器码)
注入流程简述如下:
获取 LoadLibrary 内存地址 - loadLibraryAddr
在目标进程中申请内存,将dll路径写入 - remoteDllAddr
在目标进程中申请内存,用于保存shellcode - remoteShellcodeAddr
使用 SuspendThread(htargetThread)
挂起目标线程,并使用GetThreadContext(targetThread, &context)
获取线程上下文 context
存储 context中的原EIP并更新 EIP
替换 shellcode中的相关地址参数
将shellcode写入目标进程并开始执行
总结
当前 Windows 平台用户层的注入方法主要为以上4种,其共同点为均需要在目标进程的内存中申请空间来保存相关参数,再通过创建远程线程或注入shellcode的方式直接或间接调用 LoadLibrary 来载入dll (Reflective Injection 除外)
因此涉及到的函数主要有VirtualAlloc(Ex)、WriteProcessMemory、VirtualProtect(Ex)
, 为保证这些函数成功执行,其传入的目标进程句柄(hProcess)必须拥有相应的权限,通常进程句柄通过 OpenProcess 获取
PROCESS_ALL_ACCESS包括以下 等 特定权限:
PROCESS_TERMINATE
PROCESS_CREATE_THREAD PROCESS_DUP_HANDLE PROCESS_SET_INFORMATION PROCESS_VM_OPERATION PROCESS_VM_READ PROCESS_VM_WRITE
而以上函数要求进程句柄至少具有 PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION, PROCESS_VM_WRITE 权限
防御
在我们的驱动中,对打开进程或线程句柄的操作注册了回调函数,当某一个进程句柄被请求时,回调函数首先查看DesiredAccess
参数,如果相应权限位被置1,则将该位置为0(即拒绝该权限的请求行为),因此通过OpenProcess函数返回的句柄将不具有 读写内存或进行内存操作的权限,以此来防御 dll 注入
目前为止,驱动可以防御住所有的用户层 针对特定进程的 dll 注入行为
Last updated