DWORD ThreadHijackInjection(HANDLE hProcess, PCHAR dllName){ DWORD CurrentPid = GetProcessId(hProcess); DWORD dwInjectionThread; HANDLE hThread; // We are going to just get a handle to a thread in the process, any thread. HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); THREADENTRY32 te; if (h != INVALID_HANDLE_VALUE) { te.dwSize = sizeof(te); if (Thread32First(h, &te)) { do { if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) { if(te.th32OwnerProcessID == CurrentPid){ dwInjectionThread = te.th32ThreadID; } } te.dwSize = sizeof(te); } while (Thread32Next(h, &te)); } CloseHandle(h); } // Suspend that thread. hThread = OpenThread(THREAD_INJECT_PERMISSIONS, FALSE, te.th32ThreadID); SuspendThread(hThread); // Get its context, so we know where to return to after redirecting logic flow. CONTEXT context; context.ContextFlags = CONTEXT_FULL; GetThreadContext(hThread, &context); DWORD_PTR *returnPointer; #ifdef _WIN64 returnPointer = &context.Rip; #define PLACEHOLDER 0xDEADBEEFDEADBEEF #else returnPointer = &context.Eip; #define PLACEHOLDER 0xDEADBEEF #endif // Make a buffer for the PIC PVOID picBuf = malloc(GetLoaderPicSize()); // Have the pic copied into that buffer. GetLoaderPic(picBuf, GetProcAddress(GetModuleHandleA("Kernel32.dll"),"LoadLibraryA"), dllName, (DWORD)(strlen(dllName)+1)); // Replace deadbeef (return address) in the pic with a pointer to the thread's current position. for(DWORD i=0; i < GetLoaderPicSize() - sizeof(PVOID);i++){ DWORD_PTR *deadbeef = (DWORD_PTR*)((DWORD_PTR)picBuf + i); if(*deadbeef == PLACEHOLDER){ *deadbeef = *returnPointer; break; } } // Create a code cave in the target process. LPVOID cave = VirtualAllocEx(hProcess, 0, GetLoaderPicSize(), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // Copy over the pic WriteProcessMemory(hProcess, cave, picBuf, GetLoaderPicSize(), NULL); // Redirect execution flow. *returnPointer = (DWORD_PTR)cave; SetThreadContext(hThread,&context); ResumeThread(hThread); return 1; }
/* PIC inject for win8/8.1 */ BOOL pic_inject(void *mpara, LPCWSTR dll_name) { BOOL exitCode = FALSE; CONTEXT context; DWORD_PTR *returnPointer; DWORD_PTR i; PVOID picBuf; LPVOID funcBuff; SIZE_T cbSize; char dllName[VALUE_LEN+1]; HMODULE hNtdll; PROCESS_INFORMATION pi = *(LPPROCESS_INFORMATION)mpara; _NtAllocateVirtualMemory TrueNtAllocateVirtualMemory = NULL; _NtWriteVirtualMemory TrueNtWriteVirtualMemory = NULL; _NtFreeVirtualMemory TrueNtFreeVirtualMemory = NULL; _NtResumeThread TrueNtResumeThread = NULL; hNtdll = GetModuleHandleW(L"ntdll.dll"); if (!hNtdll) { return exitCode; } TrueNtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory"); TrueNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(hNtdll, "NtWriteVirtualMemory"); TrueNtFreeVirtualMemory = (_NtFreeVirtualMemory)GetProcAddress(hNtdll, "NtFreeVirtualMemory"); TrueNtResumeThread = (_NtResumeThread)GetProcAddress(hNtdll, "NtResumeThread"); if ( !(TrueNtAllocateVirtualMemory && TrueNtWriteVirtualMemory && TrueNtFreeVirtualMemory && TrueNtResumeThread) ) { return exitCode; } if ( !WideCharToMultiByte(CP_ACP, 0,dll_name,(int)((wcslen(dll_name)+1)*sizeof(WCHAR)), \ dllName, VALUE_LEN,"" , NULL) ) { return exitCode; } /* Get its context, so we know where to return to after redirecting logic flow. */ context.ContextFlags = CONTEXT_FULL; GetThreadContext(pi.hThread, &context); #ifdef _WIN64 returnPointer = &context.Rip; #define PLACEHOLDER 0xDEADBEEFDEADBEEF #else returnPointer = &context.Eip; #define PLACEHOLDER 0xDEADBEEF #endif cbSize = GetLoaderPicSize(); /* Make a buffer for the PIC */ picBuf = SYS_MALLOC(cbSize); if ( !picBuf ) { return exitCode; } #ifdef _LOGDEBUG logmsg("cbSize = %lu\n",cbSize); #endif /* Have the pic copied into that buffer. */ GetLoaderPic(picBuf, GetProcAddress(GetModuleHandleA("Kernel32.dll"),"LoadLibraryA"), \ dllName, (DWORD_PTR)(strlen(dllName)+1)); /* Replace deadbeef (return address) in the pic with a pointer to the thread's current position. */ for(i=0; i < cbSize - sizeof(PVOID); i++) { DWORD_PTR *deadbeef = (DWORD_PTR*)((DWORD_PTR)picBuf + i); if(*deadbeef == PLACEHOLDER) { *deadbeef = *returnPointer; break; } } /* Create a code funcBuff in the target process. */ funcBuff = VirtualAllocEx(pi.hProcess, 0, cbSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(pi.hProcess, funcBuff, picBuf, cbSize, NULL); *returnPointer = (DWORD_PTR)funcBuff; exitCode = SetThreadContext(pi.hThread,&context); TrueNtResumeThread(pi.hThread,NULL); SYS_FREE(picBuf); cbSize = 0; TrueNtFreeVirtualMemory(pi.hProcess,funcBuff,&cbSize,MEM_RELEASE); return exitCode; }