├── .gitignore ├── LICENSE ├── README.md ├── ThreadJect.VC.db ├── ThreadJect.sln └── ThreadJect ├── ThreadJect.vcxproj ├── ThreadJect.vcxproj.filters ├── main.cpp └── ntdll.lib /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | Pods 19 | 20 | ## Ignore Visual Studio temporary files, build results, and 21 | ## files generated by popular Visual Studio add-ons. 22 | 23 | # User-specific files 24 | *.suo 25 | *.user 26 | *.userosscache 27 | *.sln.docstates 28 | 29 | # Build results 30 | [Dd]ebug/ 31 | [Dd]ebugPublic/ 32 | [Rr]elease/ 33 | [Rr]eleases/ 34 | x64/ 35 | x86/ 36 | build/ 37 | bld/ 38 | [Bb]in/ 39 | [Oo]bj/ 40 | 41 | # Visual Studio 2015 cache/options directory 42 | .vs/ 43 | 44 | *_i.c 45 | *_p.c 46 | *_i.h 47 | *.ilk 48 | *.meta 49 | *.obj 50 | *.pch 51 | *.pdb 52 | *.pgc 53 | *.pgd 54 | *.rsp 55 | *.sbr 56 | *.tlb 57 | *.tli 58 | *.tlh 59 | *.tmp 60 | *.tmp_proj 61 | *.log 62 | *.vspscc 63 | *.vssscc 64 | .builds 65 | *.pidb 66 | *.svclog 67 | *.scc 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | *.o 78 | Sample 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Bill Demirkapi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ThreadJect 2 | ## Description 3 | Proof-of-Concept Manual DLL Injector that hijacks a thread in order to load dll into target process. 4 | ## Demonstration 5 | [![Demonstration](https://img.youtube.com/vi/5vbEJr7Yt5U/0.jpg)](https://www.youtube.com/watch?v=5vbEJr7Yt5U) 6 | ## How does it work? 7 | 1. Open DLL and read content into buffer 8 | 2. Make sure the file is a DLL and headers are properly defined 9 | 3. Adjust Privilege & open the target process based on PID provided in first cmd argument 10 | 4. Copy DLL into target process 11 | 5. Copy loader information into target process 12 | 6. Copy loader function into target process 13 | 7. Find thread to hijack 14 | 8. Suspend target thread 15 | 9. Modify shellcode with proper addresses (ex: address to loader func, address to inject info) 16 | 10. Copy shellcode to call our loader function 17 | 11. Modify Thread EIP to go to our shellcode 18 | 12. Shellcode calls loader function with injection info as first argument 19 | 13. Resume target thread - should be injected now 20 | ## Usage 21 | ``` 22 | ThreadJect.exe 23 | ``` 24 | ## Credits 25 | ``` 26 | @ZwClose7 on Rohitab - Base LoadLibrary Injector (uses Thread Hijacking) and his CreateRemoteThread Manual DLL Injector 27 | @D4stiny (me) - Modified LoadLibrary Injector by adding code from the CreateRemoteThread injector and changing the shellcode that is used in the thread hijacking to support the manual mapping of the DLL. 28 | ``` -------------------------------------------------------------------------------- /ThreadJect.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D4stiny/ThreadJect/9ff33205a499f494d6f394d65c448fd921b7a4e0/ThreadJect.VC.db -------------------------------------------------------------------------------- /ThreadJect.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadJect", "ThreadJect\ThreadJect.vcxproj", "{268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Debug|Win32.ActiveCfg = Release|Win32 15 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Debug|Win32.Build.0 = Release|Win32 16 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Debug|Win32.Deploy.0 = Release|Win32 17 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Release|Win32.ActiveCfg = Release|Win32 18 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Release|Win32.Build.0 = Release|Win32 19 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC}.Release|Win32.Deploy.0 = Release|Win32 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /ThreadJect/ThreadJect.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {268C73A1-C7ED-43A7-9907-D5D99DE6BDAC} 15 | Win32Proj 16 | ThreadJect 17 | ThreadJect 18 | 19 | 20 | 21 | Application 22 | true 23 | v140 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v140_xp 30 | true 31 | NotSet 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | NotUsing 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 70 | MultiThreaded 71 | false 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ThreadJect/ThreadJect.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /ThreadJect/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2017 Bill Demirkapi 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | typedef HMODULE(WINAPI *pLoadLibraryA)(LPCSTR); 30 | typedef FARPROC(WINAPI *pGetProcAddress)(HMODULE, LPCSTR); 31 | 32 | typedef BOOL(WINAPI *PDLL_MAIN)(HMODULE, DWORD, PVOID); 33 | 34 | typedef struct _MANUAL_INJECT 35 | { 36 | PVOID ImageBase; 37 | PIMAGE_NT_HEADERS NtHeaders; 38 | PIMAGE_BASE_RELOCATION BaseRelocation; 39 | PIMAGE_IMPORT_DESCRIPTOR ImportDirectory; 40 | pLoadLibraryA fnLoadLibraryA; 41 | pGetProcAddress fnGetProcAddress; 42 | }MANUAL_INJECT, *PMANUAL_INJECT; 43 | 44 | DWORD WINAPI LoadDll(PVOID p) 45 | { 46 | PMANUAL_INJECT ManualInject; 47 | 48 | HMODULE hModule; 49 | DWORD i, Function, count, delta; 50 | 51 | PDWORD ptr; 52 | PWORD list; 53 | 54 | PIMAGE_BASE_RELOCATION pIBR; 55 | PIMAGE_IMPORT_DESCRIPTOR pIID; 56 | PIMAGE_IMPORT_BY_NAME pIBN; 57 | PIMAGE_THUNK_DATA FirstThunk, OrigFirstThunk; 58 | 59 | PDLL_MAIN EntryPoint; 60 | 61 | ManualInject = (PMANUAL_INJECT)p; 62 | 63 | pIBR = ManualInject->BaseRelocation; 64 | delta = (DWORD)((LPBYTE)ManualInject->ImageBase - ManualInject->NtHeaders->OptionalHeader.ImageBase); // Calculate the delta 65 | 66 | // Relocate the image 67 | 68 | while (pIBR->VirtualAddress) 69 | { 70 | if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) 71 | { 72 | count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); 73 | list = (PWORD)(pIBR + 1); 74 | 75 | for (i = 0; iImageBase + (pIBR->VirtualAddress + (list[i] & 0xFFF))); 80 | *ptr += delta; 81 | } 82 | } 83 | } 84 | 85 | pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR + pIBR->SizeOfBlock); 86 | } 87 | 88 | pIID = ManualInject->ImportDirectory; 89 | 90 | // Resolve DLL imports 91 | 92 | while (pIID->Characteristics) 93 | { 94 | OrigFirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase + pIID->OriginalFirstThunk); 95 | FirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase + pIID->FirstThunk); 96 | 97 | hModule = ManualInject->fnLoadLibraryA((LPCSTR)ManualInject->ImageBase + pIID->Name); 98 | 99 | if (!hModule) 100 | { 101 | return FALSE; 102 | } 103 | 104 | while (OrigFirstThunk->u1.AddressOfData) 105 | { 106 | if (OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) 107 | { 108 | // Import by ordinal 109 | 110 | Function = (DWORD)ManualInject->fnGetProcAddress(hModule, (LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF)); 111 | 112 | if (!Function) 113 | { 114 | return FALSE; 115 | } 116 | 117 | FirstThunk->u1.Function = Function; 118 | } 119 | 120 | else 121 | { 122 | // Import by name 123 | 124 | pIBN = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)ManualInject->ImageBase + OrigFirstThunk->u1.AddressOfData); 125 | Function = (DWORD)ManualInject->fnGetProcAddress(hModule, (LPCSTR)pIBN->Name); 126 | 127 | if (!Function) 128 | { 129 | return FALSE; 130 | } 131 | 132 | FirstThunk->u1.Function = Function; 133 | } 134 | 135 | OrigFirstThunk++; 136 | FirstThunk++; 137 | } 138 | 139 | pIID++; 140 | } 141 | 142 | if (ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint) 143 | { 144 | EntryPoint = (PDLL_MAIN)((LPBYTE)ManualInject->ImageBase + ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint); 145 | return EntryPoint((HMODULE)ManualInject->ImageBase, DLL_PROCESS_ATTACH, NULL); // Call the entry point 146 | } 147 | 148 | return TRUE; 149 | } 150 | 151 | DWORD WINAPI LoadDllEnd() 152 | { 153 | return 0; 154 | } 155 | 156 | 157 | #pragma comment(lib,"ntdll.lib") 158 | 159 | extern "C" NTSTATUS NTAPI RtlAdjustPrivilege(ULONG Privilege,BOOLEAN Enable,BOOLEAN CurrentThread,PBOOLEAN Enabled); 160 | 161 | char code[]= 162 | { 163 | 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x81, 0xEB, 0x06, 0x00, 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xBA, 0xCC, 0xCC, 0xCC, 0xCC, 0x52, 0xFF, 0xD0, 0x61, 0x68, 0xCC, 0xCC, 0xCC, 0xCC, 0xC3 164 | }; // x86 ONLY shellcode - will need to change for x64 165 | 166 | int main(int argc,char* argv[]) 167 | { 168 | 169 | LPBYTE ptr; 170 | HANDLE hProcess,hThread,hSnap,hFile; 171 | PVOID mem, mem1; 172 | DWORD ProcessId, FileSize, read, i; 173 | PVOID buffer, image; 174 | BOOLEAN bl; 175 | PIMAGE_DOS_HEADER pIDH; 176 | PIMAGE_NT_HEADERS pINH; 177 | PIMAGE_SECTION_HEADER pISH; 178 | 179 | THREADENTRY32 te32; 180 | CONTEXT ctx; 181 | 182 | MANUAL_INJECT ManualInject; 183 | 184 | printf("\n***********************************************************\n"); 185 | printf("\nThreadJect by zwclose7 and github.com/D4stiny - Manual DLL injection via thread hijacking\n"); 186 | printf("\n***********************************************************\n"); 187 | te32.dwSize=sizeof(te32); 188 | ctx.ContextFlags=CONTEXT_FULL; 189 | 190 | if(argc!=3) 191 | { 192 | printf("\nUsage: ThreadJect [PID] [DLL name]\n"); 193 | return -1; 194 | } 195 | 196 | printf("\nOpening the DLL.\n"); 197 | hFile = CreateFile(argv[2], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // Open the DLL 198 | 199 | if (hFile == INVALID_HANDLE_VALUE) 200 | { 201 | printf("\nError: Unable to open the DLL (%d)\n", GetLastError()); 202 | return -1; 203 | } 204 | 205 | FileSize = GetFileSize(hFile, NULL); 206 | buffer = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 207 | 208 | if (!buffer) 209 | { 210 | printf("\nError: Unable to allocate memory for DLL data (%d)\n", GetLastError()); 211 | 212 | CloseHandle(hFile); 213 | return -1; 214 | } 215 | 216 | // Read the DLL 217 | 218 | if (!ReadFile(hFile, buffer, FileSize, &read, NULL)) 219 | { 220 | printf("\nError: Unable to read the DLL (%d)\n", GetLastError()); 221 | 222 | VirtualFree(buffer, 0, MEM_RELEASE); 223 | CloseHandle(hFile); 224 | 225 | return -1; 226 | } 227 | 228 | CloseHandle(hFile); 229 | 230 | pIDH = (PIMAGE_DOS_HEADER)buffer; 231 | 232 | if (pIDH->e_magic != IMAGE_DOS_SIGNATURE) 233 | { 234 | printf("\nError: Invalid executable image.\n"); 235 | 236 | VirtualFree(buffer, 0, MEM_RELEASE); 237 | return -1; 238 | } 239 | 240 | pINH = (PIMAGE_NT_HEADERS)((LPBYTE)buffer + pIDH->e_lfanew); 241 | 242 | if (pINH->Signature != IMAGE_NT_SIGNATURE) 243 | { 244 | printf("\nError: Invalid PE header.\n"); 245 | 246 | VirtualFree(buffer, 0, MEM_RELEASE); 247 | return -1; 248 | } 249 | 250 | if (!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL)) 251 | { 252 | printf("\nError: The image is not DLL.\n"); 253 | 254 | VirtualFree(buffer, 0, MEM_RELEASE); 255 | return -1; 256 | } 257 | 258 | RtlAdjustPrivilege(20,TRUE,FALSE,&bl); 259 | 260 | printf("\nOpening target process handle.\n"); 261 | 262 | ProcessId=atoi(argv[1]); 263 | hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId); 264 | 265 | if(!hProcess) 266 | { 267 | printf("\nError: Unable to open target process handle (%d)\n",GetLastError()); 268 | return -1; 269 | } 270 | 271 | printf("\nAllocating memory for the DLL.\n"); 272 | image = VirtualAllocEx(hProcess, NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Allocate memory for the DLL 273 | 274 | if (!image) 275 | { 276 | printf("\nError: Unable to allocate memory for the DLL (%d)\n", GetLastError()); 277 | 278 | VirtualFree(buffer, 0, MEM_RELEASE); 279 | CloseHandle(hProcess); 280 | 281 | return -1; 282 | } 283 | 284 | // Copy the header to target process 285 | 286 | printf("\nCopying headers into target process.\n"); 287 | 288 | if (!WriteProcessMemory(hProcess, image, buffer, pINH->OptionalHeader.SizeOfHeaders, NULL)) 289 | { 290 | printf("\nError: Unable to copy headers to target process (%d)\n", GetLastError()); 291 | 292 | VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); 293 | CloseHandle(hProcess); 294 | 295 | VirtualFree(buffer, 0, MEM_RELEASE); 296 | return -1; 297 | } 298 | 299 | pISH = (PIMAGE_SECTION_HEADER)(pINH + 1); 300 | 301 | // Copy the DLL to target process 302 | 303 | printf("\nCopying sections to target process.\n"); 304 | 305 | for (i = 0; iFileHeader.NumberOfSections; i++) 306 | { 307 | WriteProcessMemory(hProcess, (PVOID)((LPBYTE)image + pISH[i].VirtualAddress), (PVOID)((LPBYTE)buffer + pISH[i].PointerToRawData), pISH[i].SizeOfRawData, NULL); 308 | } 309 | 310 | printf("\nAllocating memory for the loader code.\n"); 311 | mem1 = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Allocate memory for the loader code 312 | 313 | if (!mem1) 314 | { 315 | printf("\nError: Unable to allocate memory for the loader code (%d)\n", GetLastError()); 316 | 317 | VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); 318 | CloseHandle(hProcess); 319 | 320 | VirtualFree(buffer, 0, MEM_RELEASE); 321 | return -1; 322 | } 323 | 324 | printf("\nLoader code allocated at %#x\n", mem1); 325 | memset(&ManualInject, 0, sizeof(MANUAL_INJECT)); 326 | 327 | ManualInject.ImageBase = image; 328 | ManualInject.NtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)image + pIDH->e_lfanew); 329 | ManualInject.BaseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 330 | ManualInject.ImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 331 | ManualInject.fnLoadLibraryA = LoadLibraryA; 332 | ManualInject.fnGetProcAddress = GetProcAddress; 333 | 334 | printf("\nWriting loader code to target process.\n"); 335 | 336 | WriteProcessMemory(hProcess, mem1, &ManualInject, sizeof(MANUAL_INJECT), NULL); // Write the loader information to target process 337 | WriteProcessMemory(hProcess, (PVOID)((PMANUAL_INJECT)mem1 + 1), LoadDll, (DWORD)LoadDllEnd - (DWORD)LoadDll, NULL); // Write the loader code to target process 338 | 339 | hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0); 340 | 341 | Thread32First(hSnap,&te32); 342 | printf("\nFinding a thread to hijack.\n"); 343 | 344 | while(Thread32Next(hSnap,&te32)) 345 | { 346 | if(te32.th32OwnerProcessID==ProcessId) 347 | { 348 | printf("\nTarget thread found. Thread ID: %d\n",te32.th32ThreadID); 349 | break; 350 | } 351 | } 352 | 353 | CloseHandle(hSnap); 354 | 355 | printf("\nAllocating memory in target process.\n"); 356 | 357 | mem=VirtualAllocEx(hProcess,NULL,4096,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); 358 | 359 | if(!mem) 360 | { 361 | printf("\nError: Unable to allocate memory in target process (%d)",GetLastError()); 362 | 363 | CloseHandle(hProcess); 364 | return -1; 365 | } 366 | 367 | printf("\nMemory allocated at %#x\n",mem); 368 | printf("\nOpening target thread handle.\n"); 369 | 370 | hThread=OpenThread(THREAD_ALL_ACCESS,FALSE,te32.th32ThreadID); 371 | 372 | if(!hThread) 373 | { 374 | printf("\nError: Unable to open target thread handle (%d)\n",GetLastError()); 375 | 376 | VirtualFreeEx(hProcess,mem,0,MEM_RELEASE); 377 | CloseHandle(hProcess); 378 | return -1; 379 | } 380 | 381 | printf("\nSuspending target thread.\n"); 382 | 383 | SuspendThread(hThread); 384 | GetThreadContext(hThread,&ctx); 385 | 386 | buffer=VirtualAlloc(NULL,65536,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); 387 | ptr=(LPBYTE)buffer; 388 | 389 | memcpy(buffer,code,sizeof(code)); 390 | 391 | while(1) 392 | { 393 | if(*ptr==0xb8 && *(PDWORD)(ptr+1)==0xCCCCCCCC) 394 | { 395 | *(PDWORD)(ptr+1)=(DWORD)((PMANUAL_INJECT)mem1 + 1); 396 | } 397 | 398 | if(*ptr==0x68 && *(PDWORD)(ptr+1)==0xCCCCCCCC) 399 | { 400 | *(PDWORD)(ptr+1)=ctx.Eip; 401 | } 402 | 403 | if (*ptr == 0xba && *(PDWORD)(ptr + 1) == 0xCCCCCCCC) 404 | { 405 | *(PDWORD)(ptr + 1) = (DWORD)(mem1); 406 | } 407 | 408 | if(*ptr==0xc3) 409 | { 410 | ptr++; 411 | break; 412 | } 413 | 414 | ptr++; 415 | } 416 | 417 | printf("\nWriting shellcode into target process.\n"); 418 | 419 | if(!WriteProcessMemory(hProcess,mem,buffer,sizeof(code),NULL)) // + 0x4 because a DWORD is 0x4 big 420 | { 421 | printf("\nError: Unable to write shellcode into target process (%d)\n",GetLastError()); 422 | 423 | VirtualFreeEx(hProcess,mem,0,MEM_RELEASE); 424 | ResumeThread(hThread); 425 | 426 | CloseHandle(hThread); 427 | CloseHandle(hProcess); 428 | 429 | VirtualFree(buffer,0,MEM_RELEASE); 430 | return -1; 431 | } 432 | 433 | ctx.Eip=(DWORD)mem; 434 | 435 | printf("\nHijacking target thread.\n"); 436 | 437 | if(!SetThreadContext(hThread,&ctx)) 438 | { 439 | printf("\nError: Unable to hijack target thread (%d)\n",GetLastError()); 440 | 441 | VirtualFreeEx(hProcess,mem,0,MEM_RELEASE); 442 | ResumeThread(hThread); 443 | 444 | CloseHandle(hThread); 445 | CloseHandle(hProcess); 446 | 447 | VirtualFree(buffer,0,MEM_RELEASE); 448 | return -1; 449 | } 450 | 451 | printf("\nResuming target thread.\n"); 452 | 453 | ResumeThread(hThread); 454 | 455 | CloseHandle(hThread); 456 | CloseHandle(hProcess); 457 | 458 | VirtualFree(buffer,0,MEM_RELEASE); 459 | return 0; 460 | } -------------------------------------------------------------------------------- /ThreadJect/ntdll.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D4stiny/ThreadJect/9ff33205a499f494d6f394d65c448fd921b7a4e0/ThreadJect/ntdll.lib --------------------------------------------------------------------------------