BOOL MapNewExecutableRegionInProcess( IN HANDLE TargetProcessHandle, IN HANDLE TargetThreadHandle, IN LPVOID NewExecutableRawImage) { PROCESS_INFORMATION BasicInformation; PIMAGE_SECTION_HEADER SectionHeader; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader64; DWORD_PTR dwImageBase; NtUnmapViewOfSection pNtUnmapViewOfSection; LPVOID pImageBase; SIZE_T dwBytesWritten; SIZE_T dwBytesRead; int Count; PCONTEXT ThreadContext; BOOL Success = FALSE; DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage; if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE) { NtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD)NewExecutableRawImage + DosHeader->e_lfanew); if (NtHeader64->Signature == IMAGE_NT_SIGNATURE) { RtlZeroMemory(&BasicInformation, sizeof(PROCESS_INFORMATION)); ThreadContext = (PCONTEXT)VirtualAlloc(NULL, sizeof(ThreadContext) + 4, MEM_COMMIT, PAGE_READWRITE); ThreadContext = (PCONTEXT)Align((DWORD)ThreadContext, 4); ThreadContext->ContextFlags = CONTEXT_FULL; if (GetThreadContext(TargetThreadHandle, ThreadContext)) //used to be LPCONTEXT(ThreadContext) { ReadProcessMemory(TargetProcessHandle, (LPCVOID)(ThreadContext->Rdx + 16), &dwImageBase, sizeof(DWORD_PTR), &dwBytesRead); pNtUnmapViewOfSection = (NtUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"); if (pNtUnmapViewOfSection) pNtUnmapViewOfSection(TargetProcessHandle, (PVOID)dwImageBase); pImageBase = VirtualAllocEx(TargetProcessHandle, (LPVOID)NtHeader64->OptionalHeader.ImageBase, NtHeader64->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE); if (pImageBase) { WriteProcessMemory(TargetProcessHandle, pImageBase, (LPCVOID)NewExecutableRawImage, NtHeader64->OptionalHeader.SizeOfHeaders, &dwBytesWritten); SectionHeader = IMAGE_FIRST_SECTION(NtHeader64); for (Count = 0; Count < NtHeader64->FileHeader.NumberOfSections; Count++) { WriteProcessMemory(TargetProcessHandle, (LPVOID)((DWORD_PTR)pImageBase + SectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)NewExecutableRawImage + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, &dwBytesWritten); SectionHeader++; } WriteProcessMemory(TargetProcessHandle, (LPVOID)(ThreadContext->Rdx + 16), (LPVOID)&NtHeader64->OptionalHeader.ImageBase, sizeof(DWORD_PTR), &dwBytesWritten); ThreadContext->Rcx = (DWORD_PTR)pImageBase + NtHeader64->OptionalHeader.AddressOfEntryPoint; SetThreadContext(TargetThreadHandle, (LPCONTEXT)ThreadContext); ResumeThread(TargetThreadHandle); Success = TRUE; } else TerminateProcess(TargetProcessHandle, 0); //VirtualFree(ThreadContext, 0, MEM_RELEASE); } } } return Success; }
bool changeContextToUndoRecoving(HANDLE thread, CONTEXT* c){ Q_UNUSED(c); return SetThreadContext(thread, &lastRecoveredContext); }
//------------------------------------------------------------------------- static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action) { // If the thread suspended in the overwritten area, // move IP to the proper address. CONTEXT c; #ifdef _M_X64 DWORD64 *pIP = &c.Rip; #else DWORD *pIP = &c.Eip; #endif UINT count; c.ContextFlags = CONTEXT_CONTROL; if (!GetThreadContext(hThread, &c)) return; if (pos == ALL_HOOKS_POS) { pos = 0; count = g_hooks.size; } else { count = pos + 1; } for (; pos < count; ++pos) { PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; BOOL enable; DWORD_PTR ip; switch (action) { case ACTION_DISABLE: enable = FALSE; break; case ACTION_ENABLE: enable = TRUE; break; case ACTION_APPLY_QUEUED: enable = pHook->queueEnable; break; } if (pHook->isEnabled == enable) continue; if (enable) ip = FindNewIP(pHook, *pIP); else ip = FindOldIP(pHook, *pIP); if (ip != 0) { *pIP = ip; SetThreadContext(hThread, &c); } } }
static int r_debug_native_reg_write (RDebug *dbg, int type, const ut8* buf, int size) { // XXX use switch or so if (type == R_REG_TYPE_DRX) { #if __i386__ || __x86_64__ #if __KFBSD__ return (0 == ptrace (PT_SETDBREGS, dbg->pid, (caddr_t)buf, sizeof (struct dbreg))); #elif __linux__ return linux_reg_write (dbg, type, buf, size); #elif __APPLE__ if (1) return false; //disable until fixed ?? know why this return xnu_reg_write (dbg, type, buf, size); #else //eprintf ("TODO: No support for write DRX registers\n"); #if __WINDOWS__ int tid = dbg->tid; int pid = dbg->pid; BOOL ret; HANDLE thread; CONTEXT ctx __attribute__((aligned (16))); memcpy (&ctx, buf, sizeof (CONTEXT)); ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; thread = w32_open_thread (pid, tid); ret=SetThreadContext (thread, &ctx)? true: false; CloseHandle(thread); return ret; #endif return false; #endif #else // i386/x86-64 return false; #endif } else if (type == R_REG_TYPE_GPR) { #if __WINDOWS__ && !__CYGWIN__ BOOL ret; CONTEXT ctx __attribute__((aligned (16))); memcpy (&ctx, buf, sizeof (CONTEXT)); ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; // eprintf ("EFLAGS =%x\n", ctx.EFlags); HANDLE thread = w32_open_thread (dbg->pid, dbg->tid); ret = SetThreadContext (thread, &ctx)? true: false; CloseHandle (thread); return ret; #elif __linux__ return linux_reg_write (dbg, type, buf, size); #elif __sun || __NetBSD__ || __KFBSD__ || __OpenBSD__ int ret = ptrace (PTRACE_SETREGS, dbg->pid, (void*)(size_t)buf, sizeof (R_DEBUG_REG_T)); if (sizeof (R_DEBUG_REG_T) < size) size = sizeof (R_DEBUG_REG_T); return (ret != 0) ? false: true; #elif __APPLE__ return xnu_reg_write (dbg, type, buf, size); #else #warning r_debug_native_reg_write not implemented #endif } //else eprintf ("TODO: reg_write_non-gpr (%d)\n", type); return false; }
LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer) { if (pppFailedPointer != NULL) { // Used to get the last error. *pppFailedPointer = s_ppPendingError; } if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { return ERROR_INVALID_OPERATION; } // If any of the pending operations failed, then we abort the whole transaction. if (s_nPendingError != NO_ERROR) { DETOUR_BREAK(); DetourTransactionAbort(); return s_nPendingError; } // Common variables. DetourOperation *o; DetourThread *t; // Insert or remove each of the detours. for (o = s_pPendingOperations; o != NULL; o = o->pNext) { if (o->fIsRemove) { PBYTE pbSrc = o->pTrampoline->rbCode; LONG cbCopy = 0; for (; cbCopy < o->pTrampoline->cbTarget;) { LONG lExtra = 0; pbSrc = (PBYTE)DetourCopyInstructionEx(o->pbTarget + cbCopy, pbSrc, NULL, &lExtra); if (lExtra != 0) { break; // Abort if offset doesn't fit. } cbCopy = (LONG)(pbSrc - o->pTrampoline->rbCode); } if (cbCopy != o->pTrampoline->cbTarget) { // Count came out different! // This is a drastic error as the backward copy should never fail. s_nPendingError = ERROR_INVALID_DATA; s_ppPendingError = (PVOID*)o->ppbPointer; DETOUR_BREAK(); } #ifdef DETOURS_IA64 #error Feature not supported in this release. #else // DETOURS_IA64 *o->ppbPointer = o->pbTarget; #endif } else { DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbTarget=%d\n", o->pTrampoline, o->pTrampoline->pbRemain, o->pTrampoline->pbDetour, o->pTrampoline->cbTarget)); DETOUR_TRACE(("detours: pbTarget=%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x [before]\n", o->pbTarget, o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_X86 PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, o->pTrampoline->pbDetour); pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain); *o->ppbPointer = o->pTrampoline->rbCode; #endif // DETOURS_X86 DETOUR_TRACE(("detours: pbTarget=%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x [after]\n", o->pbTarget, o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); DETOUR_TRACE(("detours: pbTramp =%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x\n", o->pTrampoline, o->pTrampoline->rbCode[0], o->pTrampoline->rbCode[1], o->pTrampoline->rbCode[2], o->pTrampoline->rbCode[3], o->pTrampoline->rbCode[4], o->pTrampoline->rbCode[5], o->pTrampoline->rbCode[6], o->pTrampoline->rbCode[7], o->pTrampoline->rbCode[8], o->pTrampoline->rbCode[9], o->pTrampoline->rbCode[10], o->pTrampoline->rbCode[11])); #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 } } // Update any suspended threads. for (t = s_pPendingThreads; t != NULL; t = t->pNext) { CONTEXT cxt; cxt.ContextFlags = CONTEXT_CONTROL; #undef DETOURS_EIP #undef DETOURS_EIP_TYPE #ifdef DETOURS_X86 #define DETOURS_EIP Eip #define DETOURS_EIP_TYPE DWORD #endif // DETOURS_X86 #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 if (GetThreadContext(t->hThread, &cxt)) { for (DetourOperation *o = s_pPendingOperations; o != NULL; o = o->pNext) { if (o->fIsRemove) { if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline && cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline + sizeof(o->pTrampoline)) { cxt.DETOURS_EIP -= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline; cxt.DETOURS_EIP += (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget; SetThreadContext(t->hThread, &cxt); } } else { if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget && cxt.DETOURS_EIP < ((DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget + o->pTrampoline->cbTarget)) { cxt.DETOURS_EIP -= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget; cxt.DETOURS_EIP += (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline; SetThreadContext(t->hThread, &cxt); } } } } #undef DETOURS_EIP } // Restore all of the page permissions and flush the icache. HANDLE hProcess = GetCurrentProcess(); for (o = s_pPendingOperations; o != NULL;) { // We don't care if this fails, because the code is still accessible. DWORD dwOld; VirtualProtect(o->pbTarget, o->pTrampoline->cbTarget, o->dwPerm, &dwOld); FlushInstructionCache(hProcess, o->pbTarget, o->pTrampoline->cbTarget); if (o->fIsRemove && o->pTrampoline) { detour_free_trampoline(o->pTrampoline); o->pTrampoline = NULL; } DetourOperation *n = o->pNext; delete o; o = n; } s_pPendingOperations = NULL; // Make sure the trampoline pages are no longer writable. detour_runnable_trampoline_regions(); // Resume any suspended threads. for (t = s_pPendingThreads; t != NULL;) { // There is nothing we can do if this fails. ResumeThread(t->hThread); DetourThread *n = t->pNext; delete t; t = n; } s_pPendingThreads = NULL; s_nPendingThreadId = 0; if (pppFailedPointer != NULL) { *pppFailedPointer = s_ppPendingError; } return s_nPendingError; }
int main(int argc,char **argv) { parseArgs(argc, argv); SIZE_T bW = 0, bR = 0; char *exeInput = (char *)malloc(MAX_PATH); char *dllInput = (char *)malloc(MAX_PATH); char *wdrInput = (char *)malloc(MAX_PATH); memset(exeInput,0,MAX_PATH); memset(dllInput,0,MAX_PATH); memset(wdrInput,0,MAX_PATH); if (opMode == OPMODE_LIST) { listProcesses(stringToMatch); return 0; } else if(opMode == OPMODE_INJECT) { if (globalDll == NULL) { printf(" [dll] > "); fgets(dllInput,MAX_PATH,stdin); } else { strcpy(dllInput,globalDll); } injectIntoProcess(globalInject,dllInput); return 0; } if (globalTest) { strcpy(exeInput,"test.exe"); strcpy(dllInput,"shackle.dll"); strcpy(wdrInput,"c:\\projects\\elegurawolfe\\"); } else if(globalExeName == NULL || globalWorkingDirectory == NULL || globalDll == NULL) { // printf("* SOMETHING MISSING %08x%08x%08x\n", (unsigned long )globalExeName, (unsigned long )globalWorkingDirectory, (unsigned long )globalDll); printf(" [exe] > "); fgets(exeInput,MAX_PATH,stdin); if (globalDll == NULL) { printf(" [dll] > "); fgets(dllInput,MAX_PATH,stdin); } else { strcpy(dllInput,globalDll); } printf(" [wdr] > "); fgets(wdrInput,MAX_PATH,stdin); chomp(exeInput); chomp(dllInput); chomp(wdrInput); } else { strcpy(exeInput,globalExeName); strcpy(dllInput,globalDll); strcpy(wdrInput,globalWorkingDirectory); } if (exists(exeInput) == 0) { printf(" [FAIL-EXE] %s does not exist\n",exeInput); return 0; } if(exists(dllInput) == 0) { printf(" [FAIL-DLL] %s does not exist\n",dllInput); return 0; } PROCESS_INFORMATION pi; STARTUPINFO si; memset (&pi,0,sizeof(PROCESS_INFORMATION)); memset (&si, 0, sizeof (STARTUPINFO)); si.cb = sizeof(si); HANDLE hNtDll = LoadLibrary("ntdll.dll"); NtQueryInformationProcess = (_NtQueryInformationProcess )(GetProcAddress( (HMODULE )hNtDll, "NtQueryInformationProcess")); HANDLE hKernel = LoadLibrary("kernel32.dll"); LPVOID addrLoadLibrary = GetProcAddress( (HMODULE )hKernel, "LoadLibraryA"); BOOL derp = CreateProcess(exeInput, exeInput, NULL, NULL, FALSE, CREATE_SUSPENDED + CREATE_NEW_CONSOLE, NULL, wdrInput, &si, &pi); if (derp == NULL) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } HANDLE hProcess = pi.hProcess; HANDLE hThread = pi.hThread; globalPid = pi.dwProcessId; printf(" * [INFO] new process id is %d\n",pi.dwProcessId); #if ARCHI == 64 BOOL wow64 = FALSE; IsWow64Process(hProcess,&wow64); if (wow64 == TRUE) { IsDll64Bit(globalDll); printf(" [WARN] injecting into wow64 "); } #endif printf(" [INFO] process handle is %08x\n",(unsigned long )hProcess); PROCESS_BASIC_INFORMATION pib; PEB_ARCHI globalPEB; NtQueryInformationProcess (hProcess, 0, (PVOID )(&pib), sizeof (pib),& bW); printf(" [INFO] pib.PebBaseAddress = 0x%x (size of field is %d)\n", pib.PebBaseAddress, sizeof(pib.PebBaseAddress)); ReadProcessMemory (hProcess, pib.PebBaseAddress, &globalPEB, sizeof (globalPEB), &bR); if (bR != sizeof (globalPEB)) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } printf(" [INFO] peb.ImageBaseAddress = %p\n", globalPEB.ImageBaseAddress); UINT_PTR entryPoint = guessExecutableEntryPoint (hProcess, globalPEB.ImageBaseAddress); printf(" [INFO] entryPoint = 0x%8x\n", entryPoint); char oldEntryChars[2]; DWORD oldProtect = 0; DWORD discardProtect = 0; VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect); ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)oldEntryChars,2,&bR); printf(" [INFO] old entry is %02x %02x\n", (unsigned char )oldEntryChars[0],(unsigned char )oldEntryChars[1]); printf(" [INFO] writing...\n"); WriteProcessMemory(hProcess,(LPVOID )entryPoint,"\xEB\xFE",2,&bW); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1,oldProtect,&discardProtect); char newEntryChars[2]; ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR); if (newEntryChars[0] == '\xEB' && newEntryChars[1] == '\xFE') { printf(" [INFO] new entry is %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); } else { printf(" [INFO] new entry is %02x %02x, something's wrong\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); return 0; } CONTEXT context; context.ContextFlags = CONTEXT_FULL; GetThreadContext (hThread, &context); context.PC_REG = entryPoint; SetThreadContext(hThread,&context); ResumeThread(pi.hThread); LPVOID remoteMemory = VirtualAllocEx(hProcess,NULL,strlen(dllInput) + 1,MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess,(LPVOID )remoteMemory,dllInput,strlen(dllInput) + 1,&bW); printf(" [INFO] trying to create a remote thread at %08x\n",(unsigned long )addrLoadLibrary); char *dllOutput = (char *)malloc(MAX_PATH); memset(dllOutput,0,MAX_PATH); ReadProcessMemory(hProcess,(LPCVOID )remoteMemory,dllOutput,MAX_PATH,&bR); printf(" [INFO] confirming process has cave with \"%s\"\n",dllOutput); free(dllOutput); if(globalWait) { printf(" [WAIT] press any key to create remote thread...\n"); getc(stdin); } HANDLE threadId = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE )addrLoadLibrary,remoteMemory,NULL,NULL); if (threadId == NULL) { printf(" [INFO] could not create remote thread\n"); return 0; } else { WaitForSingleObject(threadId, INFINITE); //this waits untill thread thread has finished // VirtualFree(remoteMemory, 0, MEM_RELEASE); //free myFunc memory CloseHandle(threadId); // CloseHandle(hProcess); } int i = globalCooldown; for (; i > 0; i--) { printf(" [INFO] waiting %d seconds\n",i); Sleep(1000); } printf(" [INFO] restoring entrypoint...\n"); SuspendThread(pi.hThread); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect); i = WriteProcessMemory(hProcess,(LPVOID )entryPoint,(char *)&oldEntryChars,2,&bW); if (i == 0) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, oldProtect, &discardProtect); printf(" [INFO] entry restored to %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); GetThreadContext (hThread, &context); context.PC_REG = entryPoint; SetThreadContext(hThread,&context); ResumeThread(pi.hThread); printf(" [INFO] bye!"); free(exeInput); free(dllInput); free(wdrInput); return 0; }
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; }
bool WINAPI CreateMemoryProcess( LPVOID lpImage, char* pPath ) { // Variables for Process Forking ///////////////////////////////////////////////////////////////// DWORD lWritten; DWORD lImageSize; DWORD lImageBase; DWORD lImageHeaderSize; DWORD lFirstSection; DWORD lJumpSize = 0; DWORD lSectionCount; DWORD lSectionSize; DWORD lPreviousProtection; LPVOID lpImageMemory; IMAGE_DOS_HEADER dsDosHeader; IMAGE_NT_HEADERS ntNtHeader; IMAGE_SECTION_HEADER shSections[512 * 2]; PROCESS_INFORMATION piProcessInformation; STARTUPINFO suStartUpInformation; CONTEXT cContext; DWORD lProccessBaseAdress; DWORD lProccessImageSize; char* pProcessName; bool bIsNewProccessName = false; bool bReturnValue = false; ///////////////////////////////////////////////////////////////// // End Variable Definition if(strlen(pPath) == 0) { // No process name is set. Trying to fork this process pProcessName = new char[MAX_PATH]; ZeroMemory(pProcessName, MAX_PATH); bIsNewProccessName = true; #ifdef CPDEBUG printf("Trying to fork same process file\n"); #endif // Get the file name for the dummy process if(GetModuleFileName(NULL, pProcessName, MAX_PATH) == 0) { #ifdef CPDEBUG printf("Error: Can't recive GetModuleFileName() from proccess.\n"); #endif delete [] pProcessName; return bReturnValue; } } else { pProcessName = pPath; } #ifdef CPDEBUG printf("Using %s for injection\n", pProcessName); #endif // Grab the DOS Headers memcpy(&dsDosHeader, lpImage, sizeof(dsDosHeader)); if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { #ifdef CPDEBUG printf("Error: File DOS header wrong\n"); #endif if(bIsNewProccessName) delete [] pProcessName; return false; } // Grab NT Headers memcpy(&ntNtHeader, (LPVOID)((DWORD)lpImage + dsDosHeader.e_lfanew), sizeof(ntNtHeader)); if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE) { #ifdef CPDEBUG printf("Error: No NT Signature finded.\n"); #endif if(bIsNewProccessName) delete [] pProcessName; return false; } // Get Size and Image Base lImageBase = ntNtHeader.OptionalHeader.ImageBase; lImageSize = ntNtHeader.OptionalHeader.SizeOfImage; lImageHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders; #ifdef CPDEBUG printf("New image base = %X\n", lImageBase); printf("New image size = %d\n", lImageSize); printf("New image header size = %d\n", lImageHeaderSize); #endif // Allocate memory for image lpImageMemory = new LPVOID[lImageSize]; ZeroMemory(lpImageMemory, lImageSize); lFirstSection = (DWORD)(((DWORD)lpImage + dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); memcpy(shSections, (LPVOID)(lFirstSection), sizeof(IMAGE_SECTION_HEADER) * ntNtHeader.FileHeader.NumberOfSections); #ifdef CPDEBUG printf("%d header sections founded\n", ntNtHeader.FileHeader.NumberOfSections); #endif memcpy(lpImageMemory, lpImage, lImageHeaderSize); // Get Section Alignment if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders; } else { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders / ntNtHeader.OptionalHeader.SectionAlignment; lJumpSize += 1; lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment; } LPVOID lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemory + lJumpSize); // Copy Sections To Buffer for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++) { lJumpSize = 0; lSectionSize = shSections[lSectionCount].SizeOfRawData; memcpy(lpImageMemoryDummy, (LPVOID)((DWORD)lpImage + shSections[lSectionCount].PointerToRawData), lSectionSize); if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = shSections[lSectionCount].Misc.VirtualSize; } else { lJumpSize = shSections[lSectionCount].Misc.VirtualSize / ntNtHeader.OptionalHeader.SectionAlignment; lJumpSize += 1; lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment; } lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemoryDummy + lJumpSize); } ZeroMemory(&suStartUpInformation, sizeof(STARTUPINFO)); ZeroMemory(&piProcessInformation, sizeof(PROCESS_INFORMATION)); ZeroMemory(&cContext, sizeof(CONTEXT)); suStartUpInformation.cb = sizeof(suStartUpInformation); // Create Process if(CreateProcess( NULL, pProcessName, NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &suStartUpInformation, &piProcessInformation )) { #ifdef CPDEBUG printf("Proccess suspended\n"); #endif cContext.ContextFlags = CONTEXT_FULL; if(!GetThreadContext(piProcessInformation.hThread,&cContext)) { #ifdef CPDEBUG printf("Fail to get context of suspended proccess.\n"); #endif TerminateProcess(piProcessInformation.hProcess, 0); if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; return false; return true; } DWORD *pEbxInfo = (DWORD *)cContext.Ebx; DWORD read; ReadProcessMemory( piProcessInformation.hProcess, &pEbxInfo[2], (LPVOID)&lProccessBaseAdress, sizeof(DWORD), &read ); DWORD curAddr = lProccessBaseAdress; MEMORY_BASIC_INFORMATION memInfo; while(VirtualQueryEx( piProcessInformation.hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo)) ) { if(memInfo.State == MEM_FREE) break; curAddr += memInfo.RegionSize; } lProccessImageSize = (DWORD)curAddr - (DWORD)lProccessBaseAdress; #ifdef CPDEBUG printf("Current image base adress = %X\n", lProccessBaseAdress); printf("Current image size = %d\n", lProccessImageSize); #endif // Check image base and image size if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize) { // we can load new image to same place #ifdef CPDEBUG printf("Using same image place\n"); #endif VirtualProtectEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, PAGE_EXECUTE_READWRITE, (DWORD*)&lPreviousProtection ); } else { // We can't use same place, allocate memory for it. #ifdef CPDEBUG printf("Allocation place for new image\n"); #endif if(NtUnmapViewOfSection( piProcessInformation.hProcess, (LPVOID)lProccessBaseAdress ) == 0) { #ifdef CPDEBUG printf("Old section unmaped\n"); #endif LPVOID lpIsAllocated = VirtualAllocEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if(lpIsAllocated) { #ifdef CPDEBUG printf("Memory allocated successful\n"); #endif } else { #ifdef CPDEBUG printf("Error: Can't allocated\n"); #endif } } else { #ifdef CPDEBUG printf("Error: Can't unmap old section\n"); #endif } } // Write Image to Process if(WriteProcessMemory( piProcessInformation.hProcess, (LPVOID)lImageBase, lpImageMemory, lImageSize, (DWORD*)&lWritten )) { bReturnValue = true; #ifdef CPDEBUG printf("New image writen\n"); #endif } else { #ifdef CPDEBUG printf("Error: New image written error.\n"); #endif } // Set Image Base if(WriteProcessMemory( piProcessInformation.hProcess, (LPVOID)((DWORD)cContext.Ebx + 8), &lImageBase, 4, (DWORD*)&lWritten) ) { #ifdef CPDEBUG printf("Updated init point\n"); #endif } else { bReturnValue = false; #ifdef CPDEBUG printf("Error: Can't update init point\n"); #endif } if(!bReturnValue) { #ifdef CPDEBUG printf("Error: Error during image rewriting. Exit.\n"); #endif TerminateProcess(piProcessInformation.hProcess, 0); if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; return false; } // Set the new entry point cContext.Eax = lImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint; SetThreadContext( piProcessInformation.hThread, &cContext ); if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize) { #ifdef CPDEBUG printf("Returning old protection for new image.\n"); #endif VirtualProtectEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, lPreviousProtection, 0 ); } // Resume the process ResumeThread(piProcessInformation.hThread); } else { #ifdef CPDEBUG printf("Error: Can't start %s\n", pProcessName); #endif return false; } if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; if(bReturnValue) { #ifdef CPDEBUG printf("Successful injected. No errors during doing this.\n"); #endif } return bReturnValue; }
TARGET_ADDRESS nub_setup_function_call (NUB nub, NUBTHREAD thread, TARGET_ADDRESS function, NUBINT arg_count, TARGET_ADDRESS *args, NUBHANDLE *context_cookie) { LPDBGPROCESS process = (LPDBGPROCESS) nub; LPDBGTHREAD threadC = (LPDBGTHREAD) thread; CONTEXT context; THREAD_MEMORY *saved_thread = (THREAD_MEMORY*) malloc (sizeof(THREAD_MEMORY)); BOOL status; DWORD stack_position; DWORD original_IP; DWORD i = 0; BOOL write_status; DWORD bytes_written; TARGET_ADDRESS address_to_break; // suspend_thread(threadC); // Now get context information. We need to know the return address // for our frame-to-be, and also the stack pointer + frame pointer // as is. context.ContextFlags = CONTEXT_FULL; status = get_thread_context(process, threadC, &context); dylan_debugger_message("nub_setup_function_call: Thread Context: %= : %=", threadC->ThreadHandle, status); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); //print_context("Context pulled from thread state", &context); // Now remember everything about the debug state of this thread. saved_thread->ThreadState = threadC->ThreadState; saved_thread->WaitingForDebugger = threadC->WaitingForDebugger; saved_thread->SingleStepping = threadC->SingleStepping; saved_thread->NeedsBreakpointReplacement = threadC->NeedsBreakpointReplacement; saved_thread->BreakpointToReplace = threadC->BreakpointToReplace; saved_thread->StoppedState = threadC->StoppedState; saved_thread->LastReceivedEvent = threadC->LastReceivedEvent; saved_thread->NubCodeOfLastEvent = threadC->NubCodeOfLastEvent; saved_thread->ThreadContext = context; // Allocate enough space on the stack to hold the arguments to the // remote function, and the return address. stack_position = (DWORD) nub_allocate_stack_space (nub, thread, ((DWORD) (arg_count + 1)) * sizeof(DWORD)); if (stack_position == 0x0) { debugger_error("Serious Error: Failed to allocate stack in Spy call on Thread %=", (TARGET_ADDRESS)threadC->ThreadHandle, (TARGET_ADDRESS)NULL); // Internal error return(NULL); } // And get ready for the remote call. If the thread was stopped at a // breakpoint, we need to override that, because we are going to alter // the instruction pointer. if (saved_thread->NeedsBreakpointReplacement) { LPDEBUG_POINT breakpoint = saved_thread->BreakpointToReplace; drop_breakpoint(process, breakpoint); threadC->NeedsBreakpointReplacement = FALSE; if (!(saved_thread->SingleStepping)) { context.EFlags = context.EFlags & 0xFFFFFEFF; } // And resume those threads that will have been suspended. // resume_all_except(process, thread); } if (!status) { // Internal nub error. return (NULL); } //print_context("Context being saved", &(saved_thread->ThreadContext)); // Grab the return address so that the access path chappies can set a // breakpoint on it to clean up the stack. address_to_break = (TARGET_ADDRESS) context.Eip; original_IP = context.Eip; // DIY stack frame!!!! // We are using the C calling convention to bring about our remote // call. At the point of call, the new stack frame must have all the // arguments pushed, followed by the return address. context.Esp = stack_position; // And make the instruction pointer point to our function. context.Eip = (DWORD) function; // The stack should now be fooling this thread into thinking that // it has to execute our remote function, which it will go off and do // as soon as the application resumes. But we have to set the context. status = SetThreadContext (threadC->ThreadHandle, &context); if (!status) { // Internal nub error. return(NULL); } // print_context("Context set back to thread", &context); // Push the return address - ie, the next instruction that was going // to be executed, before we started messing about... write_status = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) stack_position, (LPVOID) &(original_IP), sizeof(TARGET_ADDRESS), &bytes_written); stack_position += sizeof(TARGET_ADDRESS); if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) { // Internal nub error. return (NULL); } // Push the argument array. for (i = 0; i < (DWORD) arg_count; i++) { write_status = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) stack_position, (LPVOID) &(args[i]), sizeof(TARGET_ADDRESS), &bytes_written); if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) { // Internal nub error. return (NULL); } else { //printf ("Wrote the argument %x at %x.\n", args[i], stack_position); } stack_position += sizeof(TARGET_ADDRESS); } //print_context("Context set back to thread", &context); (*context_cookie) = (NUBHANDLE) saved_thread; //resume_thread(threadC); return (address_to_break); }
/// <summary> /// Set native thread context /// </summary> /// <param name="hThread">Thread handle.</param> /// <param name="ctx">Thread context</param> /// <returns>Status code</returns> NTSTATUS Native::SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ) { LastNtStatus( STATUS_SUCCESS ); SetThreadContext( hThread, reinterpret_cast<PCONTEXT>(&ctx) ); return LastNtStatus(); }
int r3dSetDataBreakpoint( void* address, r3dDataBreakpointByteLen byteLen, int condition ) { #ifndef FINAL_BUILD g_BreakPointThreads.Clear(); HANDLE hThreadSnap = INVALID_HANDLE_VALUE; THREADENTRY32 te32; // Take a snapshot of all running threads hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); if( hThreadSnap == INVALID_HANDLE_VALUE ) return 0; // Fill in the size of the structure before using it. te32.dwSize = sizeof(THREADENTRY32 ); // Retrieve information about the first thread, // and exit if unsuccessful if( !Thread32First( hThreadSnap, &te32 ) ) { return 0; } DWORD currProcessID = GetCurrentProcessId(); // Now walk the thread list of the system, // and display information about each thread // associated with the specified process do { if( te32.th32OwnerProcessID == currProcessID ) { g_BreakPointThreads.PushBack( te32.th32ThreadID ); } } while( Thread32Next(hThreadSnap, &te32 ) ); // Don't forget to clean up the snapshot object. CloseHandle( hThreadSnap ); //------------------------------------------------------------------------ int currentThreadId = GetCurrentThreadId(); for( int i = 0; i < (int)g_BreakPointThreads.Count(); i ++ ) { CONTEXT cxt; int threadId = g_BreakPointThreads[ i ]; HANDLE threadHandle = OpenThread( THREAD_ALL_ACCESS, FALSE, threadId ); if( threadHandle == INVALID_HANDLE_VALUE ) return 0; if( threadId != currentThreadId ) SuspendThread( threadHandle ); int len = 0; switch( byteLen ) { case R3D_DATABREAKPOINT_1_BYTE: len = 0; break; case R3D_DATABREAKPOINT_2_BYTES: len = 1; break; case R3D_DATABREAKPOINT_4_BYTES: len = 3; break; default: r3d_assert(false); // invalid length } // The only registers we care about are the debug registers cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS; // Read the register values if( !GetThreadContext(threadHandle, &cxt) ) { CloseHandle( threadHandle ); return 0; } // Find an available hardware register int index = 0; for( index = 0; index < 4; ++index ) { if( ( cxt.Dr7 & ( 1 << ( index * 2 ) ) ) == 0 ) break; } r3d_assert( index < 4 ); // All hardware breakpoint registers are already being used switch ( index ) { case 0: cxt.Dr0 = (DWORD) address; break; case 1: cxt.Dr1 = (DWORD) address; break; case 2: cxt.Dr2 = (DWORD) address; break; case 3: cxt.Dr3 = (DWORD) address; break; default: assert(false); // m_index has bogus value } SetBits(cxt.Dr7, 16 + (index*4), 2, condition); SetBits(cxt.Dr7, 18 + (index*4), 2, len); SetBits(cxt.Dr7, index*2, 1, 1); // Write out the new debug registers int failed = 0; if ( !SetThreadContext(threadHandle, &cxt) ) failed = 1; if( threadId != currentThreadId ) ResumeThread( threadHandle ); CloseHandle( threadHandle ); if( failed ) return 0; } #endif return 1; }
STATUS DbgThreadSetBreakpoint( IN PHWBREAKDATA BreakpointData ) { HANDLE hThread; DWORD dwDebugRegister; CONTEXT ctxThreadContext = {0}; ERRORINFO err; CHAR szBreakType[20] = {'\0'}; ctxThreadContext.ContextFlags = CONTEXT_DEBUG_REGISTERS; /* Open thread with desired access */ hThread = OpenThread( THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME , FALSE, BreakpointData->dwThreadId); if ( hThread == NULL ) { REPORT_ERROR("OpenThread()", &err); /* Set the Error Flag to proper value */ BreakpointData->dwStatus = DR_BREAK_ERROR_UNK; return PWNYPOT_STATUS_INTERNAL_ERROR; } /* Is thread already suspend ? */ if ( BreakpointData->dwThreadStatus != THREAD_ALREADY_SUSPEND ) { /* Suspend thread for getting/setting thread context in a safe manner */ if ( SuspendThread(hThread) == -1 ) { REPORT_ERROR("SuspendThread()",&err); BreakpointData->dwStatus = DR_BREAK_ERROR_UNK; return PWNYPOT_STATUS_INTERNAL_ERROR; } } /* Get thread current context */ if ( !GetThreadContext(hThread,&ctxThreadContext) ) { REPORT_ERROR("GetThreadContext()",&err); BreakpointData->dwStatus = DR_BREAK_ERROR_UNK; return PWNYPOT_STATUS_INTERNAL_ERROR; } /* check if Dr(n) is busy with another Hardware Breakpoint? */ if ( !IsBitSet(ctxThreadContext.Dr7,0) || !IsBitSet(ctxThreadContext.Dr7,1) ) { /* Set the Debug Register */ dwDebugRegister = 0; /* Set the breakpoint address */ ctxThreadContext.Dr0 = (DWORD)BreakpointData->Address; /* Set Dr(n) state as a busy register, it can be use for removing specific breakpoint */ BreakpointData->dwDrBusyRemove = dwDebugRegister; } else if ( !IsBitSet(ctxThreadContext.Dr7,2) || !IsBitSet(ctxThreadContext.Dr7,3) ) { dwDebugRegister = 1; ctxThreadContext.Dr1 = (DWORD)BreakpointData->Address; BreakpointData->dwDrBusyRemove = dwDebugRegister; } else if ( !IsBitSet(ctxThreadContext.Dr7,4) || !IsBitSet(ctxThreadContext.Dr7,5) ) { dwDebugRegister = 2; ctxThreadContext.Dr2 = (DWORD)BreakpointData->Address; BreakpointData->dwDrBusyRemove = dwDebugRegister; } else if ( !IsBitSet(ctxThreadContext.Dr7,6) || !IsBitSet(ctxThreadContext.Dr7,7) ) { dwDebugRegister = 3; ctxThreadContext.Dr3 = (DWORD)BreakpointData->Address; BreakpointData->dwDrBusyRemove = dwDebugRegister; } else { /* All Debug Registers are busy */ BreakpointData->dwStatus = DR_ALL_BUSY; return PWNYPOT_STATUS_GENERAL_FAIL; } /* Set the proper bit in Dr7 for used Debug Register and Breakpoint type */ ctxThreadContext.Dr7 |= 1 << (dwDebugRegister * 2); ctxThreadContext.Dr7 |= BreakpointData->dwCondition << ((dwDebugRegister * 4) + 16); ctxThreadContext.Dr7 |= 1 << ((dwDebugRegister * 4) + 18); /* Enable the Breakpoint for thread by setting the thread context */ if ( !SetThreadContext(hThread,&ctxThreadContext) ) { REPORT_ERROR("GetThreadContext()",&err); BreakpointData->dwStatus = DR_BREAK_ERROR_UNK; return PWNYPOT_STATUS_INTERNAL_ERROR; } BreakpointData->dwStatus = DR_BREAK_SET; switch ( BreakpointData->dwCondition ) { case HW_ACCESS: strncpy( szBreakType, HW_ACCESS_STR, 20); break; case HW_EXECUTE: strncpy( szBreakType, HW_EXECUTE_STR, 20); break; case HW_WRITE: strncpy( szBreakType, HW_WRITE_STR, 20); break; } DEBUG_PRINTF(LDBG, NULL, "Breakpoint On | TID : %p - Dr%d - Len : %d - Condition : %s!\n", BreakpointData->dwThreadId , dwDebugRegister, BreakpointData->dwSize , szBreakType); /* Resume the thread if it was not in suspend state at creation time */ if ( BreakpointData->dwThreadStatus != THREAD_ALREADY_SUSPEND ) ResumeThread(hThread); return PWNYPOT_STATUS_SUCCESS; }
void clear_application_breakpoint (LPDBGPROCESS process, DWORD address) { LPDEBUG_POINT this_debug_point, last_debug_point; LPDBGTHREAD this_thread; if (!process->ExitingProcess) { dylan_debugger_message("clear_application_breakpoint %=", address, 0); this_debug_point = process->DebugPointList; this_thread = process->ThreadList; last_debug_point = NULL; while (this_debug_point != NULL) { if ((this_debug_point->DebugPointType == DBG_POINT_BREAKPOINT) && (this_debug_point->u.Breakpoint.Type == APPLICATION_BREAKPOINT) && (this_debug_point->u.Breakpoint.Address == address)) { // Lift out the breakpoint. lift_breakpoint(process, this_debug_point); // One or more threads might actually be stopped at this breakpoint. // If so, they must be stopped from writing it back into the // process. this_thread = process->ThreadList; while (this_thread != NULL) { CONTEXT context; if (this_thread->NeedsBreakpointReplacement) { // This thread is waiting at a breakpoint. If that breakpoint // is the one we're removing now, we have to hack its state. if (this_thread->BreakpointToReplace == this_debug_point) { dylan_debugger_message("Thread no longer needs breakpoint replacement %= %=", this_thread->ThreadHandle, address); this_thread->NeedsBreakpointReplacement = FALSE; // The thread will have been put into single-step mode in order // to recover from the breakpoint. But it might also be in // single-step mode anyway! If it isn't, take it out of // single-step mode. if (!(this_thread->SingleStepping)) { context.ContextFlags = CONTEXT_CONTROL; get_thread_context(process, this_thread, &context); context.EFlags = context.EFlags & 0xFFFFFEFF; SetThreadContext(this_thread->ThreadHandle, &context); // resume_all_except(process, this_thread); } } } this_thread = this_thread->Next; } // Delete the descriptor from the list. if (last_debug_point == NULL) { // This shouldn't happen, but we might as well handle it. (process->DebugPointList) = this_debug_point->Next; free(this_debug_point); this_debug_point = (process->DebugPointList); } else { last_debug_point->Next = this_debug_point->Next; free(this_debug_point); this_debug_point = (last_debug_point->Next); } } else { last_debug_point = this_debug_point; this_debug_point = this_debug_point->Next; } } } }
/* 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; }
virtual void WritePatch() override { hadesmem::detail::AcquireSRWLock const lock( &GetSrwLock(), hadesmem::detail::SRWLockType::Exclusive); auto& veh_hooks = GetVehHooks(); HADESMEM_DETAIL_ASSERT(veh_hooks.find(target_) == std::end(veh_hooks)); veh_hooks[target_] = this; auto const veh_cleanup_hook = [&]() { auto const veh_hooks_removed = veh_hooks.erase(target_); (void)veh_hooks_removed; HADESMEM_DETAIL_ASSERT(veh_hooks_removed); }; auto scope_veh_cleanup_hook = hadesmem::detail::MakeScopeWarden(veh_cleanup_hook); HADESMEM_DETAIL_TRACE_A("Setting DR hook."); auto& dr_hooks = GetDrHooks(); auto const thread_id = ::GetCurrentThreadId(); HADESMEM_DETAIL_ASSERT(dr_hooks.find(thread_id) == std::end(dr_hooks)); Thread const thread(thread_id); auto context = GetThreadContext(thread, CONTEXT_DEBUG_REGISTERS); std::uint32_t dr_index = static_cast<std::uint32_t>(-1); for (std::uint32_t i = 0; i < 4; ++i) { // Check whether the DR is available according to the control register bool const control_available = !(context.Dr7 & (1ULL << (i * 2))); // Check whether the DR is zero. Pobably not actually necessary, but // it's a nice additional sanity check. This may require a // user-controlable flag in future though if the code being hooked is // 'hostile'. bool const dr_available = !(&context.Dr0)[i]; if (control_available && dr_available) { dr_index = i; break; } } if (dr_index == static_cast<std::uint32_t>(-1)) { HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"No free debug registers."}); } dr_hooks[ ::GetCurrentThreadId()] = dr_index; auto const dr_cleanup_hook = [&]() { auto const dr_hooks_removed = dr_hooks.erase(::GetCurrentThreadId()); (void)dr_hooks_removed; HADESMEM_DETAIL_ASSERT(dr_hooks_removed); }; auto scope_dr_cleanup_hook = hadesmem::detail::MakeScopeWarden(dr_cleanup_hook); (&context.Dr0)[dr_index] = reinterpret_cast<std::uintptr_t>(target_); // Set appropriate L0-L3 flag context.Dr7 |= static_cast<std::uintptr_t>(1ULL << (dr_index * 2)); // Set appropriate RW0-RW3 field (Execution) std::uintptr_t break_type = 0; context.Dr7 |= (break_type << (16 + 4 * dr_index)); // Set appropriate LEN0-LEN3 field (1 byte) std::uintptr_t break_len = 0; context.Dr7 |= (break_len << (18 + 4 * dr_index)); // Set LE flag std::uintptr_t local_enable = 1 << 8; context.Dr7 |= local_enable; SetThreadContext(thread, context); scope_veh_cleanup_hook.Dismiss(); scope_dr_cleanup_hook.Dismiss(); }
TARGET_ADDRESS nub_allocate_stack_space (NUB nub, NUBTHREAD nubthread, NUBINT byte_count) { LPDBGPROCESS process = (LPDBGPROCESS) nub; LPDBGTHREAD thread = (LPDBGTHREAD) nubthread; NUBINT code; DWORD count = (DWORD) byte_count; CONTEXT context; CONTEXT context_as_was; BOOL status_get_context, status_set_context, status_write, status_read; ALLOCATOR_INSTRUCTION_SEQUENCE instruction_sequence; ALLOCATOR_INSTRUCTION_SEQUENCE saved_stack_memory; DWORD SP; DWORD IP; DWORD instruction_position; DWORD bytes_written, bytes_read; DWORD expected_bp_address; BOOL spy_has_returned = FALSE; int second_chance_counter = 0; // Get the context for the thread. context.ContextFlags = CONTEXT_FULL; status_get_context = get_thread_context(process, thread, &context); dylan_debugger_message("nub_allocate_stack_space: Thread Context before: %= : %=", thread->ThreadHandle, status_get_context); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); context_as_was = context; if (thread->NeedsBreakpointReplacement) context.EFlags = context.EFlags & 0xFFFFFEFF; // Fill in the instruction sequence SUB ESP, <count>; INT 3 instruction_sequence.Nop1 = 0x90; instruction_sequence.Nop2 = 0x90; instruction_sequence.SubInstruction = 0x81; instruction_sequence.SpecifyEsp = 0xEC; instruction_sequence.Immediate32 = count; instruction_sequence.BreakInstruction = 0xCC; SP = context.Esp; IP = context.Eip; // Write the instruction sequence onto the stack. The number of words we // are writing is small enough that this should work on both NT and // 95. //context.Esp -= sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE); instruction_position = context.Esp; context.Eip = instruction_position; // Save the data that was there originally. As a precaution, we will // re-write this back again if we have to abort the whole procedure. status_read = ReadProcessMemory (process->ProcessHandle, (LPCVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_read); // Out with the old, in with the new... status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &instruction_sequence, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Flush the instruction cache because we have written a segment of // code. FlushInstructionCache(process->ProcessHandle, (LPCVOID) instruction_position, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE)); // Set the context of the thread so that it will execute the SUB instruction // and then return control to the debugger. status_set_context = SetThreadContext(thread->ThreadHandle, &context); if (!status_set_context) { status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); SetThreadContext(thread->ThreadHandle, &context_as_was); // Just in case return(NULL); } // Remember the address at which we expect the breakpoint. expected_bp_address = instruction_position + 8; // Let the thread execute the fragment of code. Hopefully, that will give // us space on the stack that Windows 95 won't crap all over. suspend_all(process); process->ThreadRunningSpy = thread; thread->AddressOfSpyBreakpoint = expected_bp_address; // Explicitly continue all threads to release frozen threads; // they are all suspended at this point so won't be put back // into execution nub_threads_continue(nub); // Now do what it takes to put this Spy running Thread alone into execution execute_thread(thread); wait_for_stop_reason_internal (process, TRUE, 30000, &code, STOP_REASON_WAIT_SPY); if (code == SPY_RETURN_DBG_EVENT) { // Resume the suspended threads. resume_all_except(process, thread); // Write back the stack data that we crapped all over. status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Get the context again. This should have ESP correctly set. status_get_context = GetThreadContext(thread->ThreadHandle, &context); dylan_debugger_message("nub_allocate_stack_space: Thread Context after: %= : %=", thread->ThreadHandle, status_get_context); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); return((TARGET_ADDRESS) (context.Esp)); } else { resume_all_except(process, thread); status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); SetThreadContext(thread->ThreadHandle, &context_as_was); nub_debug_message("Error: Micro Spy call failed on Thread %=, code: %=", (TARGET_ADDRESS)thread->ThreadHandle, (TARGET_ADDRESS)code); return (NULL); } // Resume the suspended threads. resume_all_except(process, thread); // Write back the stack data that we crapped all over. status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Get the context again. This should have ESP correctly set. status_get_context = GetThreadContext(thread->ThreadHandle, &context); return((TARGET_ADDRESS) (context.Esp)); }
bool DebugFrontend::StartProcessAndRunToEntry(LPCSTR exeFileName, LPSTR commandLine, LPCSTR directory, PROCESS_INFORMATION& processInfo) { STARTUPINFO startUpInfo = { 0 }; startUpInfo.cb = sizeof(startUpInfo); ExeInfo info; if (!GetExeInfo(exeFileName, info) || info.entryPoint == 0) { MessageEvent("Error: The entry point for the application could not be located", MessageType_Error); return false; } if (!info.i386) { MessageEvent("Error: Debugging 64-bit applications is not supported", MessageType_Error); return false; } DWORD flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, flags, NULL, directory, &startUpInfo, &processInfo)) { OutputError(GetLastError()); return false; } // Running to the entry point currently doesn't work for managed applications, so // just start it up. if (!info.managed) { unsigned long entryPoint = info.entryPoint; BYTE breakPointData; bool done = false; while (!done) { DEBUG_EVENT debugEvent; WaitForDebugEvent(&debugEvent, INFINITE); DWORD continueStatus = DBG_EXCEPTION_NOT_HANDLED; if (debugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP || debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { CONTEXT context; context.ContextFlags = CONTEXT_FULL; GetThreadContext(processInfo.hThread, &context); if (context.Eip == entryPoint + 1) { // Restore the original code bytes. SetBreakpoint(processInfo.hProcess, (LPVOID)entryPoint, false, &breakPointData); done = true; // Backup the instruction pointer so that we execute the original instruction. --context.Eip; SetThreadContext(processInfo.hThread, &context); // Suspend the thread before we continue the debug event so that the program // doesn't continue to run. SuspendThread(processInfo.hThread); } continueStatus = DBG_CONTINUE; } } else if (debugEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) { done = true; } else if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { // Offset the entry point by the load address of the process. entryPoint += reinterpret_cast<size_t>(debugEvent.u.CreateProcessInfo.lpBaseOfImage); // Write a break point at the entry point of the application so that we // will stop when we reach that point. SetBreakpoint(processInfo.hProcess, reinterpret_cast<void*>(entryPoint), true, &breakPointData); CloseHandle(debugEvent.u.CreateProcessInfo.hFile); } else if (debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) { CloseHandle(debugEvent.u.LoadDll.hFile); } ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, continueStatus); } } DebugActiveProcessStop(processInfo.dwProcessId); return true; }
void _debug_rstr_context(CONTEXT* __context__,kernel_pthread_t *__pthread_ptr__){ CONTEXT __local_context__; __context__->ContextFlags=PTHREAD_CONTEXT_DUMP; memcpy(&__local_context__,__context__,sizeof(CONTEXT)); SetThreadContext(__pthread_ptr__->tcb->hTask, &__local_context__); }
bool clear_break_point( _In_ ch_param* param, _In_ DWORD_PTR address, _In_ unsigned char opcode, _In_ bool reset_eip ) { _ASSERTE(NULL != param); _ASSERTE(0 != address); _ASSERTE(NULL != opcode); if (NULL == param || 0 == address || NULL == opcode) return false; SIZE_T cb_rw = 0; unsigned char temp = 0; BOOL ret = ReadProcessMemory( param->hproc, (LPCVOID)address, &temp, sizeof(unsigned char), &cb_rw ); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); return false; } if (temp != BREAK_OPCODE) { log( "hprocess = 0x%08x, address = 0x%p, opcode = 0x%02x (not BREAK_OPCODE!)", param->hproc, address, temp ); return false; } MEMORY_BASIC_INFORMATION mbi = { 0 }; if (0 == VirtualQueryEx( param->hproc, (LPCVOID)address, &mbi, sizeof(mbi))) { log( "VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); return false; } if (TRUE != VirtualProtectEx( param->hproc, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect)) { log( "VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ) gle = %u", param->hproc, mbi.BaseAddress, mbi.RegionSize, GetLastError() ); return false; } do { ret = WriteProcessMemory( param->hproc, (LPVOID)address, &opcode, sizeof(unsigned char), &cb_rw); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); ret = FALSE; break; } if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char))) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); } } while (false); VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect); if (true == reset_eip) { _ASSERTE(NULL != param->hthread); if (NULL != param->hthread) { #if defined(_AMD64_) param->context.Rip--; #elif defined(_X86_) param->context.Eip--; #else #error !!unsupported architecture!! #endif if (TRUE != SetThreadContext(param->hthread, ¶m->context)) { log( "SetThreadContext(hthread=0x%08x), gle = %u", param->hthread, GetLastError() ); } } } return (TRUE == ret) ? true : false; }
/* Function to setup remote process that waits for this process to exit and then deletes its executable. */ static int SelfDelete() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); /* Create a process using the explorer executable but suspend it immediately. */ if(CreateProcess(0, _T("explorer.exe"), 0, 0, 0, (CREATE_SUSPENDED | IDLE_PRIORITY_CLASS), 0, 0, &si, &pi)) { /* Structure to store code and data to copy to remote process. */ SelfDeleteRemoteCode code; DWORD oldProtect; CONTEXT context; DWORD entryPoint; /* Setup pointers to kernel functions for the remote code to call. */ code.fnWaitForSingleObject = WaitForSingleObject; code.fnCloseHandle = CloseHandle; code.fnDeleteFile = DeleteFile; code.fnSleep = Sleep; code.fnExitProcess = ExitProcess; code.fnGetLastError = GetLastError; /* Give the remote process a copy of our own process handle. */ DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), pi.hProcess, &code.hParent, 0, FALSE, 0); /* Store the file name of this process's executable. */ GetModuleFileName(0, code.szFileName, MAX_PATH); /* Store the binary code to execute remotely. */ memcpy(code.opCodes, SelfDeleteRemoteThread, SELF_DELETE_CODESIZE); /* Allocate some space on process's stack and place our SelfDeleteRemoteCode structure there. Then set the instruction pointer to this location and let the process resume. */ context.ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); GetThreadContext(pi.hThread, &context); /* Allocate space on stack that is aligned to cache-line boundary. */ entryPoint = (context.Esp - sizeof(SelfDeleteRemoteCode)) & ~0x1F; /* Place a pointer to the structure at the bottom-of-stack. This pointer is located in such a way that it becomes the SelfDeleteRemoteThread's first argument. */ code.Arg0 = (SelfDeleteRemoteCode*)entryPoint; /* Set dummy return address for remote thread. It will never return. */ context.Esp = entryPoint - 4; /* Set remote thread to execute the opCodes we copy to the process. */ context.Eip = entryPoint + (((char*)&code.opCodes) - ((char*)&code)); /* Copy the code and data to the remote process entry point. */ VirtualProtectEx(pi.hProcess, (PVOID)entryPoint, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect); WriteProcessMemory(pi.hProcess, (PVOID)entryPoint, &code, sizeof(code), 0); /* Make sure the new code will be loaded. */ FlushInstructionCache(pi.hProcess, (PVOID)entryPoint, sizeof(code)); /* Set the remote thread to execute at our entry point. */ SetThreadContext(pi.hThread, &context); /* Let the remote process continue. It will block until this process exits. */ ResumeThread(pi.hThread); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return 1; } return 0; }
/* * Set the register state of the supplied thread * * req: TLV_TYPE_THREAD_HANDLE - The thread to set * req: TLV_TYPE_REGISTER x N - The registers to set */ DWORD request_sys_process_thread_set_regs(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE thread; DWORD result = ERROR_SUCCESS; do { if ((thread = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_THREAD_HANDLE))) { CONTEXT context; DWORD index = 0; Tlv reg; memset(&context, 0, sizeof(context)); // Get the current thread register state context.ContextFlags = CONTEXT_FULL; if (!GetThreadContext(thread, &context)) { result = GetLastError(); break; } // Enumerate through all of the register we're setting while (packet_enum_tlv(packet, index++, TLV_TYPE_REGISTER, ®) == ERROR_SUCCESS) { LPCSTR name; ULONG value; Tlv nameTlv, valueTlv; // Get the group's entries if ((packet_get_tlv_group_entry(packet, ®, TLV_TYPE_REGISTER_NAME, &nameTlv) != ERROR_SUCCESS) || (packet_get_tlv_group_entry(packet, ®, TLV_TYPE_REGISTER_VALUE_32, &valueTlv) != ERROR_SUCCESS)) continue; // Validate them if ((packet_is_tlv_null_terminated(packet, &nameTlv) != ERROR_SUCCESS) || (valueTlv.header.length < sizeof(ULONG))) continue; // Stash them name = (LPCSTR)nameTlv.buffer; value = ntohl(*(PULONG)valueTlv.buffer); // Set this register's value set_thread_register_value(&context, name, value); } // Update the thread's context if (!SetThreadContext(thread, &context)) { result = GetLastError(); break; } } else result = ERROR_INVALID_PARAMETER; } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* this thread assists with the returns from simulated interrupts ideally, the interrupthandler would just assume the state right before the interrupt, but this is not possible given the x86 and nt, so the interrupt handling thread has to suspend itself, and let some other thread manipulate its state while it is suspended. when this thread runs, interrupts will be disabled, so we reenable them once it is finished. */ DWORD WINAPI interrupt_return_assist(LPVOID ptr) { signal_queue_t *sq; int scount, rcount; int success = FALSE; CONTEXT context; if (DEBUG) kprintf("IRA:starting ...\n"); for(;;) { /* wait politely until we are needed */ WaitOnObject(cleanup); if (DEBUG) kprintf("IRA:woken up ...\n"); WaitOnObject(mutex); { success = FALSE; sq = signalq; signalq = signalq->next; assert(signalq == NULL); /* wait for the system thread to enter a "safe" state */ while(readytoreturn != TRUE) SwitchToThread(); while(success != TRUE) { scount = SuspendThread(sq->threadid); memset(&context, 0, sizeof(CONTEXT)); #ifdef WINCE context.ContextFlags = CONTEXT_FULL; #else context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; #endif AbortOnError(GetThreadContext(system_thread, &context)); if (DEBUG) kprintf("IRA:system thread is at 0x%x.\n", EIP); if((EIP >= loopforever_start_address && EIP <= loopforever_end_address)) { if (DEBUG) kprintf("IRA:enabling interrupts.\n"); interrupt_level = ENABLED; AbortOnError(SetThreadContext(sq->threadid, sq->context)); rcount = ResumeThread(sq->threadid); if (DEBUG) kprintf("IRA:Interrupt return assist scount %d rcount %d\n", scount, rcount); assert(rcount >= scount + 1); success = TRUE; } else { ResumeThread(system_thread); ReleaseMutex(mutex); SwitchToThread(); WaitOnObject(mutex); } } } ReleaseMutex(mutex); free(sq); } /* never reached */ return 0; }
int pthread_cancel (pthread_t thread) /* * ------------------------------------------------------ * DOCPUBLIC * This function requests cancellation of 'thread'. * * PARAMETERS * thread * reference to an instance of pthread_t * * * DESCRIPTION * This function requests cancellation of 'thread'. * NOTE: cancellation is asynchronous; use pthread_join to * wait for termination of 'thread' if necessary. * * RESULTS * 0 successfully requested cancellation, * ESRCH no thread found corresponding to 'thread', * ENOMEM implicit self thread create failed. * ------------------------------------------------------ */ { int result; int cancel_self; pthread_t self; /* This is the proper way to test thread validity. */ result = pthread_kill(thread, 0); if (0 != result) { return result; } if ((self = pthread_self()) == NULL) { return ENOMEM; }; /* * FIXME!! * * Can a thread cancel itself? * * The standard doesn't * specify an error to be returned if the target * thread is itself. * * If it may, then we need to ensure that a thread can't * deadlock itself trying to cancel itself asyncronously * (pthread_cancel is required to be an async-cancel * safe function). */ cancel_self = pthread_equal(thread, self); /* * Lock for async-cancel safety. */ (void) pthread_mutex_lock(&thread->cancelLock); if (thread->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS && thread->cancelState == PTHREAD_CANCEL_ENABLE && thread->state < PThreadStateCanceling ) { if (cancel_self) { thread->state = PThreadStateCanceling; thread->cancelState = PTHREAD_CANCEL_DISABLE; (void) pthread_mutex_unlock(&thread->cancelLock); ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } else { HANDLE threadH = thread->threadH; SuspendThread(threadH); if (WaitForSingleObject(threadH, 0) == WAIT_TIMEOUT ) { CONTEXT context; thread->state = PThreadStateCanceling; thread->cancelState = PTHREAD_CANCEL_DISABLE; context.ContextFlags = CONTEXT_CONTROL; GetThreadContext(threadH, &context); PTW32_PROGCTR(context) = (DWORD) ptw32_cancel_self; SetThreadContext(threadH, &context); (void) pthread_mutex_unlock(&thread->cancelLock); ResumeThread(threadH); } } } else { /* * Set for deferred cancellation. */ if ( thread->state >= PThreadStateCanceling || !SetEvent (thread->cancelEvent)) { result = ESRCH; } (void) pthread_mutex_unlock(&thread->cancelLock); } return (result); }
/* * Send an interrupt to the system thread: adjust its stack to call * the appropriate interrupt handler with the specified argument. the * "type" argument identifies interrupt-specific processing which must * be done, in particular, what we should do if interrupts are * disabled or the system thread is in a non-preemptable state * (e.g. executing a system library function). clock interrupts are * dropped, network interrupts are deferred. this function replaces * code which used to be common to clock_poll and network_poll. */ void send_interrupt(int type, void* arg) { CONTEXT context; int safe_to_proceed = 0; int drop_interrupt = 0; interrupt_queue_t* interrupt_info = NULL; for (;;) { WaitOnObject(mutex); /* need to protect this code: we only activate the interrupt if interrupts are actually enabled, but we also need to ensure they are not disabled after we test -- so we suspend the system thread first. */ SuspendThread(system_thread); memset(&context, 0, sizeof(CONTEXT)); #ifdef WINCE context.ContextFlags = CONTEXT_FULL; #else context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; #endif /* Warning: a printf here makes the system lock */ AbortOnError(GetThreadContext(system_thread, &context)); /* find interrupt description in the interrupt queue */ interrupt_info = interrupt_queue; while (interrupt_info!=NULL && interrupt_info->type!=type) interrupt_info = interrupt_info->next; if (interrupt_info == NULL) { /* * we couldn't find the interrupt with type "type" so we crash the * sistem. */ kprintf("An interrupt of the unregistered type %d was received.\n", type); AbortOnCondition(1,"Crashing."); } else { /* * interrupt-type-specific processing: can we interrupt now? If we * ended up interrupting the process at a time when it is in some non-minithread-safe * Windows library, then defer or drop the interrupt. */ switch (interrupt_info->property){ case INTERRUPT_DROP: if (interrupt_level == DISABLED || (EIP < start_address) || (EIP > end_address)) { drop_interrupt = 1; } else safe_to_proceed = 1; break; case INTERRUPT_DEFER: if (interrupt_level == ENABLED && (EIP >= start_address) && (EIP <= end_address)) { interrupt_level = DISABLED; safe_to_proceed = 1; } break; default: break; } } if (safe_to_proceed == 1) break; else { ResumeThread(system_thread); ReleaseMutex(mutex); if (DEBUG) { switch (interrupt_info->property) { case INTERRUPT_DROP: kprintf("Interrupt of type %d dropped, eip = 0x%x.\n", interrupt_info->type, EIP); break; case INTERRUPT_DEFER: kprintf("Interrupt of type %d deffered, eip = 0x%x.\n", interrupt_info->type, EIP); break; } } } if (drop_interrupt == 1) return; else SwitchToThread(); } /* now fix the system thread's stack so it runs run_user_handler */ { #ifdef _M_AMD64 __int64 stack; #else int stack; #endif if (DEBUG) { kprintf("Interrupts are enabled, system thread pc = 0x%x\n", EIP); kprintf("Adjusting system thread context ...\n"); } /* set the interrupt number */ /* arg->intnumber = ++intnumber; */ stack = ESP; /* Esp == extended stack pointer */ /* safe to do a printf because other thread is stunned in user code */ if (DEBUG) kprintf("Suspended system thread, adjusting stack, sp = 0x%x\n", stack); stack -= (sizeof(CONTEXT) + 64); /* 64 is slop */ /* This alignment is necessary on x64 systems, otherwise it will crash * with error code 998. */ stack += 64 - (stack % 64); /* align to a 64-byte boundary */ memcpy((int *) stack, &context, sizeof(CONTEXT)); EIP = receive_interrupt; REG1 = stack; /*pointer to context*/ REG2 = type; /*type, second argument */ #ifndef WINCE #ifdef _M_AMD64 context.R8 = (__int64) arg; /* space to store registers */ stack -= sizeof(int *) * 5; /* used in debugging the ra */ *(__int64 *) stack = 0xdeadbeefcafebabe; #else /* for x86 put arg pointer on the stack since only two parameters can be passed in registers. */ stack-=sizeof(void*); *((int*)stack)=(int) arg; stack-=sizeof(void*); #endif #else /* for ARM put the third argument in R2 */ context.R2 = (int) arg; #endif ESP = stack; AbortOnError(SetThreadContext(system_thread, &context)); AbortOnError(GetThreadContext(system_thread, &context)); ResumeThread(system_thread); } ReleaseMutex(mutex); }
void InjectDLL64( LPPROCESS_INFORMATION ppi ) { CONTEXT context; DWORD len; LPVOID mem; DWORD64 LLW; union { PBYTE pB; PDWORD64 pL; } ip; #define CODESIZE 92 static BYTE code[CODESIZE+TSIZE(MAX_PATH)] = { 0,0,0,0,0,0,0,0, // original rip 0,0,0,0,0,0,0,0, // LoadLibraryW 0x9C, // pushfq 0x50, // push rax 0x51, // push rcx 0x52, // push rdx 0x53, // push rbx 0x55, // push rbp 0x56, // push rsi 0x57, // push rdi 0x41,0x50, // push r8 0x41,0x51, // push r9 0x41,0x52, // push r10 0x41,0x53, // push r11 0x41,0x54, // push r12 0x41,0x55, // push r13 0x41,0x56, // push r14 0x41,0x57, // push r15 0x48,0x83,0xEC,0x28, // sub rsp, 40 0x48,0x8D,0x0D,41,0,0,0, // lea ecx, L"path\to\errout64.dll" 0xFF,0x15,-49,-1,-1,-1, // call LoadLibraryW 0x48,0x83,0xC4,0x28, // add rsp, 40 0x41,0x5F, // pop r15 0x41,0x5E, // pop r14 0x41,0x5D, // pop r13 0x41,0x5C, // pop r12 0x41,0x5B, // pop r11 0x41,0x5A, // pop r10 0x41,0x59, // pop r9 0x41,0x58, // pop r8 0x5F, // pop rdi 0x5E, // pop rsi 0x5D, // pop rbp 0x5B, // pop rbx 0x5A, // pop rdx 0x59, // pop rcx 0x58, // pop rax 0x9D, // popfq 0xFF,0x25,-91,-1,-1,-1, // jmp original Rip 0, // dword alignment for LLW, fwiw }; len = TSIZE(lstrlen( hDllName ) + 1); if (len > TSIZE(MAX_PATH)) return; CopyMemory( code + CODESIZE, hDllName, len ); len += CODESIZE; context.ContextFlags = CONTEXT_CONTROL; GetThreadContext( ppi->hThread, &context ); mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); LLW = (DWORD64)LoadLibraryW; ip.pB = code; *ip.pL++ = context.Rip; *ip.pL++ = LLW; WriteProcessMemory( ppi->hProcess, mem, code, len, NULL ); FlushInstructionCache( ppi->hProcess, mem, len ); context.Rip = (DWORD64)mem + 16; SetThreadContext( ppi->hThread, &context ); }
/** * Sets a data watch for the given address. * * @address The location to watch. * @size The size of the memory block address points to. Can be 1, 2 or 4 bytes. * @when Determines when to trigger the break point (write or read/write). */ void DataBreakpoint::Set(void* address, int size, Condition when) { if (_register_index != -1) throw std::runtime_error("Watch point already set. Use clear() before setting a new one."); switch (size) { case 1: size = 0; break; case 2: size = 1; break; case 4: size = 3; break; default: throw std::runtime_error("Invalid data length for watch point specified."); } HANDLE currentThread = GetCurrentThread(); // Set up the thread context for this watch point. CONTEXT context; context.ContextFlags = CONTEXT_DEBUG_REGISTERS; // Read the register values if (!GetThreadContext(currentThread, &context)) throw std::runtime_error("Failed getting the current thread context."); // Find an available hardware register. for (_register_index = 0; _register_index < 4; ++_register_index) { if ((context.Dr7 & (REGISTER_TYPE)(1 << (2 * _register_index))) == 0) break; } if (_register_index >= 4) throw std::runtime_error("Could not find a free hardware register."); switch (_register_index) { case 0: context.Dr0 = (REGISTER_TYPE)address; break; case 1: context.Dr1 = (REGISTER_TYPE)address; break; case 2: context.Dr2 = (REGISTER_TYPE)address; break; case 3: context.Dr3 = (REGISTER_TYPE)address; break; } SetBits(context.Dr7, 16 + (4 * _register_index), 2, when); SetBits(context.Dr7, 18 + (4 * _register_index), 2, size); SetBits(context.Dr7, 2 * _register_index, 1, 1); if (!SetThreadContext(currentThread, &context)) throw std::runtime_error("Could not set modified thread context for the watch point."); }
bool DebuggingLoop() { DEBUG_EVENT DebugEvent; CONTEXT ctxThreadContext; DWORD dwDebugState = NULL; PTCHAR sTemp = (PTCHAR)malloc(255 * sizeof(TCHAR)); szTempSym = (PCHAR)malloc(MAX_SYM_NAME); ctxThreadContext.ContextFlags = CONTEXT_FULL; while(bDebugging) { if(!WaitForDebugEvent(&DebugEvent,INFINITE)) { free(sTemp); free(szTempSym); return false; } switch(DebugEvent.dwDebugEventCode) { case LOAD_DLL_DEBUG_EVENT: { SymRefreshModuleList(piProcInfo.hProcess); dwDebugState = DBG_CONTINUE; break; } case CREATE_PROCESS_DEBUG_EVENT: { if(!bSymInit) bSymInit = SymInitialize(piProcInfo.hProcess,NULL,FALSE); dwDebugState = DBG_CONTINUE; break; } case CREATE_THREAD_DEBUG_EVENT: { HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId); GetThreadContext(hThread,&ctxThreadContext); ctxThreadContext.EFlags |= 0x100; SetThreadContext(hThread,&ctxThreadContext); dwDebugState = DBG_CONTINUE; break; } case EXIT_PROCESS_DEBUG_EVENT: { bDebugging = false; dwDebugState = DBG_CONTINUE; break; } case EXCEPTION_DEBUG_EVENT: { switch(DebugEvent.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: { dwDebugState = DBG_CONTINUE; break; } case EXCEPTION_SINGLE_STEP: { HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId); GetThreadContext(hThread,&ctxThreadContext); InsertInfo((DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,DebugEvent.dwThreadId,sTemp); ctxThreadContext.EFlags |= 0x100; SetThreadContext(hThread,&ctxThreadContext); dwDebugState = DBG_CONTINUE; break; } default: dwDebugState = DBG_EXCEPTION_NOT_HANDLED; } break; } default: dwDebugState = DBG_EXCEPTION_NOT_HANDLED; } ContinueDebugEvent(DebugEvent.dwProcessId,DebugEvent.dwThreadId,dwDebugState); } free(sTemp); free(szTempSym); return false; }
static void arm_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event) { SetThreadContext (th->h, &th->context); }
BOOL GetSetThreadContext_Injection() { #ifdef _WIN64 return TRUE; //TODO implement this on x64 #else TCHAR lpApplicationName[] = _T("C:\\Windows\\System32\\svchost.exe"); TCHAR lpApplicationName2[] = _T("C:\\masm32\\examples\\dialogs_later\\basic\\basicdlg.exe"); BOOL bResult = FALSE; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; PCONTEXT pContext = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; SecureZeroMemory(&StartupInfo, sizeof(STARTUPINFO)); SecureZeroMemory(&ProcessInfo, sizeof(PPROCESS_INFORMATION)); do { /* not a loop */ // Create the hollowed process in suspended mode if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo)) { print_last_error(_T("CreateProcess")); break; } // Allocate space for context structure LPVOID pTargetImageBase = NULL; pContext = PCONTEXT(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE)); if (pContext == NULL) { print_last_error(_T("VirtualAlloc")); break; } // Get the thread context of target pContext->ContextFlags = CONTEXT_FULL; if (!GetThreadContext(ProcessInfo.hThread, pContext)) { print_last_error(_T("GetThreadContext")); break; } // Read the image base address of target ReadProcessMemory(ProcessInfo.hProcess, LPCVOID(pContext->Ebx + 8), pTargetImageBase, 4, NULL); // Opening source image hFile = CreateFile(lpApplicationName2, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL); if (hFile == INVALID_HANDLE_VALUE) { print_last_error(_T("CreateFile")); break; } // Reading the file DWORD dwSize = GetFileSize(hFile, 0); DWORD dwBytesRead; PBYTE pBuffer = static_cast<PBYTE>(MALLOC(dwSize)); if (pBuffer == NULL) { print_last_error(_T("HeapAlloc")); break; } else { SecureZeroMemory(pBuffer, dwSize); ReadFile(hFile, pBuffer, dwSize, &dwBytesRead, 0); PIMAGE_SECTION_HEADER pImageSectionHeader; PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuffer; if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) { PIMAGE_NT_HEADERS32 pNTHeaders = PIMAGE_NT_HEADERS(DWORD(pBuffer) + pDosHeader->e_lfanew); if (pNTHeaders->Signature == IMAGE_NT_SIGNATURE) { if (DWORD(pTargetImageBase) == pNTHeaders->OptionalHeader.ImageBase) { pNtUnmapViewOfSection NtUnmapViewOfSection; NtUnmapViewOfSection = (pNtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection")); NtUnmapViewOfSection(ProcessInfo.hProcess, pTargetImageBase); } LPVOID pImageBase; pImageBase = VirtualAllocEx(ProcessInfo.hProcess, LPVOID(pNTHeaders->OptionalHeader.ImageBase), pNTHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pImageBase == NULL) { print_last_error(_T("VirtualAllocEx")); break; } else { WriteProcessMemory(ProcessInfo.hProcess, pImageBase, pBuffer, pNTHeaders->OptionalHeader.SizeOfHeaders, NULL); for (int Count = 0; Count < pNTHeaders->FileHeader.NumberOfSections; Count++) { pImageSectionHeader = PIMAGE_SECTION_HEADER(DWORD(pBuffer) + pDosHeader->e_lfanew + 248 + (Count * 40)); WriteProcessMemory(ProcessInfo.hProcess, LPVOID(DWORD(pImageBase) + pImageSectionHeader->VirtualAddress), LPVOID(DWORD(pBuffer) + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL); } WriteProcessMemory(ProcessInfo.hProcess, LPVOID(pContext->Ebx + 8), LPVOID(&pNTHeaders->OptionalHeader.ImageBase), 4, NULL); pContext->Eax = DWORD(pImageBase) + pNTHeaders->OptionalHeader.AddressOfEntryPoint; SetThreadContext(ProcessInfo.hThread, LPCONTEXT(pContext)); LONG dwRet; dwRet = ResumeThread(ProcessInfo.hThread); bResult = (dwRet != -1); } } } FREE(pBuffer); } } while (FALSE); /* not a loop */ /* Cleanup */ if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess); if (pContext) VirtualFree(pContext, 0, MEM_RELEASE); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); return bResult; #endif }
BOOL MapNewExecutableRegionInProcess( IN HANDLE TargetProcessHandle, IN HANDLE TargetThreadHandle, IN LPVOID NewExecutableRawImage) { PROCESS_BASIC_INFORMATION BasicInformation; PIMAGE_SECTION_HEADER SectionHeader; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader; PMINI_PEB ProcessPeb; NTSTATUS (NTAPI *NtUnmapViewOfSection)(HANDLE, LPVOID) = NULL; NTSTATUS (NTAPI *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG) = NULL; NTSTATUS Status; CONTEXT ThreadContext; LPVOID OldEntryPoint = NULL; LPVOID TargetImageBase = NULL; ULONG SectionIndex = 0; ULONG SizeOfBasicInformation; BOOL Success = FALSE; // // Error checking? Bah. // DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage; NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)NewExecutableRawImage + DosHeader->e_lfanew); do { // // Get the old entry point address by inspecting eax of the current // thread (which should be BaseProcessStart). Eax holds the address // of the entry point for the executable when the process is created // suspended. // ZeroMemory( &ThreadContext, sizeof(ThreadContext)); ThreadContext.ContextFlags = CONTEXT_INTEGER; if (!GetThreadContext( TargetThreadHandle, &ThreadContext)) { break; } OldEntryPoint = (LPVOID) NtHeader->OptionalHeader.ImageBase; // // Unmap the old executable region in the child process to avoid // conflicts // NtUnmapViewOfSection = (NTSTATUS (NTAPI *)(HANDLE, LPVOID))GetProcAddress( GetModuleHandle( TEXT("NTDLL")), "NtUnmapViewOfSection"); NtUnmapViewOfSection(TargetProcessHandle, OldEntryPoint); // // Change the entry point address to the new executable's entry point // ThreadContext.Eax = NtHeader->OptionalHeader.AddressOfEntryPoint + NtHeader->OptionalHeader.ImageBase; if (!SetThreadContext( TargetThreadHandle, &ThreadContext)) break; // // Allocate storage for the new executable in the child process // if (!(TargetImageBase = VirtualAllocEx( TargetProcessHandle, (LPVOID)NtHeader->OptionalHeader.ImageBase, NtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))) break; // // Update the executable's image base address in the PEB... // NtQueryInformationProcess = (NTSTATUS (NTAPI *)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG))GetProcAddress( GetModuleHandle( TEXT("NTDLL")), "NtQueryInformationProcess"); if (NtQueryInformationProcess( TargetProcessHandle, ProcessBasicInformation, &BasicInformation, sizeof(BasicInformation), &SizeOfBasicInformation) != ERROR_SUCCESS) break; ProcessPeb = BasicInformation.PebBaseAddress; if (!WriteProcessMemory( TargetProcessHandle, (LPVOID)&ProcessPeb->ImageBaseAddress, (LPVOID)&NtHeader->OptionalHeader.ImageBase, sizeof(LPVOID), NULL)) break; // // Copy the image headers and all of the section contents // if (!WriteProcessMemory( TargetProcessHandle, TargetImageBase, NewExecutableRawImage, NtHeader->OptionalHeader.SizeOfHeaders, NULL)) break; Success = TRUE; for (SectionIndex = 0, SectionHeader = IMAGE_FIRST_SECTION(NtHeader); SectionIndex < NtHeader->FileHeader.NumberOfSections; SectionIndex++) { // // Skip uninitialized data // if ((!SectionHeader[SectionIndex].SizeOfRawData) || (SectionHeader[SectionIndex].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) continue; if (!WriteProcessMemory( TargetProcessHandle, (LPVOID)((PCHAR)TargetImageBase + SectionHeader[SectionIndex].VirtualAddress), (LPVOID)((PCHAR)NewExecutableRawImage + SectionHeader[SectionIndex].PointerToRawData), SectionHeader[SectionIndex].SizeOfRawData, NULL)) { Success = FALSE; break; } } } while (0); return Success; }