前段时间,在论坛看到了这篇文章--> [翻译]十种注入技巧:具有通用性的进程注入技巧研究后,想仔细学习进程注入。平时分析会多些,但很少去实现,如果文章中哪里有错误,欢迎指出,以便及时改正。
OS:Windows 10 PRO 1709 IDE:Visual Studio 2015 Community 语言:Visual C++
获取目标进程PID。 提升Dropper进程权限。 打开目标进程。 在目标进程内开辟缓冲区,用来存储DLL的路径。 找到目标进程中加载的kernel32.dll的句柄,通过该句柄来获取目标进程中kernel32.dll的导出函数LoadLibrary函数的地址。 通过CreateRemoteThread函数来调用LoadLibrary,使目标进程加载Payload DLL。
实现:
获取目标进程PID。(本来想注入计算器,但是获取计算器的进程ID的时候总是获取一个辅助进程ID,所以就注入记事本了)。
HANDLE GetThePidOfTargetProcess() { //Get the pid of the process which to be injected. HWND injectionProcessHwnd = FindWindowA(0, "Untitled - Notepad"); DWORD dwInjectionProcessID; GetWindowThreadProcessId(injectionProcessHwnd, &dwInjectionProcessID); cout << "Notepad's pid -> " << dwInjectionProcessID << endl; HANDLE injectionProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_CREATE_THREAD, 0, dwInjectionProcessID);//dwInjectionProcessID); return injectionProcessHandle; } 提升权限。
HANDLE GetThePidOfTargetProcess() { //Get the pid of the process which to be injected. HWND injectionProcessHwnd = FindWindowA(0, "Untitled - Notepad"); DWORD dwInjectionProcessID; GetWindowThreadProcessId(injectionProcessHwnd, &dwInjectionProcessID); cout << "Notepad's pid -> " << dwInjectionProcessID << endl; HANDLE injectionProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_CREATE_THREAD, 0, dwInjectionProcessID);//dwInjectionProcessID); return injectionProcessHandle; }
void PrivilegeEscalation() { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tp; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Luid = luid; AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); } 进行注入。
void PrivilegeEscalation() { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tp; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Luid = luid; AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); }
BOOL DoInjection(char *InjectionDllPath,HANDLE injectionProcessHandle) { DWORD injBufSize = lstrlen((LPCWSTR)InjectionDllPath) + 1; LPVOID AllocAddr = VirtualAllocEx(injectionProcessHandle, NULL, injBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(injectionProcessHandle, AllocAddr, (void*)InjectionDllPath, injBufSize, NULL); PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA"); HANDLE hRemoteThread; if ((hRemoteThread = CreateRemoteThread(injectionProcessHandle, NULL, 0, pfnStartAddr, AllocAddr, 0, NULL)) == NULL) { ER = GetLastError(); cout << "Create Remote Thread Failed!" << endl; return FALSE; } else { cout << "Create Remote Thread Success!" << endl; return TRUE; } } *具体的实现代码在附件中上传也会附上GitHub地址。
BOOL DoInjection(char *InjectionDllPath,HANDLE injectionProcessHandle) { DWORD injBufSize = lstrlen((LPCWSTR)InjectionDllPath) + 1; LPVOID AllocAddr = VirtualAllocEx(injectionProcessHandle, NULL, injBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(injectionProcessHandle, AllocAddr, (void*)InjectionDllPath, injBufSize, NULL); PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA"); HANDLE hRemoteThread; if ((hRemoteThread = CreateRemoteThread(injectionProcessHandle, NULL, 0, pfnStartAddr, AllocAddr, 0, NULL)) == NULL) { ER = GetLastError(); cout << "Create Remote Thread Failed!" << endl; return FALSE; } else { cout << "Create Remote Thread Success!" << endl; return TRUE; } }
*具体的实现代码在附件中上传也会附上GitHub地址。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
MaYil 感谢分享
黑洛 我记得哪本书上说的来着,请尽量不要在DllMain中进行创建线程的操作,很容易导致死锁。如果你再加个WaitForSingleObject肯定就死锁了。
丘嗒山 怎么样才能不调用CreateRemoteThread?
sudozhange 用其他的方法注入,这种方法已经很旧很旧了,现在基本上都没有使用的了
丘嗒山 大佬,求赐教~~,还有你分析x64 内存的截图,用的是啥调试器?
sudozhange x64,我用的是windbg,虽然不太好用吧(不熟练的结果: