Sandboxie/Sandboxie/core/dll/Win32.c

755 lines
24 KiB
C

/*
* Copyright 2020-2022 David Xanatos, xanasoft.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// Win32 Services
//---------------------------------------------------------------------------
#define NOGDI
#include "dll.h"
#include "debug.h"
#include "common\pattern.h"
#include "common\arm64_asm.h"
#include "core/drv/api_defs.h"
#include "core/low/lowdata.h"
#ifndef _WIN64
#include "common\dllimport.h"
NTSTATUS SbieApi_ProtectVirtualMemory(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, ULONG flNewProtect, ULONG* lpflOldProtect);
NTSTATUS SbieApi_ReadVirtualMemory(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, ULONG64* lpNumberOfBytesRead);
NTSTATUS SbieApi_WriteVirtualMemory(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, ULONG64* lpNumberOfBytesWritten);
NTSTATUS SbieApi_FlushInstructionCache(HANDLE hProcess, DWORD64 lpBaseAddress, SIZE_T nSize);
NTSTATUS SbieApi_QueryVirtualMemory(HANDLE hProcess, DWORD64 BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength);
BOOLEAN Win32_HookWin32WoW64();
#endif
#ifdef _M_ARM64EC
ULONG Hook_GetSysCallFunc(ULONG* aCode, void** pHandleStubHijack);
ULONG* SbieDll_FindFirstSysCallFunc(ULONG* aCode, void** pHandleStubHijack);
void* SbieDll_GetEcExitThunk(void* HandleStubHijack);
#endif
ULONG SbieDll_GetSysCallOffset(const ULONG *SyscallPtr, ULONG syscall_index);
extern SBIELOW_DATA* SbieApi_data;
#define SBIELOW_CALL(x) ((P_##x)&data->x##_code)
//---------------------------------------------------------------------------
// Win32_HookWin32SysCalls
//---------------------------------------------------------------------------
_FX BOOLEAN Win32_HookWin32SysCalls(HMODULE win32u_base)
{
UCHAR *SystemServiceAsm;
ULONG *SyscallPtr;
ULONG SyscallNum;
void *RegionBase;
SIZE_T RegionSize;
ULONG OldProtect;
SBIELOW_DATA* data = SbieApi_data;
SystemServiceAsm = (UCHAR*)data->pSystemService;
UCHAR* syscall_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, 16384); // enough room for over 2000 syscalls
if (!syscall_data)
return FALSE;
if (!NT_SUCCESS(SbieApi_Call(API_QUERY_SYSCALLS, 2, (ULONG_PTR)syscall_data, 1))) {
HeapFree(GetProcessHeap(), 0, syscall_data);
return FALSE;
}
//
// our syscall data area describes the ZwXxx functions in ntdll,
// overwrite each export to jump to our assembly SystemService
// see also core/drv/syscall.c and core/svc/DriverInjectAssist.cpp
//
SyscallPtr = (ULONG *)(syscall_data
+ sizeof(ULONG)); // size of buffer
#ifdef _M_ARM64EC
ULONG* aCode = SbieDll_FindFirstSysCallFunc((ULONG*)win32u_base, NULL);
if (aCode == NULL) {
HeapFree(GetProcessHeap(), 0, syscall_data);
return FALSE;
}
for (ULONG pos = 0; pos < 128; aCode++, pos += 4) {
SyscallNum = Hook_GetSysCallFunc(aCode, NULL);
if (SyscallNum == -1)
continue;
if (SbieDll_GetSysCallOffset(SyscallPtr, SyscallNum)) {
RegionBase = aCode;
RegionSize = 16;
SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize,
PAGE_EXECUTE_READWRITE, &OldProtect);
MOV mov;
mov.OP = 0xD2800011; // mov x17, #0xFFFF
mov.imm16 = (USHORT)SyscallNum;
*aCode++ = mov.OP;
*aCode++ = 0x18000048; // ldr w8, 8
*aCode++ = 0xD61F0100; // br x8
*(ULONG*)aCode = (ULONG)(ULONG_PTR)SystemServiceAsm;
SBIELOW_CALL(NtFlushInstructionCache)(
NtCurrentProcess(), RegionBase, (ULONG)RegionSize);
SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize,
OldProtect, &OldProtect);
}
//if (aCode[13] != 0 || aCode[14] != 0 || aCode[15] != 0 || aCode[16] != 0)
// break;
//aCode += (13 + 3 + 3 + 1);
aCode += 16;
pos = 0; // reset
}
#else
while (SyscallPtr[0] || SyscallPtr[1]) {
//
// the ULONG at SyscallPtr[1] gives the offset of the ZwXxx export
// from the base address of ntdll
//
UCHAR* ZwXxxPtr = (UCHAR *)((ULONG_PTR)SyscallPtr[1] + (UCHAR*)win32u_base);
//
// make the syscall address writable
//
RegionBase = ZwXxxPtr;
#ifdef _M_ARM64
RegionSize = 16;
#elif _WIN64
RegionSize = 14;
#else ! _WIN64
RegionSize = 10;
#endif _WIN64
//
// SyscallPtr[0] specifies the syscall number in the low 24 bits.
// on 32-bit Windows, also specifies the parameter count (in bytes)
// in the high 8 bits. this is used by SystemServiceAsm
//
// overwrite the ZwXxx export to call our SystemServiceAsm,
// and then restore the original page protection
//
SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize,
PAGE_EXECUTE_READWRITE, &OldProtect);
SyscallNum = SyscallPtr[0];
#ifdef _M_ARM64
ULONG* aCode = (ULONG*)ZwXxxPtr;
MOV mov;
mov.OP = 0xD2800011; // mov x17, #0xFFFF
mov.imm16 = (USHORT)SyscallNum;
*aCode++ = mov.OP;
*aCode++ = 0x18000048; // ldr w8, 8
*aCode++ = 0xD61F0100; // br x8
*(ULONG*)aCode = (ULONG)(ULONG_PTR)SystemServiceAsm;
SBIELOW_CALL(NtFlushInstructionCache)(
NtCurrentProcess(), RegionBase, (ULONG)RegionSize);
#elif _WIN64
ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber
ZwXxxPtr[1] = 0xC7;
ZwXxxPtr[2] = 0xC2;
*(ULONG *)&ZwXxxPtr[3] = SyscallNum;
if (!data->flags.long_diff) {
if (data->flags.is_win10) {
ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm
ZwXxxPtr[8] = 0xE9;
*(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13));
}
else {
ZwXxxPtr[7] = 0xe9; // jmp SystemServiceAsm
*(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 12));
}
}
else {
ZwXxxPtr[7] = 0xB8; // mov eax, SystemServiceAsm
*(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm;
*(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax
}
#else ! _WIN64
ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber, with param count in the highest byte
*(ULONG *)&ZwXxxPtr[1] = SyscallNum;
ZwXxxPtr[5] = 0xE9; // jmp SystemServiceAsm
*(ULONG *)&ZwXxxPtr[6] =
(ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 10));
#endif _WIN64
SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize,
OldProtect, &OldProtect);
SyscallPtr += 2;
}
#endif
HeapFree(GetProcessHeap(), 0, syscall_data);
return TRUE;
}
//---------------------------------------------------------------------------
// Win32_Init
//---------------------------------------------------------------------------
_FX BOOLEAN Win32_Init(HMODULE hmodule)
{
Dll_Win32u = hmodule;
// In Windows 10 all Win32k.sys calls are located in win32u.dll
if (Dll_OsBuild < 10041 || (Dll_ProcessFlags & SBIE_FLAG_WIN32K_HOOKABLE) == 0 || !SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", TRUE))
return TRUE; // just return on older builds, or not enabled
if (Dll_CompartmentMode || SbieApi_data->flags.bNoSysHooks)
return TRUE; // no syscall hooking in comaprtment mode
//
// chrome needs for a working GPU acceleration the GdiDdDDI* win32k syscalls to have the right user token
// this however with some other software causes issues, presumably as then other syscalls would need to have the same token
//
BOOLEAN useByDefualt = (Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME);
if (SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"UseWin32kHooks", useByDefualt)) {
// disable Electron Workaround when we are ready to hook the required win32k syscalls
extern BOOL Dll_ElectronWorkaround;
Dll_ElectronWorkaround = FALSE;
#ifndef _WIN64
if (Dll_IsWow64)
Win32_HookWin32WoW64(); // WoW64 hooks
else
#endif
Win32_HookWin32SysCalls(hmodule); // Native x86/x64 hooks
}
return TRUE;
}
#ifndef _WIN64
//---------------------------------------------------------------------------
// Win32_GetSysCallNumberWoW64
//---------------------------------------------------------------------------
ULONG Win32_GetSysCallNumberWoW64(DWORD64 pos, UCHAR* dll_data)
{
// 4C 8B D1 - r10,rcx
if (!(dll_data[pos + 0] == 0x4c && dll_data[pos + 1] == 0x8b && dll_data[pos + 2] == 0xd1))
return 0;
// B8 XX XX XX XX - mov eax,0xXXXX
if (!(dll_data[pos + 3] == 0xb8))
return 0;
ULONG syscall_index = *(ULONG*)&dll_data[pos + 4];
// F6 04 25 08 03 FE 7F 01 - test BYTE PTR ds:0x7ffe0308,0x1
//
// 75 03 - jne 0x15 (label_1)
if (!(dll_data[pos + 16] == 0x75 && dll_data[pos + 17] == 0x03))
return 0;
// 0F 05 - syscall
if (!(dll_data[pos + 18] == 0x0f && dll_data[pos + 19] == 0x05))
return 0;
// C3 - ret
if (!(dll_data[pos + 20] == 0xc3))
return 0;
// label_1:
// CD 2E - int 0x2e
if (!(dll_data[pos + 21] == 0xcd && dll_data[pos + 22] == 0x2e))
return 0;
// C3 - ret
if (!(dll_data[pos + 23] == 0xc3))
return 0;
//
return syscall_index;
}
//---------------------------------------------------------------------------
// Win32_GetSysCallNumberArm64
//---------------------------------------------------------------------------
_FX ULONG Win32_GetSysCallNumberArm64(ULONG* aCode)
{
// 0: e10000d4 svc #0x1000
SVC svc;
svc.OP = aCode[0];
if (!IS_SVC(svc) || svc.imm16 < 0x1000) // win32 syscalls are >= 0x1000
return -1;
// 1: c0035fd6 ret
if (aCode[1] != 0xd65f03c0)
return -1;
return svc.imm16;
}
//---------------------------------------------------------------------------
// Win32_HookWin32WoW64
//---------------------------------------------------------------------------
_FX BOOLEAN Win32_HookWin32WoW64()
{
BOOLEAN ok = FALSE;
UCHAR* dll_data = NULL;
UCHAR* syscall_data = NULL;
//
// first set up the 64 bit capable NtQueryVirtualMemory64 for FindDllBase64
//
extern void* NtQueryVirtualMemory64;
if (!NtQueryVirtualMemory64)
NtQueryVirtualMemory64 = SbieApi_QueryVirtualMemory;
//
// get the 64-bit address of the wow64win.dll
//
DWORD64 BaseAddress = FindDllBase64(NtCurrentProcess(), L"wow64win.dll");
SIZE_T SizeOfImage = 0x00100000; // 1 MB should be more than enough
if (!BaseAddress) {
SbieApi_Log(2303, L"win32k, wow64win.dll base not found");
return FALSE;
}
dll_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)SizeOfImage);
if (!dll_data) {
SbieApi_Log(2303, L"win32k, alloc failed (1)");
goto finish;
}
ULONG64 SizeRead;
if (!NT_SUCCESS(SbieApi_ReadVirtualMemory(NtCurrentProcess(), (PVOID64)BaseAddress, dll_data, SizeOfImage, &SizeRead))) {
SbieApi_Log(2303, L"win32k, wow64win.dll read failed");
goto finish;
}
DWORD64 SystemServiceAsm;
ULONG* SyscallPtr;
ULONG SyscallNum;
DWORD64 RegionBase;
SIZE_T RegionSize;
ULONG OldProtect;
SBIELOW_DATA* data = SbieApi_data;
SystemServiceAsm = data->pSystemService;
syscall_data = (UCHAR*)HeapAlloc(GetProcessHeap(), 0, 16384); // enough room for over 2000 syscalls
if (!syscall_data) {
SbieApi_Log(2303, L"win32k, alloc failed (2)");
goto finish;
}
if (!NT_SUCCESS(SbieApi_Call(API_QUERY_SYSCALLS, 2, (ULONG_PTR)syscall_data, 1))) {
SbieApi_Log(2303, L"win32k, syscall query failed");
goto finish;
}
SyscallPtr = (ULONG*)(syscall_data + sizeof(ULONG)); // size of buffer
if (Dll_IsXtAjit) { // x86 on arm64
UCHAR* ZwXxxPtr;
ULONG* aCode = (ULONG*)dll_data;
for (ULONG64 pos = 0; pos < SizeRead; aCode++, pos += 4) {
if (Win32_GetSysCallNumberArm64(aCode) != -1)
break;
}
if ((DWORD64)aCode >= (DWORD64)dll_data + SizeRead) {
SbieApi_Log(2303, L"win32k, get first syscall wrapper failed");
goto finish;
}
for (ULONG pos = 0; pos < 128; aCode++, pos += 4) {
ULONG SyscallNum = Win32_GetSysCallNumberArm64(aCode);
if (SyscallNum == -1)
continue;
if (SbieDll_GetSysCallOffset(SyscallPtr, SyscallNum)) {
DWORD64 offset = (DWORD64)aCode - (DWORD64)dll_data;
RegionBase = BaseAddress + offset;
RegionSize = 16;
//
// prepare call to call our SystemServiceAsm
//
ZwXxxPtr = aCode;
MOV mov;
mov.OP = 0xD2800011; // mov x17, #0xFFFF
mov.imm16 = (USHORT)SyscallNum;
*aCode++ = mov.OP;
*aCode++ = 0x18000048; // ldr w8, 8
*aCode++ = 0xD61F0100; // br x8
*(ULONG*)aCode = (ULONG)(ULONG_PTR)SystemServiceAsm;
//
// overwrite the ZwXxx export to call our SystemServiceAsm,
// and then restore the original page protection
//
if (!NT_SUCCESS(SbieApi_ProtectVirtualMemory(NtCurrentProcess(), RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect))) {
SbieApi_Log(2303, L"win32k %d (1)", SyscallNum);
goto finish;
}
if (!NT_SUCCESS(SbieApi_WriteVirtualMemory(NtCurrentProcess(), RegionBase, ZwXxxPtr, RegionSize, &SizeRead))) {
SbieApi_Log(2303, L"win32k %d (2)", SyscallNum);
goto finish;
}
if (!NT_SUCCESS(SbieApi_FlushInstructionCache(NtCurrentProcess(), RegionBase, RegionSize))) {
SbieApi_Log(2303, L"win32k %d (3)", SyscallNum);
goto finish;
}
if (!NT_SUCCESS(SbieApi_ProtectVirtualMemory(NtCurrentProcess(), RegionBase, RegionSize, OldProtect, &OldProtect))) {
SbieApi_Log(2303, L"win32k %d (4)", SyscallNum);
goto finish;
}
}
//if (aCode[2] != 0 || aCode[3] != 0)
// break;
aCode += 4;
pos = 0; // reset
}
}
else { // x86 on x64
UCHAR ZwXxxPtr[16];
DWORD64 FuncTable = 0;
for (DWORD64 pos = 0; pos < SizeRead - 0x20; pos++) {
if (Win32_GetSysCallNumberWoW64(pos, dll_data) != 0) {
FuncTable = pos;
break;
}
}
if (FuncTable == 0) {
SbieApi_Log(2303, L"win32k, wow64win.dll sys call table not found");
goto finish;
}
for (DWORD64 pos = FuncTable; pos < SizeRead - 0x20; )
{
SyscallNum = Win32_GetSysCallNumberWoW64(pos, dll_data);
if (SyscallNum)
{
if (SbieDll_GetSysCallOffset(SyscallPtr, SyscallNum))
{
RegionBase = BaseAddress + pos;
RegionSize = 14;
//
// prepare call to call our SystemServiceAsm
//
ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber
ZwXxxPtr[1] = 0xC7;
ZwXxxPtr[2] = 0xC2;
*(ULONG*)&ZwXxxPtr[3] = SyscallNum;
if (!data->flags.long_diff) {
if (data->flags.is_win10) {
ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm
ZwXxxPtr[8] = 0xE9;
*(ULONG*)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 13));
}
else {
ZwXxxPtr[7] = 0xe9; // jmp SystemServiceAsm
*(ULONG*)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 12));
}
}
else {
ZwXxxPtr[7] = 0xB8; // mov eax, SystemServiceAsm
*(ULONG*)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm;
*(USHORT*)&ZwXxxPtr[12] = 0xE0FF; // jmp rax
}
//
// overwrite the ZwXxx export to call our SystemServiceAsm,
// and then restore the original page protection
//
if (!NT_SUCCESS(SbieApi_ProtectVirtualMemory(NtCurrentProcess(), RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect))) {
SbieApi_Log(2303, L"win32k %d (1)", SyscallNum);
goto finish;
}
if (!NT_SUCCESS(SbieApi_WriteVirtualMemory(NtCurrentProcess(), RegionBase, ZwXxxPtr, RegionSize, &SizeRead))) {
SbieApi_Log(2303, L"win32k %d (2)", SyscallNum);
goto finish;
}
if (!NT_SUCCESS(SbieApi_ProtectVirtualMemory(NtCurrentProcess(), RegionBase, RegionSize, OldProtect, &OldProtect))) {
SbieApi_Log(2303, L"win32k %d (3)", SyscallNum);
goto finish;
}
}
pos += 0x20;
}
else if (*((ULONG*)&dll_data[pos]) == 0xCCCCCCCC) { // int 3; int 3; int 3; int 3;
ok = TRUE;
break; // end of sys call function table
}
else
pos++;
}
}
finish:
if(syscall_data)
HeapFree(GetProcessHeap(), 0, syscall_data);
if(dll_data)
HeapFree(GetProcessHeap(), 0, dll_data);
return ok;
}
//
// Win32_HookWin32WoW64 needs to be able to read and write the 64-bit portion of the address space
// therefore we issue direct syscalls using 64 bit arguments to our driver's syscall interface
// The driver accepts function names and optionally returns the corresponding syscall index for later direct use
// This replaces the use of heaven's gate (wow64ext), as it is unavailable when running in emulation on arm64
//
//---------------------------------------------------------------------------
// SbieApi_ProtectVirtualMemory
//---------------------------------------------------------------------------
NTSTATUS SbieApi_ProtectVirtualMemory(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, ULONG flNewProtect, ULONG* lpflOldProtect)
{
ULONG64 BaseAddress = lpAddress;
ULONG64 NumberOfBytesToProtect = dwSize;
static SHORT syscall_index = 0xFFF;
ULONG64 stack[17];
stack[0] = hProcess;
stack[1] = &BaseAddress;
stack[2] = &NumberOfBytesToProtect;
stack[3] = flNewProtect;
stack[4] = lpflOldProtect;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
memset(parms, 0, sizeof(parms));
parms[0] = API_INVOKE_SYSCALL;
parms[1] = (ULONG64)(ULONG_PTR)syscall_index;
parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack
parms[3] = (ULONG64)(ULONG_PTR)"ProtectVirtualMemory";
parms[4] = (ULONG64)(ULONG_PTR)&syscall_index;
NTSTATUS status = SbieApi_Ioctl(parms);
return status;
}
//---------------------------------------------------------------------------
// SbieApi_ReadVirtualMemory
//---------------------------------------------------------------------------
NTSTATUS SbieApi_ReadVirtualMemory(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, ULONG64 *lpNumberOfBytesRead)
{
static SHORT syscall_index = 0xFFF;
ULONG64 stack[17];
stack[0] = hProcess;
stack[1] = lpBaseAddress;
stack[2] = lpBuffer;
stack[3] = nSize;
stack[4] = lpNumberOfBytesRead;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
memset(parms, 0, sizeof(parms));
parms[0] = API_INVOKE_SYSCALL;
parms[1] = (ULONG64)(ULONG_PTR)syscall_index;
parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack
parms[3] = (ULONG64)(ULONG_PTR)"ReadVirtualMemory";
parms[4] = (ULONG64)(ULONG_PTR)&syscall_index;
NTSTATUS status = SbieApi_Ioctl(parms);
if (status == STATUS_PARTIAL_COPY)
status = STATUS_SUCCESS;
return status;
}
//---------------------------------------------------------------------------
// SbieApi_WriteVirtualMemory
//---------------------------------------------------------------------------
NTSTATUS SbieApi_WriteVirtualMemory(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, ULONG64 *lpNumberOfBytesWritten)
{
static SHORT syscall_index = 0xFFF;
ULONG64 stack[17];
stack[0] = hProcess;
stack[1] = lpBaseAddress;
stack[2] = lpBuffer;
stack[3] = nSize;
stack[4] = lpNumberOfBytesWritten;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
memset(parms, 0, sizeof(parms));
parms[0] = API_INVOKE_SYSCALL;
parms[1] = (ULONG64)(ULONG_PTR)syscall_index;
parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack
parms[3] = (ULONG64)(ULONG_PTR)"WriteVirtualMemory";
parms[4] = (ULONG64)(ULONG_PTR)&syscall_index;
NTSTATUS status = SbieApi_Ioctl(parms);
return status;
}
//---------------------------------------------------------------------------
// SbieApi_FlushInstructionCache
//---------------------------------------------------------------------------
NTSTATUS SbieApi_FlushInstructionCache(HANDLE hProcess, DWORD64 lpBaseAddress, SIZE_T nSize)
{
static SHORT syscall_index = 0xFFF;
ULONG64 stack[17];
stack[0] = hProcess;
stack[1] = lpBaseAddress;
stack[2] = nSize;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
memset(parms, 0, sizeof(parms));
parms[0] = API_INVOKE_SYSCALL;
parms[1] = (ULONG64)(ULONG_PTR)syscall_index;
parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack
parms[3] = (ULONG64)(ULONG_PTR)"FlushInstructionCache";
parms[4] = (ULONG64)(ULONG_PTR)&syscall_index;
NTSTATUS status = SbieApi_Ioctl(parms);
return status;
}
//---------------------------------------------------------------------------
// SbieApi_QueryVirtualMemory
//---------------------------------------------------------------------------
NTSTATUS SbieApi_QueryVirtualMemory(HANDLE hProcess, DWORD64 BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength)
{
DWORD64 ReturnLength64 = 0;
static SHORT syscall_index = 0xFFF;
ULONG64 stack[17];
stack[0] = hProcess;
stack[1] = BaseAddress;
stack[2] = MemoryInformationClass;
stack[3] = MemoryInformation;
stack[4] = MemoryInformationLength;
stack[5] = &ReturnLength64;
__declspec(align(8)) ULONG64 parms[API_NUM_ARGS];
memset(parms, 0, sizeof(parms));
parms[0] = API_INVOKE_SYSCALL;
parms[1] = (ULONG64)(ULONG_PTR)syscall_index;
parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack
parms[3] = (ULONG64)(ULONG_PTR)"QueryVirtualMemory";
parms[4] = (ULONG64)(ULONG_PTR)&syscall_index;
NTSTATUS status = SbieApi_Ioctl(parms);
if(ReturnLength) *ReturnLength = (SIZE_T)ReturnLength64;
return status;
}
#endif