远程线程注入(三)DLL注入
DLL注入和远程线程注入类似,我们只需要将要执行的函数体放到dll文件中,然后获得kernel32.dll中的LoadLibraryA()和GetProcAddress()的地址,
将这两个函数的地址作为参数传递给远程线程中,利用CreateRemoteThread开启远程线程,在远程线程中加载测试dll文件中即可。
需要用到 远程线程注入(一)中的msg.dll,依然是拿QQ开刀- -
上代码:
//远程DLL注入 #include <windows.h> #include <cstdio> typedef struct _RemotePara { char dwMessageBox[12]; DWORD pLoadlibrary; }RemotePara; //传入到远程线程中的参数 DWORD _stdcall ThreadProc(RemotePara *lpPara) //远程线程函数 { typedef int (_stdcall *MMessageBoxA)(HWND, LPCTSTR, LPCTSTR, DWORD); typedef HINSTANCE (_stdcall *mLoadLibrary)(LPCTSTR); mLoadLibrary myLoadLibrary; myLoadLibrary = (mLoadLibrary) lpPara->pLoadlibrary; myLoadLibrary(lpPara->dwMessageBox); return 0; } void EnableDebugPriv() //提权操作 { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { CloseHandle(hToken); return; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if ( !AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL) ) { CloseHandle(hToken); } } DWORD GetProcessID(char *FileName) //根据进程名,获得进程ID { HANDLE hProcess; PROCESSENTRY32 pe; BOOL bRet; //进行进程快照 hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); pe.dwSize = sizeof(PROCESSENTRY32); //找到第一个进程 bRet = Process32First(hProcess, &pe); //循环比较 while(bRet) { if(strcmp(FileName, pe.szExeFile) == 0) { //返回得到的ProcessID return pe.th32ProcessID; } else { //指向下一个进程 bRet = Process32Next(hProcess,&pe); } } return NULL; } int main() { const DWORD THREADSIZE = 1024 * 4; //4MB的空间 DWORD byte_write; EnableDebugPriv(); //提权 //打开被注入进程 HANDLE hWnd = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessID("QQ.exe")); if (!hWnd) { return 1; } //在被注入进程中申请内存空间 void *pRemoteThread = VirtualAllocEx(hWnd, 0, THREADSIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!pRemoteThread) { return 2; } //将远程线程函数写入被注入进程 if ( !WriteProcessMemory(hWnd, pRemoteThread, (LPCVOID)&ThreadProc, THREADSIZE, 0) ) { return 3; } //为将要传入线程的参数赋值 RemotePara myRemotePara; ZeroMemory(&myRemotePara, sizeof(myRemotePara)); HINSTANCE hker = LoadLibrary("kernel32.dll"); //获得LoadLibraryA的函数地址 myRemotePara.pLoadlibrary = (DWORD)GetProcAddress(hker, "LoadLibraryA"); strcat(myRemotePara.dwMessageBox, "msg.dll"); //相对地址默认是在System32或者SysWOW64里面 FreeLibrary(hker); //在被注入进程中申请传入参数的空间 RemotePara *pRemotePara = (RemotePara *)VirtualAllocEx(hWnd, 0, sizeof(RemotePara), MEM_COMMIT, PAGE_READWRITE); if (!pRemotePara) { return 4; } //将参数写入被注入进程 if ( !WriteProcessMemory(hWnd, pRemotePara, &myRemotePara, sizeof(RemotePara), 0) ) { return 5; } //启动远程线程 HANDLE hTread = CreateRemoteThread(hWnd, 0, 0, (DWORD(_stdcall *)(void *))pRemoteThread, pRemotePara, 0, &byte_write); if (!hTread) { return 6; } return 0; }
注入Dll:
1,OpenProcess获得要注入进程的句柄
2,VirtualAllocEx在远程进程中开辟出一段内存,长度为strlen(dllname)+1;
3,WriteProcessMemory将Dll的名字写入第二步开辟出的内存中。
4,CreateRemoteThread将LoadLibraryA作为线程函数,参数为Dll的名称,创建新线程
5,CloseHandle关闭线程句柄
卸载Dll:
1,CreateRemoteThread将GetModuleHandle注入到远程进程中,参数为被注入的Dll名
2,GetExitCodeThread将线程退出的退出码作为Dll模块的句柄值。
3,CloseHandle关闭线程句柄
3,CreateRemoteThread将FreeLibraryA注入到远程进程中,参数为第二步获得的句柄值。
4,WaitForSingleObject等待对象句柄返回
5,CloseHandle关闭线程及进程句柄。
——现在的努力是为了小时候吹过的牛B!!