最近在整理学习Windows注入方面的知识,这个远程注入前面早写过,现在看看人家博客的理解整理,整理,
需要源码的可以到我的github上下载。
链接是 https://github.com/Arsense/WindowsCode
首先先来说说什么是注入,为什么要注入
0x00 Baise
注入就是把自己的Dll注入到人家的代码中,被注入的DLL拥有目标进程内存的访问权限,所以我们可以通过该
向某个进程注入DLL时的方法主要有以下三种:
- 创建远程线程(CreateRemoteThread() API)
- 使用注册表(AppInit_DLLs值)
- 消息钩取(SetWindowsHookEx())
1.CreateRemoteHook 实际上是个比较简单的HOOK
下面看HOOK的步骤
技术向目标程序增加或修改某些功能
0×01 远程线程注入方法CreateRemoteThread
1. 使用VirtualAllocEx在目标进程的地址空间中创建一块我们DLL所在路径长度的内存空间。
2. 使用WriteProcessMemory将DLL路径写入分配的内存。
3. 一旦DLL路径写入内存中,再使用CreateRemoteThread(或者其他无正式说明的功能),它再调用LoadLibrary函数将DLL注入目标进程中。
0×02 Windows功能的暗点
在Windows中无正式说明的功能是指在微软当中没有详细文档介绍其信息的这些功能。这样在使用这些功能就会存在一些问题。最明显的问题就是没有一个特定功能的文档。不过在 ReactOS项目中对许多这种功能做了文档说明,而这篇文章则给了我们最直观的理解。此外在微软没有正式通过的情况先,这些功能可能最终会被“越界”使用。最后呢,他们都需要更多的代码,了解并需要正确使用。
试想一下这些问题,为何要使用这些无正式说明的功能?基本的原因就是自从Vista之后,如果目标进程不在当前会话中而是在一个不同的会话中,那么CreateRemoteThread将会失效。而这些无正式说明功能就不会。当然这个从逆向工程的角度也不会立即就能理解。最后这个只过是在Windows中一些不知名的功能中捣点小乱而已。
在我们的代码中,我们使用CreateRemote 线程和两个无正式说明的函数NtCreateThreadEx 和RtlCreateUserThread。也许你听说过Mimikatz 和 Metasploit。这两个都是使用RtlCreateUserThread来实现DLL注入的。如果你想看这些代码,Mimikatz可以在这里找到,Meterpreter则在这里。需要说明的是Mimikatz的博客是法语,如果有语言障碍则可以看这里。
那么这两个函数该挑选哪一个呢?NtCreateThreadEx是一个系统调用,是用户空间应用和内核打交道的方法。快速在IDA中查通过名字标签找到看一下RtlCreateUserThread。将ntdll.dll拖进IDA中,通过名字标签找到RtlCreateUserThread,
后面会发现发现,RtlCreateUserThread调用NtCreateThreadEx 。因此RtlCreateUserThread应该是NtCreateThreadEx 的封装。我们想调用RtlCreateUserThread是因为NtCreateThreadEx 的系统调用选项可以在Windows版本间改变。因此,RtlCreateUserThread更好用一些。 Mimikatz 和Meterpreter使用RtlCreateUserThread是由于这个选项更加安全。
0×03 代码
对下面的代码进行一些改进,下面使用CreateRemoteThread方法一步步实现上述步骤:
1. 使用VirtualAllocEx在目标进程的地址空间中创建一块我们DLL所在路径长度的内存空间。
//This dll path should be relative to the target process or an absolute path char* dll = "inject.dll"; //We need a handle to the process we will be injecting into HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); //Create the space needed for the dll we are going to be injecting LPVOID lpSpace = (LPVOID)VirtualAllocEx(hProcess, NULL, strlen(dll), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
2.使用WriteProcessMemory将DLL路径写入分配的内存
//Write inject.dll to memory of process int n = WriteProcessMemory(hProcess, lpSpace, dll, strlen(dll), NULL);
3. 一旦DLL路径写入内存中,再使用CreateRemoteThread(或者其他无正式说明的功能),它再调用LoadLibrary函数将DLL注入目标进程中。
HMODULE hModule = GetModuleHandle("kernel32.dll"); LPVOID lpBaseAddress = (LPVOID)GetProcAddress(hModule,"LoadLibraryA"); //Create Remote Thread using the address to LoadLibraryA and the space for the DLL hThread = CreateRemoteThread(hProcess, NULL, , (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, NULL, NULL);