Skip to content

Commit

Permalink
Adding x86 Support (Wow64+native) with refactoring. This commit is si…
Browse files Browse the repository at this point in the history
…milar to jthuraisamy#9 and some inspiration from https://github.com/mai1zhi2/SysWhispers2_x86/blob/main/SysWhispers2_x86_WOW64Gate/SyscallsStubs.asm.

Updated README.md with instructions to support both x86 and x64 targets.
Updated base.c to support x86 registers
Updated syswhispers.py to add x86 and x64 stubs to support a refactored version that uses fewer redundant instructions.
  • Loading branch information
xenoscr committed Feb 27, 2022
1 parent 82c9e3b commit 533c686
Show file tree
Hide file tree
Showing 8 changed files with 5,111 additions and 7,832 deletions.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,34 @@ Using the `--preset common` switch will create a header/ASM pair with the follow
1. Copy the generated H/C/ASM files into the project folder.
2. In Visual Studio, go to *Project**Build Customizations...* and enable MASM.
3. In the *Solution Explorer*, add the .h and .c/.asm files to the project as header and source files, respectively.
4. Go to the properties of the ASM file, and set the *Item Type* to *Microsoft Macro Assembler*.
5. Ensure that the project platform is set to x64. 32-bit projects are not supported at this time.
4. Go to the properties of the x86 ASM file.
5. Select *All Configurations* from the *Configurations* drop-down.
6. Select *Win32* from the Platform drop-down.
7. Set the following options:
- *Excluded From Build* = *No*
- *Content* = *Yes*
- *Item Type* = *Microsoft Macro Assembler*
8. Click *Apply*
9. Select *x64* from the *Platform* drop-down.
10. Set the following options:
- *Excluded From Build* = *Yes*
- *Content* = *Yes*
- *Item Type* = *Microsoft Macro Assembler*
11. Click *Apply*, then *OK*.
12. Go to the properties of the x64 ASM file.
13. Select *All Configurations* from the *Configurations* drop-down.
14. Select *Win32* from the Platform drop-down.
15. Set the following options:
- *Excluded From Build* = *Yes*
- *Content* = *Yes*
- *Item Type* = *Microsoft Macro Assembler*
16. Click *Apply*
17. Select *x64* from the *Platform* drop-down.
18. Set the following options:
- *Excluded From Build* = *No*
- *Content* = *Yes*
- *Item Type* = *Microsoft Macro Assembler*
19. Click *Apply*, then *OK*.

## Caveats and Limitations

Expand Down
4 changes: 4 additions & 0 deletions data/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ BOOL SW2_PopulateSyscallList(void)
// Return early if the list is already populated.
if (SW2_SyscallList.Count) return TRUE;

#ifdef _WIN64
PSW2_PEB Peb = (PSW2_PEB)__readgsqword(0x60);
#else
PSW2_PEB Peb = (PSW2_PEB)__readfsdword(0x30);
#endif
PSW2_PEB_LDR_DATA Ldr = Peb->Ldr;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
PVOID DllBase = NULL;
Expand Down
8 changes: 6 additions & 2 deletions example-output/Syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ DWORD SW2_HashSyscall(PCSTR FunctionName)
return Hash;
}

BOOL SW2_PopulateSyscallList()
BOOL SW2_PopulateSyscallList(void)
{
// Return early if the list is already populated.
if (SW2_SyscallList.Count) return TRUE;

#ifdef _WIN64
PSW2_PEB Peb = (PSW2_PEB)__readgsqword(0x60);
#else
PSW2_PEB Peb = (PSW2_PEB)__readfsdword(0x30);
#endif
PSW2_PEB_LDR_DATA Ldr = Peb->Ldr;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
PVOID DllBase = NULL;
Expand Down Expand Up @@ -79,7 +83,7 @@ BOOL SW2_PopulateSyscallList()
SW2_SyscallList.Count = i;

// Sort the list by address in ascending order.
for (DWORD i = 0; i < SW2_SyscallList.Count - 1; i++)
for (i = 0; i < SW2_SyscallList.Count - 1; i++)
{
for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++)
{
Expand Down
180 changes: 96 additions & 84 deletions example-output/Syscalls.h
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
#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 <Windows.h>

#define SW2_SEED 0x874DD416
#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);

#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 <Windows.h>

#define SW2_SEED 0x62BE744E
#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(void);
EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash);

typedef struct _UNICODE_STRING
{
USHORT Length;
Expand Down Expand Up @@ -88,25 +88,6 @@ typedef struct _WNF_TYPE_ID
GUID TypeId;
} WNF_TYPE_ID, *PWNF_TYPE_ID;

typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef enum _KCONTINUE_TYPE
{
KCONTINUE_UNWIND,
KCONTINUE_RESUME,
KCONTINUE_LONGJUMP,
KCONTINUE_SET,
KCONTINUE_LAST
} KCONTINUE_TYPE;

typedef enum _PS_CREATE_STATE
{
PsCreateInitialState,
Expand All @@ -119,18 +100,37 @@ typedef enum _PS_CREATE_STATE
PsCreateMaximumStates
} PS_CREATE_STATE, *PPS_CREATE_STATE;

typedef struct _SYSTEM_HANDLE_INFORMATION
typedef enum _KCONTINUE_TYPE
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
KCONTINUE_UNWIND,
KCONTINUE_RESUME,
KCONTINUE_LONGJUMP,
KCONTINUE_SET,
KCONTINUE_LAST
} KCONTINUE_TYPE;

typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

typedef enum _PLUGPLAY_EVENT_CATEGORY
{
HardwareProfileChangeEvent,
Expand Down Expand Up @@ -197,11 +197,6 @@ typedef struct _PS_ATTRIBUTE
PSIZE_T ReturnLength;
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;

typedef struct _WNF_STATE_NAME
{
ULONG Data[2];
} WNF_STATE_NAME, *PWNF_STATE_NAME;

#ifndef InitializeObjectAttributes
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
Expand All @@ -213,6 +208,11 @@ typedef struct _WNF_STATE_NAME
}
#endif

typedef struct _WNF_STATE_NAME
{
ULONG Data[2];
} WNF_STATE_NAME, *PWNF_STATE_NAME;

typedef struct _KEY_VALUE_ENTRY
{
PUNICODE_STRING ValueName;
Expand Down Expand Up @@ -4046,4 +4046,16 @@ EXTERN_C NTSTATUS NtContinueEx(
IN PCONTEXT ContextRecord,
IN PKCONTINUE_ARGUMENT ContinueArgument);

EXTERN_C NTSTATUS RtlCreateUserThread(
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits,
IN OUT PULONG StackReserved,
IN OUT PULONG StackCommit,
IN PVOID StartAddress,
IN PVOID StartParameter OPTIONAL,
OUT PHANDLE ThreadHandle,
OUT PCLIENT_ID ClientID);

#endif

0 comments on commit 533c686

Please sign in to comment.