#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 SW2_HEADER_H_ #define SW2_HEADER_H_ #include #define SW2_SEED 0x63191199 #define SW2_ROL8(v) (v << 8 | v >> 24) #define SW2_ROR8(v) (v >> 8 | v << 24) #define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v)) #define SW2_MAX_ENTRIES 500 #define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) // Typedefs are prefixed to avoid pollution. typedef struct _SW2_SYSCALL_ENTRY { DWORD Hash; DWORD Address; } SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY; typedef struct _SW2_SYSCALL_LIST { DWORD Count; SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES]; } SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST; typedef struct _SW2_PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA; typedef struct _SW2_LDR_DATA_TABLE_ENTRY { PVOID Reserved1[2]; LIST_ENTRY InMemoryOrderLinks; PVOID Reserved2[2]; PVOID DllBase; } SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY; typedef struct _SW2_PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PSW2_PEB_LDR_DATA Ldr; } SW2_PEB, *PSW2_PEB; DWORD SW2_HashSyscall(PCSTR FunctionName); BOOL SW2_PopulateSyscallList(); EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash); EXTERN_C NTSTATUS NtProtectVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID * BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG NewProtect, OUT PULONG OldProtect); EXTERN_C NTSTATUS NtAllocateVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID * BaseAddress, IN ULONG ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect); #endif