mirror of
https://github.com/tdeerenberg/InlineWhispers3.git
synced 2025-07-17 00:44:17 +00:00
Add SysWhispers3 data
This commit is contained in:
7
SysWhispers3/.gitignore
vendored
7
SysWhispers3/.gitignore
vendored
@ -1,6 +1 @@
|
||||
.idea
|
||||
!data/*
|
||||
__pycache__
|
||||
*.asm
|
||||
*.c
|
||||
*.h
|
||||
__pycache__
|
||||
|
265
SysWhispers3/data/base.c
Normal file
265
SysWhispers3/data/base.c
Normal file
@ -0,0 +1,265 @@
|
||||
#include "<BASENAME>.h"
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
// JUMPER
|
||||
|
||||
#ifdef _M_IX86
|
||||
|
||||
EXTERN_C PVOID internal_cleancall_wow64_gate(VOID) {
|
||||
return (PVOID)__readfsdword(0xC0);
|
||||
}
|
||||
|
||||
// LOCAL_IS_WOW64
|
||||
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
SW3_SYSCALL_LIST SW3_SyscallList;
|
||||
|
||||
// SEARCH_AND_REPLACE
|
||||
#ifdef SEARCH_AND_REPLACE
|
||||
// THIS IS NOT DEFINED HERE; don't know if I'll add it in a future release
|
||||
EXTERN void SearchAndReplace(unsigned char[], unsigned char[]);
|
||||
#endif
|
||||
|
||||
DWORD SW3_HashSyscall(PCSTR FunctionName)
|
||||
{
|
||||
DWORD i = 0;
|
||||
DWORD Hash = SW3_SEED;
|
||||
|
||||
while (FunctionName[i])
|
||||
{
|
||||
WORD PartialName = *(WORD*)((ULONG_PTR)FunctionName + i++);
|
||||
Hash ^= PartialName + SW3_ROR8(Hash);
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
#ifndef JUMPER
|
||||
PVOID SC_Address(PVOID NtApiAddress)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
PVOID SC_Address(PVOID NtApiAddress)
|
||||
{
|
||||
DWORD searchLimit = 512;
|
||||
PVOID SyscallAddress;
|
||||
|
||||
#ifdef _WIN64
|
||||
// If the process is 64-bit on a 64-bit OS, we need to search for syscall
|
||||
BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 };
|
||||
ULONG distance_to_syscall = 0x12;
|
||||
#else
|
||||
// If the process is 32-bit on a 32-bit OS, we need to search for sysenter
|
||||
BYTE syscall_code[] = { 0x0f, 0x34, 0xc3 };
|
||||
ULONG distance_to_syscall = 0x0f;
|
||||
#endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
// If the process is 32-bit on a 64-bit OS, we need to jump to WOW32Reserved
|
||||
if (local_is_wow64())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[+] Running 32-bit app on x64 (WOW64)\n");
|
||||
#endif
|
||||
// JUMP_TO_WOW32Reserved
|
||||
}
|
||||
#endif
|
||||
|
||||
// we don't really care if there is a 'jmp' between
|
||||
// NtApiAddress and the 'syscall; ret' instructions
|
||||
SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall);
|
||||
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
// we can use the original code for this system call :)
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
|
||||
// the 'syscall; ret' intructions have not been found,
|
||||
// we will try to use one near it, similarly to HalosGate
|
||||
|
||||
for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++)
|
||||
{
|
||||
// let's try with an Nt* API below our syscall
|
||||
SyscallAddress = SW3_RVA2VA(
|
||||
PVOID,
|
||||
NtApiAddress,
|
||||
distance_to_syscall + num_jumps * 0x20);
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
|
||||
// let's try with an Nt* API above our syscall
|
||||
SyscallAddress = SW3_RVA2VA(
|
||||
PVOID,
|
||||
NtApiAddress,
|
||||
distance_to_syscall - num_jumps * 0x20);
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Syscall Opcodes not found!\n");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
BOOL SW3_PopulateSyscallList()
|
||||
{
|
||||
// Return early if the list is already populated.
|
||||
if (SW3_SyscallList.Count) return TRUE;
|
||||
|
||||
#ifdef _WIN64
|
||||
PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60);
|
||||
#else
|
||||
PSW3_PEB Peb = (PSW3_PEB)__readfsdword(0x30);
|
||||
#endif
|
||||
PSW3_PEB_LDR_DATA Ldr = Peb->Ldr;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
|
||||
PVOID DllBase = NULL;
|
||||
|
||||
// Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second
|
||||
// in the list, so it's safer to loop through the full list and find it.
|
||||
PSW3_LDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0])
|
||||
{
|
||||
DllBase = LdrEntry->DllBase;
|
||||
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase;
|
||||
PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew);
|
||||
PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory;
|
||||
DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
if (VirtualAddress == 0) continue;
|
||||
|
||||
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, DllBase, VirtualAddress);
|
||||
|
||||
// If this is NTDLL.dll, exit loop.
|
||||
PCHAR DllName = SW3_RVA2VA(PCHAR, DllBase, ExportDirectory->Name);
|
||||
|
||||
if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue;
|
||||
if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break;
|
||||
}
|
||||
|
||||
if (!ExportDirectory) return FALSE;
|
||||
|
||||
DWORD NumberOfNames = ExportDirectory->NumberOfNames;
|
||||
PDWORD Functions = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions);
|
||||
PDWORD Names = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames);
|
||||
PWORD Ordinals = SW3_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
// Populate SW3_SyscallList with unsorted Zw* entries.
|
||||
DWORD i = 0;
|
||||
PSW3_SYSCALL_ENTRY Entries = SW3_SyscallList.Entries;
|
||||
do
|
||||
{
|
||||
PCHAR FunctionName = SW3_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]);
|
||||
|
||||
// Is this a system call?
|
||||
if (*(USHORT*)FunctionName == 0x775a)
|
||||
{
|
||||
Entries[i].Hash = SW3_HashSyscall(FunctionName);
|
||||
Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]];
|
||||
Entries[i].SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, DllBase, Entries[i].Address));
|
||||
|
||||
i++;
|
||||
if (i == SW3_MAX_ENTRIES) break;
|
||||
}
|
||||
} while (--NumberOfNames);
|
||||
|
||||
// Save total number of system calls found.
|
||||
SW3_SyscallList.Count = i;
|
||||
|
||||
// Sort the list by address in ascending order.
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count - 1; i++)
|
||||
{
|
||||
for (DWORD j = 0; j < SW3_SyscallList.Count - i - 1; j++)
|
||||
{
|
||||
if (Entries[j].Address > Entries[j + 1].Address)
|
||||
{
|
||||
// Swap entries.
|
||||
SW3_SYSCALL_ENTRY TempEntry;
|
||||
|
||||
TempEntry.Hash = Entries[j].Hash;
|
||||
TempEntry.Address = Entries[j].Address;
|
||||
TempEntry.SyscallAddress = Entries[j].SyscallAddress;
|
||||
|
||||
Entries[j].Hash = Entries[j + 1].Hash;
|
||||
Entries[j].Address = Entries[j + 1].Address;
|
||||
Entries[j].SyscallAddress = Entries[j + 1].SyscallAddress;
|
||||
|
||||
Entries[j + 1].Hash = TempEntry.Hash;
|
||||
Entries[j + 1].Address = TempEntry.Address;
|
||||
Entries[j + 1].SyscallAddress = TempEntry.SyscallAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return -1;
|
||||
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count; i++)
|
||||
{
|
||||
if (FunctionHash == SW3_SyscallList.Entries[i].Hash)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return NULL;
|
||||
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count; i++)
|
||||
{
|
||||
if (FunctionHash == SW3_SyscallList.Entries[i].Hash)
|
||||
{
|
||||
return SW3_SyscallList.Entries[i].SyscallAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXTERN_C PVOID SW3_GetRandomSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return NULL;
|
||||
|
||||
DWORD index = ((DWORD) rand()) % SW3_SyscallList.Count;
|
||||
|
||||
while (FunctionHash == SW3_SyscallList.Entries[index].Hash){
|
||||
// Spoofing the syscall return address
|
||||
index = ((DWORD) rand()) % SW3_SyscallList.Count;
|
||||
}
|
||||
return SW3_SyscallList.Entries[index].SyscallAddress;
|
||||
}
|
63
SysWhispers3/data/base.h
Normal file
63
SysWhispers3/data/base.h
Normal file
@ -0,0 +1,63 @@
|
||||
#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 <windows.h>
|
||||
|
||||
#ifndef _NTDEF_
|
||||
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
|
||||
typedef NTSTATUS* PNTSTATUS;
|
||||
#endif
|
||||
|
||||
#define SW3_SEED <SEED_VALUE>
|
||||
#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);
|
563
SysWhispers3/example-output/Syscalls-asm.x64.asm
Normal file
563
SysWhispers3/example-output/Syscalls-asm.x64.asm
Normal file
@ -0,0 +1,563 @@
|
||||
.code
|
||||
|
||||
EXTERN SW3_GetSyscallNumber: PROC
|
||||
|
||||
NtCreateProcess PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 029943818h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtCreateProcess ENDP
|
||||
|
||||
NtCreateThreadEx PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 052B6124Eh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtCreateThreadEx ENDP
|
||||
|
||||
NtOpenProcess PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 00DD60C24h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtOpenProcess ENDP
|
||||
|
||||
NtOpenProcessToken PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0C3914A8Dh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtOpenProcessToken ENDP
|
||||
|
||||
NtTestAlert PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 02EB45D3Ah ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtTestAlert ENDP
|
||||
|
||||
NtOpenThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 075426DE5h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtOpenThread ENDP
|
||||
|
||||
NtSuspendProcess PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0F022DFBFh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtSuspendProcess ENDP
|
||||
|
||||
NtSuspendThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 00F3F9E0Dh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtSuspendThread ENDP
|
||||
|
||||
NtResumeProcess PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 041D54040h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtResumeProcess ENDP
|
||||
|
||||
NtResumeThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0B28FAC35h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtResumeThread ENDP
|
||||
|
||||
NtGetContextThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0BB97FF4Fh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtGetContextThread ENDP
|
||||
|
||||
NtSetContextThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 093B3CF03h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtSetContextThread ENDP
|
||||
|
||||
NtClose PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 04B1B40BBh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtClose ENDP
|
||||
|
||||
NtReadVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 009824143h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtReadVirtualMemory ENDP
|
||||
|
||||
NtWriteVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 08E108490h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtWriteVirtualMemory ENDP
|
||||
|
||||
NtAllocateVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0C253FAF2h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtAllocateVirtualMemory ENDP
|
||||
|
||||
NtProtectVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0C0603A1Dh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtProtectVirtualMemory ENDP
|
||||
|
||||
NtFreeVirtualMemory PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 087118D83h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtFreeVirtualMemory ENDP
|
||||
|
||||
NtQuerySystemInformation PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0A4069EABh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQuerySystemInformation ENDP
|
||||
|
||||
NtQueryDirectoryFile PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 09533C586h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQueryDirectoryFile ENDP
|
||||
|
||||
NtQueryInformationFile PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0AC3E2418h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQueryInformationFile ENDP
|
||||
|
||||
NtQueryInformationProcess PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 002AC0B33h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQueryInformationProcess ENDP
|
||||
|
||||
NtQueryInformationThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0745A2EE3h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQueryInformationThread ENDP
|
||||
|
||||
NtCreateSection PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0F42FD4F1h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtCreateSection ENDP
|
||||
|
||||
NtOpenSection PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 064CE6A2Fh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtOpenSection ENDP
|
||||
|
||||
NtMapViewOfSection PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0508A5019h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtMapViewOfSection ENDP
|
||||
|
||||
NtUnmapViewOfSection PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0DF54DBCEh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtUnmapViewOfSection ENDP
|
||||
|
||||
NtAdjustPrivilegesToken PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 05DC34340h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtAdjustPrivilegesToken ENDP
|
||||
|
||||
NtDeviceIoControlFile PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0D1DAE373h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtDeviceIoControlFile ENDP
|
||||
|
||||
NtQueueApcThread PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 0E851AAFFh ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtQueueApcThread ENDP
|
||||
|
||||
NtWaitForMultipleObjects PROC
|
||||
mov [rsp +8], rcx ; Save registers.
|
||||
mov [rsp+16], rdx
|
||||
mov [rsp+24], r8
|
||||
mov [rsp+32], r9
|
||||
sub rsp, 28h
|
||||
mov ecx, 003837B11h ; Load function hash into ECX.
|
||||
call SW3_GetSyscallNumber ; Resolve function hash into syscall number.
|
||||
add rsp, 28h
|
||||
mov rcx, [rsp+8] ; Restore registers.
|
||||
mov rdx, [rsp+16]
|
||||
mov r8, [rsp+24]
|
||||
mov r9, [rsp+32]
|
||||
mov r10, rcx
|
||||
syscall ; Invoke system call.
|
||||
ret
|
||||
NtWaitForMultipleObjects ENDP
|
||||
|
||||
end
|
278
SysWhispers3/example-output/Syscalls.c
Normal file
278
SysWhispers3/example-output/Syscalls.c
Normal file
@ -0,0 +1,278 @@
|
||||
#include "Syscalls.h"
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
// JUMPER
|
||||
|
||||
#ifdef _M_IX86
|
||||
|
||||
EXTERN_C PVOID internal_cleancall_wow64_gate(VOID) {
|
||||
return (PVOID)__readfsdword(0xC0);
|
||||
}
|
||||
|
||||
__declspec(naked) BOOL local_is_wow64(void)
|
||||
{
|
||||
__asm {
|
||||
mov eax, fs:[0xc0]
|
||||
test eax, eax
|
||||
jne wow64
|
||||
mov eax, 0
|
||||
ret
|
||||
wow64:
|
||||
mov eax, 1
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
SW3_SYSCALL_LIST SW3_SyscallList;
|
||||
|
||||
// SEARCH_AND_REPLACE
|
||||
#ifdef SEARCH_AND_REPLACE
|
||||
// THIS IS NOT DEFINED HERE; don't know if I'll add it in a future release
|
||||
EXTERN void SearchAndReplace(unsigned char[], unsigned char[]);
|
||||
#endif
|
||||
|
||||
DWORD SW3_HashSyscall(PCSTR FunctionName)
|
||||
{
|
||||
DWORD i = 0;
|
||||
DWORD Hash = SW3_SEED;
|
||||
|
||||
while (FunctionName[i])
|
||||
{
|
||||
WORD PartialName = *(WORD*)((ULONG_PTR)FunctionName + i++);
|
||||
Hash ^= PartialName + SW3_ROR8(Hash);
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
#ifndef JUMPER
|
||||
PVOID SC_Address(PVOID NtApiAddress)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
PVOID SC_Address(PVOID NtApiAddress)
|
||||
{
|
||||
DWORD searchLimit = 512;
|
||||
PVOID SyscallAddress;
|
||||
|
||||
#ifdef _WIN64
|
||||
// If the process is 64-bit on a 64-bit OS, we need to search for syscall
|
||||
BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 };
|
||||
ULONG distance_to_syscall = 0x12;
|
||||
#else
|
||||
// If the process is 32-bit on a 32-bit OS, we need to search for sysenter
|
||||
BYTE syscall_code[] = { 0x0f, 0x34, 0xc3 };
|
||||
ULONG distance_to_syscall = 0x0f;
|
||||
#endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
// If the process is 32-bit on a 64-bit OS, we need to jump to WOW32Reserved
|
||||
if (local_is_wow64())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[+] Running 32-bit app on x64 (WOW64)\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// we don't really care if there is a 'jmp' between
|
||||
// NtApiAddress and the 'syscall; ret' instructions
|
||||
SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall);
|
||||
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
// we can use the original code for this system call :)
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
|
||||
// the 'syscall; ret' intructions have not been found,
|
||||
// we will try to use one near it, similarly to HalosGate
|
||||
|
||||
for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++)
|
||||
{
|
||||
// let's try with an Nt* API below our syscall
|
||||
SyscallAddress = SW3_RVA2VA(
|
||||
PVOID,
|
||||
NtApiAddress,
|
||||
distance_to_syscall + num_jumps * 0x20);
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
|
||||
// let's try with an Nt* API above our syscall
|
||||
SyscallAddress = SW3_RVA2VA(
|
||||
PVOID,
|
||||
NtApiAddress,
|
||||
distance_to_syscall - num_jumps * 0x20);
|
||||
if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code)))
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
printf("Found Syscall Opcodes at address 0x%p\n", SyscallAddress);
|
||||
#endif
|
||||
return SyscallAddress;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Syscall Opcodes not found!\n");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
BOOL SW3_PopulateSyscallList()
|
||||
{
|
||||
// Return early if the list is already populated.
|
||||
if (SW3_SyscallList.Count) return TRUE;
|
||||
|
||||
#ifdef _WIN64
|
||||
PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60);
|
||||
#else
|
||||
PSW3_PEB Peb = (PSW3_PEB)__readfsdword(0x30);
|
||||
#endif
|
||||
PSW3_PEB_LDR_DATA Ldr = Peb->Ldr;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
|
||||
PVOID DllBase = NULL;
|
||||
|
||||
// Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second
|
||||
// in the list, so it's safer to loop through the full list and find it.
|
||||
PSW3_LDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0])
|
||||
{
|
||||
DllBase = LdrEntry->DllBase;
|
||||
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase;
|
||||
PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew);
|
||||
PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory;
|
||||
DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
if (VirtualAddress == 0) continue;
|
||||
|
||||
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, DllBase, VirtualAddress);
|
||||
|
||||
// If this is NTDLL.dll, exit loop.
|
||||
PCHAR DllName = SW3_RVA2VA(PCHAR, DllBase, ExportDirectory->Name);
|
||||
|
||||
if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) continue;
|
||||
if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) break;
|
||||
}
|
||||
|
||||
if (!ExportDirectory) return FALSE;
|
||||
|
||||
DWORD NumberOfNames = ExportDirectory->NumberOfNames;
|
||||
PDWORD Functions = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions);
|
||||
PDWORD Names = SW3_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames);
|
||||
PWORD Ordinals = SW3_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
// Populate SW3_SyscallList with unsorted Zw* entries.
|
||||
DWORD i = 0;
|
||||
PSW3_SYSCALL_ENTRY Entries = SW3_SyscallList.Entries;
|
||||
do
|
||||
{
|
||||
PCHAR FunctionName = SW3_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]);
|
||||
|
||||
// Is this a system call?
|
||||
if (*(USHORT*)FunctionName == 0x775a)
|
||||
{
|
||||
Entries[i].Hash = SW3_HashSyscall(FunctionName);
|
||||
Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]];
|
||||
Entries[i].SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, DllBase, Entries[i].Address));
|
||||
|
||||
i++;
|
||||
if (i == SW3_MAX_ENTRIES) break;
|
||||
}
|
||||
} while (--NumberOfNames);
|
||||
|
||||
// Save total number of system calls found.
|
||||
SW3_SyscallList.Count = i;
|
||||
|
||||
// Sort the list by address in ascending order.
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count - 1; i++)
|
||||
{
|
||||
for (DWORD j = 0; j < SW3_SyscallList.Count - i - 1; j++)
|
||||
{
|
||||
if (Entries[j].Address > Entries[j + 1].Address)
|
||||
{
|
||||
// Swap entries.
|
||||
SW3_SYSCALL_ENTRY TempEntry;
|
||||
|
||||
TempEntry.Hash = Entries[j].Hash;
|
||||
TempEntry.Address = Entries[j].Address;
|
||||
TempEntry.SyscallAddress = Entries[j].SyscallAddress;
|
||||
|
||||
Entries[j].Hash = Entries[j + 1].Hash;
|
||||
Entries[j].Address = Entries[j + 1].Address;
|
||||
Entries[j].SyscallAddress = Entries[j + 1].SyscallAddress;
|
||||
|
||||
Entries[j + 1].Hash = TempEntry.Hash;
|
||||
Entries[j + 1].Address = TempEntry.Address;
|
||||
Entries[j + 1].SyscallAddress = TempEntry.SyscallAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return -1;
|
||||
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count; i++)
|
||||
{
|
||||
if (FunctionHash == SW3_SyscallList.Entries[i].Hash)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return NULL;
|
||||
|
||||
for (DWORD i = 0; i < SW3_SyscallList.Count; i++)
|
||||
{
|
||||
if (FunctionHash == SW3_SyscallList.Entries[i].Hash)
|
||||
{
|
||||
return SW3_SyscallList.Entries[i].SyscallAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXTERN_C PVOID SW3_GetRandomSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW3_SyscallList is populated.
|
||||
if (!SW3_PopulateSyscallList()) return NULL;
|
||||
|
||||
DWORD index = ((DWORD) rand()) % SW3_SyscallList.Count;
|
||||
|
||||
while (FunctionHash == SW3_SyscallList.Entries[index].Hash){
|
||||
// Spoofing the syscall return address
|
||||
index = ((DWORD) rand()) % SW3_SyscallList.Count;
|
||||
}
|
||||
return SW3_SyscallList.Entries[index].SyscallAddress;
|
||||
}
|
487
SysWhispers3/example-output/Syscalls.h
Normal file
487
SysWhispers3/example-output/Syscalls.h
Normal file
@ -0,0 +1,487 @@
|
||||
#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 <windows.h>
|
||||
|
||||
#define SW3_SEED 0x769430A3
|
||||
#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 500
|
||||
#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);
|
||||
typedef struct _SYSTEM_HANDLE
|
||||
{
|
||||
ULONG ProcessId;
|
||||
BYTE ObjectTypeNumber;
|
||||
BYTE Flags;
|
||||
USHORT Handle;
|
||||
PVOID Object;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
||||
|
||||
typedef struct _IO_STATUS_BLOCK
|
||||
{
|
||||
union
|
||||
{
|
||||
NTSTATUS Status;
|
||||
VOID* Pointer;
|
||||
};
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION
|
||||
{
|
||||
ULONG HandleCount;
|
||||
SYSTEM_HANDLE Handles[1];
|
||||
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
|
||||
|
||||
typedef VOID(KNORMAL_ROUTINE) (
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2);
|
||||
|
||||
typedef struct _PS_ATTRIBUTE
|
||||
{
|
||||
ULONG Attribute;
|
||||
SIZE_T Size;
|
||||
union
|
||||
{
|
||||
ULONG Value;
|
||||
PVOID ValuePtr;
|
||||
} u1;
|
||||
PSIZE_T ReturnLength;
|
||||
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;
|
||||
|
||||
typedef struct _UNICODE_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
#ifndef InitializeObjectAttributes
|
||||
#define InitializeObjectAttributes( p, n, a, r, s ) { \
|
||||
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||
(p)->RootDirectory = r; \
|
||||
(p)->Attributes = a; \
|
||||
(p)->ObjectName = n; \
|
||||
(p)->SecurityDescriptor = s; \
|
||||
(p)->SecurityQualityOfService = NULL; \
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct _OBJECT_ATTRIBUTES
|
||||
{
|
||||
ULONG Length;
|
||||
HANDLE RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||
|
||||
typedef struct _CLIENT_ID
|
||||
{
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
typedef enum _SYSTEM_INFORMATION_CLASS
|
||||
{
|
||||
SystemBasicInformation = 0,
|
||||
SystemPerformanceInformation = 2,
|
||||
SystemTimeOfDayInformation = 3,
|
||||
SystemProcessInformation = 5,
|
||||
SystemProcessorPerformanceInformation = 8,
|
||||
SystemHandleInformation = 16,
|
||||
SystemInterruptInformation = 23,
|
||||
SystemExceptionInformation = 33,
|
||||
SystemRegistryQuotaInformation = 37,
|
||||
SystemLookasideInformation = 45,
|
||||
SystemCodeIntegrityInformation = 103,
|
||||
SystemPolicyInformation = 134,
|
||||
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
|
||||
|
||||
typedef enum _PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0,
|
||||
ProcessDebugPort = 7,
|
||||
ProcessWow64Information = 26,
|
||||
ProcessImageFileName = 27,
|
||||
ProcessBreakOnTermination = 29
|
||||
} PROCESSINFOCLASS, *PPROCESSINFOCLASS;
|
||||
|
||||
typedef enum _WAIT_TYPE
|
||||
{
|
||||
WaitAll = 0,
|
||||
WaitAny = 1
|
||||
} WAIT_TYPE, *PWAIT_TYPE;
|
||||
|
||||
typedef VOID(NTAPI* PIO_APC_ROUTINE) (
|
||||
IN PVOID ApcContext,
|
||||
IN PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN ULONG Reserved);
|
||||
|
||||
typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;
|
||||
|
||||
typedef enum _THREADINFOCLASS
|
||||
{
|
||||
ThreadBasicInformation,
|
||||
ThreadTimes,
|
||||
ThreadPriority,
|
||||
ThreadBasePriority,
|
||||
ThreadAffinityMask,
|
||||
ThreadImpersonationToken,
|
||||
ThreadDescriptorTableEntry,
|
||||
ThreadEnableAlignmentFaultFixup,
|
||||
ThreadEventPair_Reusable,
|
||||
ThreadQuerySetWin32StartAddress,
|
||||
ThreadZeroTlsCell,
|
||||
ThreadPerformanceCount,
|
||||
ThreadAmILastThread,
|
||||
ThreadIdealProcessor,
|
||||
ThreadPriorityBoost,
|
||||
ThreadSetTlsArrayAddress,
|
||||
ThreadIsIoPending,
|
||||
ThreadHideFromDebugger,
|
||||
ThreadBreakOnTermination,
|
||||
MaxThreadInfoClass
|
||||
} THREADINFOCLASS, *PTHREADINFOCLASS;
|
||||
|
||||
typedef enum _SECTION_INHERIT
|
||||
{
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
} SECTION_INHERIT, *PSECTION_INHERIT;
|
||||
|
||||
typedef enum _FILE_INFORMATION_CLASS
|
||||
{
|
||||
FileDirectoryInformation = 1,
|
||||
FileFullDirectoryInformation = 2,
|
||||
FileBothDirectoryInformation = 3,
|
||||
FileBasicInformation = 4,
|
||||
FileStandardInformation = 5,
|
||||
FileInternalInformation = 6,
|
||||
FileEaInformation = 7,
|
||||
FileAccessInformation = 8,
|
||||
FileNameInformation = 9,
|
||||
FileRenameInformation = 10,
|
||||
FileLinkInformation = 11,
|
||||
FileNamesInformation = 12,
|
||||
FileDispositionInformation = 13,
|
||||
FilePositionInformation = 14,
|
||||
FileFullEaInformation = 15,
|
||||
FileModeInformation = 16,
|
||||
FileAlignmentInformation = 17,
|
||||
FileAllInformation = 18,
|
||||
FileAllocationInformation = 19,
|
||||
FileEndOfFileInformation = 20,
|
||||
FileAlternateNameInformation = 21,
|
||||
FileStreamInformation = 22,
|
||||
FilePipeInformation = 23,
|
||||
FilePipeLocalInformation = 24,
|
||||
FilePipeRemoteInformation = 25,
|
||||
FileMailslotQueryInformation = 26,
|
||||
FileMailslotSetInformation = 27,
|
||||
FileCompressionInformation = 28,
|
||||
FileObjectIdInformation = 29,
|
||||
FileCompletionInformation = 30,
|
||||
FileMoveClusterInformation = 31,
|
||||
FileQuotaInformation = 32,
|
||||
FileReparsePointInformation = 33,
|
||||
FileNetworkOpenInformation = 34,
|
||||
FileAttributeTagInformation = 35,
|
||||
FileTrackingInformation = 36,
|
||||
FileIdBothDirectoryInformation = 37,
|
||||
FileIdFullDirectoryInformation = 38,
|
||||
FileValidDataLengthInformation = 39,
|
||||
FileShortNameInformation = 40,
|
||||
FileIoCompletionNotificationInformation = 41,
|
||||
FileIoStatusBlockRangeInformation = 42,
|
||||
FileIoPriorityHintInformation = 43,
|
||||
FileSfioReserveInformation = 44,
|
||||
FileSfioVolumeInformation = 45,
|
||||
FileHardLinkInformation = 46,
|
||||
FileProcessIdsUsingFileInformation = 47,
|
||||
FileNormalizedNameInformation = 48,
|
||||
FileNetworkPhysicalNameInformation = 49,
|
||||
FileIdGlobalTxDirectoryInformation = 50,
|
||||
FileIsRemoteDeviceInformation = 51,
|
||||
FileUnusedInformation = 52,
|
||||
FileNumaNodeInformation = 53,
|
||||
FileStandardLinkInformation = 54,
|
||||
FileRemoteProtocolInformation = 55,
|
||||
FileRenameInformationBypassAccessCheck = 56,
|
||||
FileLinkInformationBypassAccessCheck = 57,
|
||||
FileVolumeNameInformation = 58,
|
||||
FileIdInformation = 59,
|
||||
FileIdExtdDirectoryInformation = 60,
|
||||
FileReplaceCompletionInformation = 61,
|
||||
FileHardLinkFullIdInformation = 62,
|
||||
FileIdExtdBothDirectoryInformation = 63,
|
||||
FileDispositionInformationEx = 64,
|
||||
FileRenameInformationEx = 65,
|
||||
FileRenameInformationExBypassAccessCheck = 66,
|
||||
FileMaximumInformation = 67,
|
||||
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _PS_ATTRIBUTE_LIST
|
||||
{
|
||||
SIZE_T TotalLength;
|
||||
PS_ATTRIBUTE Attributes[1];
|
||||
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;
|
||||
|
||||
EXTERN_C NTSTATUS NtCreateProcess(
|
||||
OUT PHANDLE ProcessHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN HANDLE ParentProcess,
|
||||
IN BOOLEAN InheritObjectTable,
|
||||
IN HANDLE SectionHandle OPTIONAL,
|
||||
IN HANDLE DebugPort OPTIONAL,
|
||||
IN HANDLE ExceptionPort OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtCreateThreadEx(
|
||||
OUT PHANDLE ThreadHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID StartRoutine,
|
||||
IN PVOID Argument OPTIONAL,
|
||||
IN ULONG CreateFlags,
|
||||
IN SIZE_T ZeroBits,
|
||||
IN SIZE_T StackSize,
|
||||
IN SIZE_T MaximumStackSize,
|
||||
IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtOpenProcess(
|
||||
OUT PHANDLE ProcessHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN PCLIENT_ID ClientId OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtOpenProcessToken(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE TokenHandle);
|
||||
|
||||
EXTERN_C NTSTATUS NtTestAlert();
|
||||
|
||||
EXTERN_C NTSTATUS NtOpenThread(
|
||||
OUT PHANDLE ThreadHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN PCLIENT_ID ClientId OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtSuspendProcess(
|
||||
IN HANDLE ProcessHandle);
|
||||
|
||||
EXTERN_C NTSTATUS NtSuspendThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
OUT PULONG PreviousSuspendCount);
|
||||
|
||||
EXTERN_C NTSTATUS NtResumeProcess(
|
||||
IN HANDLE ProcessHandle);
|
||||
|
||||
EXTERN_C NTSTATUS NtResumeThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN OUT PULONG PreviousSuspendCount OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtGetContextThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN OUT PCONTEXT ThreadContext);
|
||||
|
||||
EXTERN_C NTSTATUS NtSetContextThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN PCONTEXT Context);
|
||||
|
||||
EXTERN_C NTSTATUS NtClose(
|
||||
IN HANDLE Handle);
|
||||
|
||||
EXTERN_C NTSTATUS NtReadVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress OPTIONAL,
|
||||
OUT PVOID Buffer,
|
||||
IN SIZE_T BufferSize,
|
||||
OUT PSIZE_T NumberOfBytesRead OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtWriteVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN PVOID Buffer,
|
||||
IN SIZE_T NumberOfBytesToWrite,
|
||||
OUT PSIZE_T NumberOfBytesWritten OPTIONAL);
|
||||
|
||||
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);
|
||||
|
||||
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 NtFreeVirtualMemory(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID * BaseAddress,
|
||||
IN OUT PSIZE_T RegionSize,
|
||||
IN ULONG FreeType);
|
||||
|
||||
EXTERN_C NTSTATUS NtQuerySystemInformation(
|
||||
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
IN OUT PVOID SystemInformation,
|
||||
IN ULONG SystemInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtQueryDirectoryFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event OPTIONAL,
|
||||
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
IN PVOID ApcContext OPTIONAL,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
OUT PVOID FileInformation,
|
||||
IN ULONG Length,
|
||||
IN FILE_INFORMATION_CLASS FileInformationClass,
|
||||
IN BOOLEAN ReturnSingleEntry,
|
||||
IN PUNICODE_STRING FileName OPTIONAL,
|
||||
IN BOOLEAN RestartScan);
|
||||
|
||||
EXTERN_C NTSTATUS NtQueryInformationFile(
|
||||
IN HANDLE FileHandle,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
OUT PVOID FileInformation,
|
||||
IN ULONG Length,
|
||||
IN FILE_INFORMATION_CLASS FileInformationClass);
|
||||
|
||||
EXTERN_C NTSTATUS NtQueryInformationProcess(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PROCESSINFOCLASS ProcessInformationClass,
|
||||
OUT PVOID ProcessInformation,
|
||||
IN ULONG ProcessInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtQueryInformationThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN THREADINFOCLASS ThreadInformationClass,
|
||||
OUT PVOID ThreadInformation,
|
||||
IN ULONG ThreadInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtCreateSection(
|
||||
OUT PHANDLE SectionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN PLARGE_INTEGER MaximumSize OPTIONAL,
|
||||
IN ULONG SectionPageProtection,
|
||||
IN ULONG AllocationAttributes,
|
||||
IN HANDLE FileHandle OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtOpenSection(
|
||||
OUT PHANDLE SectionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
|
||||
EXTERN_C NTSTATUS NtMapViewOfSection(
|
||||
IN HANDLE SectionHandle,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN OUT PVOID BaseAddress,
|
||||
IN ULONG ZeroBits,
|
||||
IN SIZE_T CommitSize,
|
||||
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
|
||||
IN OUT PSIZE_T ViewSize,
|
||||
IN SECTION_INHERIT InheritDisposition,
|
||||
IN ULONG AllocationType,
|
||||
IN ULONG Win32Protect);
|
||||
|
||||
EXTERN_C NTSTATUS NtUnmapViewOfSection(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress);
|
||||
|
||||
EXTERN_C NTSTATUS NtAdjustPrivilegesToken(
|
||||
IN HANDLE TokenHandle,
|
||||
IN BOOLEAN DisableAllPrivileges,
|
||||
IN PTOKEN_PRIVILEGES NewState OPTIONAL,
|
||||
IN ULONG BufferLength,
|
||||
OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
|
||||
OUT PULONG ReturnLength OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtDeviceIoControlFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event OPTIONAL,
|
||||
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
IN PVOID ApcContext OPTIONAL,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN ULONG IoControlCode,
|
||||
IN PVOID InputBuffer OPTIONAL,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength);
|
||||
|
||||
EXTERN_C NTSTATUS NtQueueApcThread(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN PKNORMAL_ROUTINE ApcRoutine,
|
||||
IN PVOID ApcArgument1 OPTIONAL,
|
||||
IN PVOID ApcArgument2 OPTIONAL,
|
||||
IN PVOID ApcArgument3 OPTIONAL);
|
||||
|
||||
EXTERN_C NTSTATUS NtWaitForMultipleObjects(
|
||||
IN ULONG Count,
|
||||
IN PHANDLE Handles,
|
||||
IN WAIT_TYPE WaitType,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER Timeout OPTIONAL);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user