#pragma once // Code below is adapted from @modexpblog. Read linked article for more details. // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams #ifndef SW3_HEADER_H_ #define SW3_HEADER_H_ #include #ifndef _NTDEF_ typedef _Return_type_success_(return >= 0) LONG NTSTATUS; typedef NTSTATUS* PNTSTATUS; #endif #define SW3_SEED #define SW3_ROL8(v) (v << 8 | v >> 24) #define SW3_ROR8(v) (v >> 8 | v << 24) #define SW3_ROX8(v) ((SW3_SEED % 2) ? SW3_ROL8(v) : SW3_ROR8(v)) #define SW3_MAX_ENTRIES 600 #define SW3_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) // Typedefs are prefixed to avoid pollution. typedef struct _SW3_SYSCALL_ENTRY { DWORD Hash; DWORD Address; PVOID SyscallAddress; } SW3_SYSCALL_ENTRY, *PSW3_SYSCALL_ENTRY; typedef struct _SW3_SYSCALL_LIST { DWORD Count; SW3_SYSCALL_ENTRY Entries[SW3_MAX_ENTRIES]; } SW3_SYSCALL_LIST, *PSW3_SYSCALL_LIST; typedef struct _SW3_PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } SW3_PEB_LDR_DATA, *PSW3_PEB_LDR_DATA; typedef struct _SW3_LDR_DATA_TABLE_ENTRY { PVOID Reserved1[2]; LIST_ENTRY InMemoryOrderLinks; PVOID Reserved2[2]; PVOID DllBase; } SW3_LDR_DATA_TABLE_ENTRY, *PSW3_LDR_DATA_TABLE_ENTRY; typedef struct _SW3_PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PSW3_PEB_LDR_DATA Ldr; } SW3_PEB, *PSW3_PEB; DWORD SW3_HashSyscall(PCSTR FunctionName); BOOL SW3_PopulateSyscallList(); EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); EXTERN_C PVOID internal_cleancall_wow64_gate(VOID);