1. 原理
主要通过API:CreateRemoteThread 来进行远程线程注入
2.远程线程注入Dll的步骤
1.通过进程Id打开指定的进程 2.在指定的进程,分配一段大小为要导入的dll文件名长度的一段内存空间,将dll的文件名写入到分配的内存中。 3.获取目的进程中的loadLibrary的函数地址。 4.创建远程线程,通过上一步获得的loadlibrary函数进行dll导入。 5.释放内存,卸载dll。
3.代码远程注入注意点
1.不能调用除kernel32和user32之外动态库中的api函数。 2.不能使用static字符串 3. 去掉编译器的/GZ编译选项。这个选项是默认的,不然注入进去被注入的程序会崩溃。 4. 要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。 5. ThreadFunc中的局部变量总大小必须小于4k字节。注意,当degug编译时,这4k中大约有10个字节会被事先占用。 (注入64位的程序,那么也需要64位的dll,主要用的函数:NtCreateThreadEx)
4.代码实现
//提升权限 BOOL cRemoteThreadInject::grantPriviledge(char* priName) { if(NULL == priName) { return FALSE; } TOKEN_PRIVILEGES tokenPriviledge, oldPriviledge; DWORD dwRetLength = sizeof(oldPriviledge); HANDLE tokenHandle = NULL; LUID uId; if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &tokenHandle)) { if (ERROR_NO_TOKEN != GetLastError()) { return FALSE; } if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle)) { return FALSE; } } if (!LookupPrivilegeValue(NULL, priName, &uId)) { CloseHandle(tokenHandle); tokenHandle = NULL; return FALSE; } tokenPriviledge.PrivilegeCount = 1; tokenPriviledge.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tokenPriviledge.Privileges[0].Luid = uId; if (!AdjustTokenPrivileges(tokenHandle, FALSE, &tokenPriviledge, sizeof(TOKEN_PRIVILEGES), &oldPriviledge, &dwRetLength)) { CloseHandle(tokenHandle); tokenHandle = NULL; return FALSE; } return TRUE; }
/* 函数功能:通过进程名称获取进程PID 参数1:进程名称 参数2:返回的进程pid */ BOOL cRemoteThreadInject::GetProcessId(IN char* processName, OUT DWORD* processId) { if(NULL == processName) { return FALSE; } HANDLE handle = NULL; PROCESSENTRY32 processTry32 ={0}; processTry32.dwSize = sizeof(PROCESSENTRY32); handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(INVALID_HANDLE_VALUE == handle) { return FALSE; } Process32First(handle, &processTry32); do{ if(lstrcmpi(processTry32.szExeFile, processName) == 0) { *processId = processTry32.th32ProcessID; break; } }while(Process32Next(handle, &processTry32)); CloseHandle(handle); handle = NULL; if(0 == *processId) { return FALSE; } return TRUE; }
/* 功能:注入dll文件到进程 参数1:进程的名称 参数2:注入dll的路径 */ BOOL cRemoteThreadInject::injectDll(char* processName, char* dllPath) { if((NULL == processName) || (NULL == dllPath)) { return FALSE; } DWORD processId = 0; GetProcessId(processName, &processId); if(processId <= 0) { return FALSE; } grantPriviledge("SE_DEBUG_NAME"); HANDLE handle = NULL; handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if(NULL == handle) { return FALSE; } int dllPathLen = sizeof(dllPath) +1; PVOID data = VirtualAllocEx(handle, NULL, dllPathLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(NULL == data) { CloseHandle(handle); handle = NULL; return FALSE; } SIZE_T RetLength = 0; BOOL bWriteMem = WriteProcessMemory(handle, data, dllPath, strlen(dllPath)+1, &RetLength); if(FALSE == bWriteMem) { return FALSE; } LPTHREAD_START_ROUTINE LoadLibraryAddress = NULL; #ifdef _UNICODE HMODULE Kernel32Module = GetModuleHandle(L"Kernel32"); LoadLibraryAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryW"); #else HMODULE Kernel32Module = GetModuleHandle(_T("Kernel32")); LoadLibraryAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryA"); #endif HANDLE Threadhandle = CreateRemoteThread(handle, NULL, 0, LoadLibraryAddress, data, 0, NULL); if (NULL == Threadhandle) { CloseHandle(handle); handle = NULL; return FALSE; } if (WaitForSingleObject(Threadhandle, INFINITE) == WAIT_FAILED) { return FALSE; } CloseHandle(handle); handle = NULL; CloseHandle(Threadhandle); Threadhandle = NULL; return TRUE; }
/* 函数功能:卸载注入到进程后的dll 参数1:进程的名称 参数2:要卸载的dll */ BOOL cRemoteThreadInject::unitInjectDll(char* processName, char* dllPath) { if((NULL == processName) || (NULL == dllPath)) { return FALSE; } DWORD processId = 0; GetProcessId(processName, &processId); if(processId <= 0) { return FALSE; } BOOL bMore = FALSE; BOOL bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; HMODULE hModule = NULL; MODULEENTRY32 me = {sizeof(me)}; LPTHREAD_START_ROUTINE pThreadProc; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId); bMore = Module32First(hSnapshot, &me); for(; bMore; bMore = Module32Next(hSnapshot, &me)) { if(!_tcsicmp(me.szModule, dllPath) || !_tcsicmp(me.szExePath, dllPath)) { bFound = TRUE; break; } } if(!bFound) { CloseHandle(hSnapshot); return FALSE; } hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if(NULL == hProcess) { return FALSE; } hModule = GetModuleHandle("kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hProcess); hProcess = NULL; CloseHandle(hThread); hThread = NULL; CloseHandle(hSnapshot); hSnapshot = NULL; return TRUE; }
最后:
最近我整理了整套 《JAVA核心知识点总结》,说实话 ,作为一名Java程序员,不论你需不需要面试都应该好好看下这份资料。
版权申明:本站文章均来自网络,如有侵权,请联系01056159998 邮箱:itboby@foxmail.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有