From db2b095d6cbfc5b755c370c81de308f4cf2ec6da Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Wed, 15 Dec 2021 23:31:28 +0100 Subject: [PATCH] 1.0.4 --- CHANGELOG.md | 2 +- Sandboxie/core/dll/SboxDll.vcxproj | 1 + Sandboxie/core/dll/SboxDll.vcxproj.filters | 3 + Sandboxie/core/dll/Win32.c | 297 +++++++++++---------- Sandboxie/core/dll/dllhook.c | 57 ++-- Sandboxie/core/dll/lowlevel_inject.c | 26 +- Sandboxie/core/low/init.c | 139 +++++----- SandboxiePlus/SandMan/SandMan.rc | 2 +- SandboxiePlus/version.h | 11 +- 9 files changed, 281 insertions(+), 257 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4777ee98..b6c764e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed - mechanism to hook Win32 system calls now also works for 32 bit applications running under WoW64 - +- cleaned up low level hooking code a bit diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj index 5fb49941..a42e660e 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj +++ b/Sandboxie/core/dll/SboxDll.vcxproj @@ -406,6 +406,7 @@ + diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters index 3684b96f..1dd59a1f 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj.filters +++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters @@ -295,6 +295,9 @@ common\wow64ext + + common + diff --git a/Sandboxie/core/dll/Win32.c b/Sandboxie/core/dll/Win32.c index 3b5c2d9f..69fc6072 100644 --- a/Sandboxie/core/dll/Win32.c +++ b/Sandboxie/core/dll/Win32.c @@ -25,16 +25,18 @@ #include "common\pattern.h" -#define HOOK_WIN32K - -#ifdef HOOK_WIN32K - #include "core/drv/api_defs.h" #include "core/low/lowdata.h" SBIELOW_DATA* SbieApi_data = NULL; #define SBIELOW_CALL(x) ((P_##x)&data->x##_code) + +//--------------------------------------------------------------------------- +// SbieDll_HookWin32SysCalls +//--------------------------------------------------------------------------- + + _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) { UCHAR *SystemServiceAsm, *ZwXxxPtr; @@ -102,7 +104,6 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) SyscallNum = SyscallPtr[0]; #ifdef _WIN64 - SyscallNum &= 0xFFFF; // clear the not needed param count ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber ZwXxxPtr[1] = 0xC7; @@ -112,7 +113,7 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) if (data->flags.is_win10) { ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm - ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm + ZwXxxPtr[8] = 0xE9; *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13)); } else { @@ -129,7 +130,7 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) #else ! _WIN64 - ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber + 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] = @@ -148,72 +149,12 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) return TRUE; } -#ifndef _WIN64 -BOOLEAN SbieDll_HookWoW64SysCalls(); - -#endif - -#endif - -_FX BOOLEAN Win32_Init(HMODULE hmodule) -{ -#ifdef HOOK_WIN32K - // In Windows 10 all Win32k.sys calls are located in win32u.dll - if (Dll_OsBuild < 10041 || !SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", FALSE)) - return TRUE; // just return on older builds - - // NoSysCallHooks BEGIN - if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) - return TRUE; - // NoSysCallHooks END - - // disable Electron Workaround when we are ready to hook the required win32k syscalls - extern BOOL Dll_ElectronWorkaround; - Dll_ElectronWorkaround = FALSE; - - // - // chrome needs for a working GPU acceleration the GdiDdDDI* win32k syscalls to have the right user token - // - - WCHAR* cmdline = GetCommandLine(); - - if ((wcsstr(cmdline, L"--type=gpu-process") != NULL && wcsstr(cmdline, L"--gpu-preferences=") != NULL) - || SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"AlwaysUseWin32kHooks", FALSE)) { +//--------------------------------------------------------------------------- +// Win32_WoW64_GetSysCallNumber +//--------------------------------------------------------------------------- #ifndef _WIN64 - if (Dll_IsWow64) - SbieDll_HookWoW64SysCalls(); - else -#endif - SbieDll_HookWin32SysCalls(hmodule); - } - -#endif - - return TRUE; -} - -#ifdef HOOK_WIN32K - -#ifndef _WIN64 - -//#include "../../common/wow64ext/wow64ext.h" -DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...); -DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName); -DWORD64 __cdecl getNTDLL64(); -DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, const char* funcName); -SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength); -DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); -BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType); -BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect); -BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); -BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); -//BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext); -//BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext); -VOID __cdecl SetLastErrorFromX64Call(DWORD64 status); - - ULONG Win32_WoW64_GetSysCallNumber(DWORD64 pos, UCHAR* dll_data) { // 4C 8B D1 - r10,rcx @@ -247,13 +188,52 @@ ULONG Win32_WoW64_GetSysCallNumber(DWORD64 pos, UCHAR* dll_data) if (!(dll_data[pos + 23] == 0xc3)) return 0; - // 0F 1F 84 00 00 00 00 00 // return syscall_index; } -_FX BOOLEAN SbieDll_HookWoW64SysCalls() + +//--------------------------------------------------------------------------- +// SbieDll_HasSysCallHook +//--------------------------------------------------------------------------- + + +_FX BOOLEAN SbieDll_HasSysCallHook(UCHAR* syscall_data, ULONG syscall_index) +{ + ULONG *SyscallPtr; + ULONG SyscallNum; + + SyscallPtr = (ULONG *)(syscall_data + sizeof(ULONG)); // size of buffer + + while (SyscallPtr[0] || SyscallPtr[1]) { + + SyscallNum = SyscallPtr[0]; + + SyscallNum &= 0xFFFF; // clear the not needed param count + + if (SyscallNum == syscall_index) + return TRUE; + + SyscallPtr += 2; + } + + return FALSE; +} + + +//--------------------------------------------------------------------------- +// SbieDll_HookWin32WoW64 +//--------------------------------------------------------------------------- + +//#include "../../common/wow64ext/wow64ext.h" +DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...); +DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName); +BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect); +BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); +BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); + +_FX BOOLEAN SbieDll_HookWin32WoW64() { BOOLEAN ok = FALSE; UCHAR* dll_data = NULL; @@ -261,20 +241,28 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls() DWORD64 BaseAddress = GetModuleHandle64(L"wow64win.dll"); SIZE_T SizeOfImage = 0x00100000; // 1 MB should be more than enough - if (!BaseAddress) + if (!BaseAddress) { + SbieApi_Log(2303, L"win32k, wow64win.dll base not found"); return FALSE; + } HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); - if (hProcess == INVALID_HANDLE_VALUE) + if (hProcess == INVALID_HANDLE_VALUE) { + SbieApi_Log(2303, L"win32k, can't open process"); return FALSE; + } dll_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)SizeOfImage); - if (!dll_data) + if (!dll_data) { + SbieApi_Log(2303, L"win32k, alloc failed (1)"); goto finish; + } SIZE_T SizeRead; - if (!ReadProcessMemory64(hProcess, (PVOID64)BaseAddress, dll_data, SizeOfImage, &SizeRead)) + if (!ReadProcessMemory64(hProcess, (PVOID64)BaseAddress, dll_data, SizeOfImage, &SizeRead)) { + SbieApi_Log(2303, L"win32k, wow64win.dll read failed"); goto finish; + } DWORD64 FuncTable = 0; @@ -284,13 +272,14 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls() break; } } - - if (FuncTable == 0) + + if (FuncTable == 0) { + SbieApi_Log(2303, L"win32k, wow64win.dll sys call table not found"); goto finish; + } DWORD64 SystemServiceAsm; UCHAR ZwXxxPtr[16]; - ULONG *SyscallPtr; ULONG SyscallNum; DWORD64 RegionBase; SIZE_T RegionSize; @@ -300,79 +289,73 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls() SystemServiceAsm = data->pSystemService; syscall_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, 16384); // enough room for over 2000 syscalls - if (!syscall_data) - goto finish; + 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))) { - HeapFree(GetProcessHeap(), 0, syscall_data); + SbieApi_Log(2303, L"win32k, syscall query failed"); goto finish; } for (DWORD64 pos = FuncTable; pos < SizeRead - 0x20; ) { - ULONG syscall_index = Win32_WoW64_GetSysCallNumber(pos, dll_data); - if (syscall_index) + SyscallNum = Win32_WoW64_GetSysCallNumber(pos, dll_data); + if (SyscallNum) { - SyscallPtr = (ULONG *)(syscall_data + sizeof(ULONG)); // size of buffer + if(SbieDll_HasSysCallHook(syscall_data, SyscallNum)) + { + RegionBase = BaseAddress + pos; + RegionSize = 14; + + // + // prepare call to call our SystemServiceAsm + // - while (SyscallPtr[0] || SyscallPtr[1]) { - - SyscallNum = SyscallPtr[0]; - - SyscallNum &= 0xFFFF; // clear the not needed param count - - if (SyscallNum == syscall_index){ - - RegionBase = BaseAddress + pos; - // _WIN64 - RegionSize = 14; - // ! _WIN64 + ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber + ZwXxxPtr[1] = 0xC7; + ZwXxxPtr[2] = 0xC2; + *(ULONG *)&ZwXxxPtr[3] = SyscallNum; + if (!data->flags.long_diff) { - if (!ReadProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead)) - goto finish; - - // - // overwrite the ZwXxx export to call our SystemServiceAsm, - // and then restore the original page protection - // - - // _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; // jmp SystemServiceAsm - *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 13)); - } - else { - ZwXxxPtr[7] = 0xe9; // jmp SystemServiceAsm - *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 12)); - } + 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] = 0xB8; // mov eax, SystemServiceAsm - *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm; - *(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax + ZwXxxPtr[7] = 0xe9; // jmp SystemServiceAsm + *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 12)); } - // ! _WIN64 + } + else { - - if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect)) - goto finish; - - if (!WriteProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead)) - goto finish; - - if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, OldProtect, &OldProtect)) - goto finish; + ZwXxxPtr[7] = 0xB8; // mov eax, SystemServiceAsm + *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm; + *(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax } - SyscallPtr += 2; + + // + // overwrite the ZwXxx export to call our SystemServiceAsm, + // and then restore the original page protection + // + + if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect)) { + SbieApi_Log(2303, L"win32k %d (1)", SyscallNum); + goto finish; + } + + if (!WriteProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead)) { + SbieApi_Log(2303, L"win32k %d (2)", SyscallNum); + goto finish; + } + + if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, OldProtect, &OldProtect)) { + SbieApi_Log(2303, L"win32k %d (3)", SyscallNum); + goto finish; + } } pos += 0x20; @@ -385,7 +368,6 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls() pos++; } - finish: if(syscall_data) @@ -398,7 +380,44 @@ finish: return ok; } - #endif -#endif \ No newline at end of file +//--------------------------------------------------------------------------- +// Win32_Init +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Win32_Init(HMODULE hmodule) +{ + // In Windows 10 all Win32k.sys calls are located in win32u.dll + if (Dll_OsBuild < 10041 || !SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", FALSE)) + return TRUE; // just return on older builds + + // NoSysCallHooks BEGIN + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) + return TRUE; + // NoSysCallHooks END + + // disable Electron Workaround when we are ready to hook the required win32k syscalls + extern BOOL Dll_ElectronWorkaround; + Dll_ElectronWorkaround = FALSE; + + // + // chrome needs for a working GPU acceleration the GdiDdDDI* win32k syscalls to have the right user token + // + + WCHAR* cmdline = GetCommandLine(); + + if ((wcsstr(cmdline, L"--type=gpu-process") != NULL && wcsstr(cmdline, L"--gpu-preferences=") != NULL) + || SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"AlwaysUseWin32kHooks", FALSE)) { + +#ifndef _WIN64 + if (Dll_IsWow64) + SbieDll_HookWin32WoW64(); // WoW64 hooks + else +#endif + SbieDll_HookWin32SysCalls(hmodule); // Native x86/x64 hooks + } + + return TRUE; +} \ No newline at end of file diff --git a/Sandboxie/core/dll/dllhook.c b/Sandboxie/core/dll/dllhook.c index 141504c3..2d0d1ca4 100644 --- a/Sandboxie/core/dll/dllhook.c +++ b/Sandboxie/core/dll/dllhook.c @@ -130,7 +130,7 @@ _FX void *SbieDll_Hook( // (this helps to co-exist with Cisco Security Agent) // - if (*(UCHAR *)SourceFunc == 0xEB) { + if (*(UCHAR *)SourceFunc == 0xEB) { // jmp xx; signed char offset = *((signed char *)SourceFunc + 1); SourceFunc = (UCHAR *)SourceFunc + offset + 2; } @@ -142,7 +142,7 @@ _FX void *SbieDll_Hook( // otherwise (for 32-bit code) just replace the jump target // - while (*(UCHAR *)SourceFunc == 0xE9) { + while (*(UCHAR *)SourceFunc == 0xE9) { // jmp xx xx xx xx; diff = *(LONG *)((ULONG_PTR)SourceFunc + 1); target = (ULONG_PTR)SourceFunc + diff + 5; @@ -192,15 +192,15 @@ skip_e9_rewrite: ; // can process it // - if (*(USHORT *)SourceFunc == 0xE990) { + if (*(USHORT *)SourceFunc == 0xE990) { // nop; jmp xx xx xx xx; diff = *(LONG *)((ULONG_PTR)SourceFunc + 2); target = (ULONG_PTR)SourceFunc + diff + 6; - if (*(USHORT *)target == 0x25FF) + if (*(USHORT *)target == 0x25FF) // jmp QWORD PTR [rip+xx xx xx xx]; SourceFunc = (void *)target; } // - // DX: this simplification fails for delay loaded libraries, see coments about SetSecurityInfo, + // DX: this simplification fails for delay loaded libraries, see comments about SetSecurityInfo, // resulting in an endless loop, so just dont do that // @@ -211,13 +211,13 @@ skip_e9_rewrite: ; // 12 bytes. // - if (*(UCHAR *)SourceFunc == 0x48 && - *(USHORT *)((UCHAR *)SourceFunc + 1) == 0x25FF) { - // 4825FF is same as 25FF + if (*(UCHAR *)SourceFunc == 0x48 && // rex.W + *(USHORT *)((UCHAR *)SourceFunc + 1) == 0x25FF) { // jmp QWORD PTR [rip+xx xx xx xx]; + // 48 FF 25 is same as FF 25 SourceFunc = (UCHAR *)SourceFunc + 1; } - if (*(USHORT *)SourceFunc == 0x25FF) { + if (*(USHORT *)SourceFunc == 0x25FF) { // jmp QWORD PTR [rip+xx xx xx xx]; void *orig_addr; /* @@ -254,7 +254,7 @@ skip_e9_rewrite: ; #ifdef _WIN64 - if (*(USHORT *)SourceFunc == 0x15FF) { + if (*(USHORT *)SourceFunc == 0x15FF) { // call QWORD PTR [rip+xx xx xx xx]; // // the call instruction pushes a qword into the stack, we need @@ -312,8 +312,8 @@ skip_e9_rewrite: ; return NULL; } - ULONG ByteCount = *(ULONG*)(tramp + 80); - ULONG UsedCount = 0; + //ULONG ByteCount = *(ULONG*)(tramp + 80); + //ULONG UsedCount = 0; // // create the detour @@ -351,22 +351,20 @@ skip_e9_rewrite: ; OutputDebugStringA(buffer); */ if (Dll_Windows >= 10) { - func[0] = 0x48; // 32bit relative JMP DetourFunc - func[1] = 0xE9; // 32bit relative JMP DetourFunc + func[0] = 0x48; // 32bit relative rex.W JMP DetourFunc + func[1] = 0xE9; *(ULONG *)(&func[2]) = (ULONG)diff; - UsedCount = 1 + 1 + 4; + //UsedCount = 1 + 1 + 4; } else { func[0] = 0xE9; // 32bit relative JMP DetourFunc *(ULONG *)(&func[1]) = (ULONG)diff; - UsedCount = 1 + 4; + //UsedCount = 1 + 4; } } else { - - BOOLEAN hookset = FALSE; BOOLEAN defaultRange = FALSE; int i; @@ -377,12 +375,12 @@ skip_e9_rewrite: ; //default step size for (i = 0; i < NUM_VTABLES && !hookset; i++, ptrVTable++) { - if (!ptrVTable->offset) { + if (!ptrVTable->offset) { // if the vtable is not yet initialized initialize it ULONG_PTR tempAddr; ULONG_PTR step = 0x20000;// + VTABLE_SIZE; ULONG_PTR max_attempts = 0x4000000 / step; - // optimization for windows 7 and low memory DLL's + // optimization for windows 7 and low memory DLL's if ((ULONG_PTR)func < 0x80000000 && ((ULONG_PTR)func > 0x4000000)) { step = 0x200000; } @@ -414,7 +412,7 @@ skip_e9_rewrite: ; ptrVTable->index = 0; ptrVTable->maxEntries = VTABLE_SIZE / sizeof(void *); } - if (ptrVTable->offset) { + if (ptrVTable->offset) { // check if we have an nitialized vtable target = (ULONG_PTR)&func[6]; diff = (ULONG_PTR) &((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index]; diff = diff - target; @@ -424,14 +422,14 @@ skip_e9_rewrite: ; // is DetourFunc in 32bit jump range if (delta < 0x80000000 && ptrVTable->index <= ptrVTable->maxEntries) { ((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index] = (ULONG_PTR)DetourFunc; - *(USHORT *)&func[0] = 0x25ff; + *(USHORT *)&func[0] = 0x25ff; // jmp QWORD PTR [rip+diff]; *(ULONG *)&func[2] = (ULONG)diff; - UsedCount = 2 + 4; + //UsedCount = 2 + 4; ptrVTable->index++; hookset = TRUE; } } - else { + else { // fail and disable vtable if it could not be initialized bVTableEable = FALSE; SbieApi_Log(2303, _fmt1, SourceFuncName, 888); LeaveCriticalSection(&VT_CriticalSection); @@ -529,9 +527,10 @@ ULONGLONG * SbieDll_findChromeTarget(unsigned char* addr) _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc) { -#ifndef _WIN64 - + if (!SourceFunc) + return NULL; UCHAR *func = (UCHAR *)SourceFunc; +#ifndef _WIN64 if (func[0] == 0xB8 && // mov eax,? func[5] == 0xBA && // mov edx,? *(USHORT *)&func[10] == 0xE2FF) // jmp edx @@ -551,10 +550,7 @@ _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc) } } #else if - UCHAR *func = (UCHAR *)SourceFunc; ULONGLONG *chrome64Target = NULL; - if (!SourceFunc) - return NULL; if (func[0] == 0x50 && //push rax func[1] == 0x48 && //mov rax,? @@ -576,7 +572,8 @@ _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc) } /*sboxie 64bit jtable hook signature */ /* // use this to hook jtable location (useful for debugging) - else if(func[0] == 0x51 && func[1] == 0x48 && func[2] == 0xb8 ) { + //else if(func[0] == 0x51 && func[1] == 0x48 && func[2] == 0xb8 ) { + else if(func[0] == 0x90 && func[1] == 0x48 && func[2] == 0xb8 ) { long long addr; addr = (ULONG_PTR) *(ULONGLONG **)&func[3] ; SourceFunc = (void *) addr; diff --git a/Sandboxie/core/dll/lowlevel_inject.c b/Sandboxie/core/dll/lowlevel_inject.c index 7f680f4e..44fa97e6 100644 --- a/Sandboxie/core/dll/lowlevel_inject.c +++ b/Sandboxie/core/dll/lowlevel_inject.c @@ -55,7 +55,7 @@ typedef struct _MY_TARGETS { SBIEDLL_EXPORT HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess); SBIEDLL_EXPORT void *SbieDll_InjectLow_CopyCode( - HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len); + HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len); SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_BuildTramp( BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr); SBIEDLL_EXPORT void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess); @@ -519,7 +519,16 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h lowdata.flags.is_win10 = 1; } - void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowdata.flags.is_wow64 == 1, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp)); + SIZE_T lowLevel_size; +#ifdef _WIN64 + BOOLEAN use_jump_Table = FALSE; + if(use_jump_Table) + lowLevel_size = m_sbielow_len + sizeof(SBIELOW_J_TABLE) + 0x400; + else +#endif + lowLevel_size = m_sbielow_len; + + void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowLevel_size, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp)); if (!remote_addr) { errlvl = 0x33; goto finish; @@ -570,7 +579,8 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h // #ifdef _WIN64 - lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *)((ULONG_PTR)remote_addr + m_sbielow_len + 0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len; + if(use_jump_Table) + lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *)((ULONG_PTR)remote_addr + m_sbielow_len + 0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len; #endif // @@ -693,16 +703,10 @@ _FX HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess) //--------------------------------------------------------------------------- -_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len) +_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len) { SIZE_T region_size; - SIZE_T lowLevel_size; void *remote_addr = NULL; -#ifdef _WIN64 - lowLevel_size = m_sbielow_len + sizeof(SBIELOW_J_TABLE) + 0x400; -#else - lowLevel_size = m_sbielow_len; -#endif region_size = lowLevel_size; //for (int i = 8; !remote_addr && i > 2; i--) { @@ -1097,7 +1101,7 @@ _FX BOOLEAN SbieDll_InjectLow_WriteJump(HANDLE hProcess, void *remote_addr, BOOL // UCHAR jump_code[16]; void * detour = (void *)remote_addr; - UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk);; + UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk); SIZE_T len1; BOOL myVM; ULONG myProtect; diff --git a/Sandboxie/core/low/init.c b/Sandboxie/core/low/init.c index ce2c6557..bc4026ba 100644 --- a/Sandboxie/core/low/init.c +++ b/Sandboxie/core/low/init.c @@ -208,7 +208,7 @@ _FX void WaitForDebugger(SBIELOW_DATA *data) ULONGLONG * findChromeTarget(unsigned char* addr) { int i = 0; - ULONGLONG target = 0; + ULONGLONG target; ULONG_PTR * ChromeTarget = NULL; if (!addr) return NULL; //Look for mov rcx,[target 4 byte offset] or in some cases mov rax,[target 4 byte offset] @@ -234,6 +234,55 @@ ULONGLONG * findChromeTarget(unsigned char* addr) } #endif +void *Hook_CheckChromeHook(void *SourceFunc) +{ + if (!SourceFunc) + return NULL; + UCHAR *ZwXxxPtr = (UCHAR *)SourceFunc; +#ifndef _WIN64 //if not _WIN64 + if (ZwXxxPtr[0] == 0xB8 && // mov eax,? + ZwXxxPtr[5] == 0xBA && // mov edx,? + *(USHORT *)&ZwXxxPtr[10] == 0xE2FF) // jmp edx + { + ULONG i = 0; + + ULONG *longs = *(ULONG **)&ZwXxxPtr[6]; + for (i = 0; i < 20; i++, longs++) + { + if (longs[0] == 0x5208EC83 && longs[1] == 0x0C24548B && + longs[2] == 0x08245489 && longs[3] == 0x0C2444C7 && + longs[5] == 0x042444C7) + { + ZwXxxPtr = (UCHAR *)longs[4]; + break; + } + } + } +#else // _WIN64 + ULONGLONG *chrome64Target = NULL; + + if (ZwXxxPtr[0] == 0x50 && //push rax + ZwXxxPtr[1] == 0x48 && //mov rax,? + ZwXxxPtr[2] == 0xb8) { + ULONGLONG* longlongs = *(ULONGLONG**)&ZwXxxPtr[3]; + chrome64Target = findChromeTarget((unsigned char*)longlongs); + } + // Chrome 49+ 64bit hook + // mov rax, + // jmp rax + else if (ZwXxxPtr[0] == 0x48 && //mov rax, + ZwXxxPtr[1] == 0xb8 && + *(USHORT*)&ZwXxxPtr[10] == 0xe0ff)/* jmp rax */ { + ULONGLONG* longlongs = *(ULONGLONG**)&ZwXxxPtr[2]; + chrome64Target = findChromeTarget((unsigned char*)longlongs); + } + if (chrome64Target != NULL) { + ZwXxxPtr = (UCHAR *)chrome64Target; + } +#endif + return ZwXxxPtr; +} + _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) { UCHAR *SystemServiceAsm; @@ -278,9 +327,6 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) void *RegionBase; SIZE_T RegionSize; ULONG OldProtect; -#ifdef _WIN64 - ULONGLONG *chrome64Target = NULL; -#endif SystemServiceAsm = (UCHAR *)SystemService; @@ -310,54 +356,16 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) // saved by chrome, rather than the chrome hook itself (32-bit only) // -#ifndef _WIN64 //if not _WIN64 - - if (ZwXxxPtr[0] == 0xB8 && // mov eax,? - ZwXxxPtr[5] == 0xBA && // mov edx,? - *(USHORT *)&ZwXxxPtr[10] == 0xE2FF) // jmp edx - { - ULONG i = 0; - - ULONG *longs = *(ULONG **)&ZwXxxPtr[6]; - for (i = 0; i < 20; i++, longs++) - { - if (longs[0] == 0x5208EC83 && longs[1] == 0x0C24548B && - longs[2] == 0x08245489 && longs[3] == 0x0C2444C7 && - longs[5] == 0x042444C7) - { - ZwXxxPtr = (UCHAR *)longs[4]; - break; - } - } - } -#else // _WIN64 - if (ZwXxxPtr[0] == 0x50 && //push rax - ZwXxxPtr[1] == 0x48 && //mov rax,? - ZwXxxPtr[2] == 0xb8) { - ULONGLONG *longlongs = *(ULONGLONG **)&ZwXxxPtr[3]; - chrome64Target = findChromeTarget((unsigned char *)longlongs); - } - // Chrome 49+ 64bit hook - // mov rax, - // jmp rax - else if (ZwXxxPtr[0] == 0x48 && //mov rax, - ZwXxxPtr[1] == 0xb8 && - *(USHORT *)&ZwXxxPtr[10] == 0xe0ff)/* jmp rax */ { - ULONGLONG *longlongs = *(ULONGLONG **)&ZwXxxPtr[2]; - chrome64Target = findChromeTarget((unsigned char *)longlongs); - } -#endif + ZwXxxPtr = Hook_CheckChromeHook(ZwXxxPtr); // // make the syscall address writable // + RegionBase = ZwXxxPtr; #ifdef _WIN64 - RegionSize = 14; - if (!chrome64Target) { - chrome64Target = (ULONG_PTR*)ZwXxxPtr; - } + RegionSize = data->Sbie64bitJumpTable ? 13 : 14; // 16; #else ! _WIN64 RegionSize = 10; #endif _WIN64 @@ -371,21 +379,18 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) // and then restore the original page protection // + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + SyscallNum = SyscallPtr[0]; #ifdef _WIN64 - SyscallNum &= 0xFFFF; // clear the not needed param count - if (chrome64Target && data->Sbie64bitJumpTable) { - RegionSize = 16; - ZwXxxPtr = (UCHAR *)chrome64Target; - RegionBase = ZwXxxPtr; + if (data->Sbie64bitJumpTable) { + // bytes overwriten /*16*/ 13; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); - - unsigned char * jTableTarget = (unsigned char *)&data->Sbie64bitJumpTable->entry[SyscallNum & 0x3ff]; + unsigned char * jTableTarget = (unsigned char *)&data->Sbie64bitJumpTable->entry[SyscallNum & 0x3ff]; // jump table is sized for up to 1024 entries // write new patch for jump table // The jTable is now injected in the same memory module with lowlevel; no need for a 64 bit long jump // mov r10, <4 byte SyscallNum> @@ -427,18 +432,11 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) // jmp rax ZwXxxPtr[11] = 0xFF; ZwXxxPtr[12] = 0xE0; - - chrome64Target = NULL; } - else - { - RegionBase = ZwXxxPtr; + else { + // bytes overwriten 14; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); - - ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber + ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber ZwXxxPtr[1] = 0xC7; ZwXxxPtr[2] = 0xC2; *(ULONG *)&ZwXxxPtr[3] = SyscallNum; @@ -446,7 +444,7 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) if (data->flags.is_win10) { ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm - ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm + ZwXxxPtr[8] = 0xE9; *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13)); } else { @@ -456,18 +454,15 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService) } else { - ZwXxxPtr[7] = 0xB8; // mov eax, SystemServiceAsm + ZwXxxPtr[7] = 0xB8; // mov eax, SystemServiceAsm *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm; *(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax } } #else ! _WIN64 + // bytes overwriten 10; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); - - ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber + 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] = diff --git a/SandboxiePlus/SandMan/SandMan.rc b/SandboxiePlus/SandMan/SandMan.rc index 24f47c5f..2b70207a 100644 --- a/SandboxiePlus/SandMan/SandMan.rc +++ b/SandboxiePlus/SandMan/SandMan.rc @@ -88,7 +88,7 @@ BEGIN BLOCK "0c0704b0" BEGIN VALUE "CompanyName", MY_COMPANY_NAME_STRING - VALUE "FileDescription", "SandBox Manager" + VALUE "FileDescription", "SandBoxie Manager" VALUE "FileVersion", VERSION_STR VALUE "InternalName", "SandMan.exe" VALUE "LegalCopyright", MY_COPYRIGHT_STRING diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h index 71743aab..7db323bb 100644 --- a/SandboxiePlus/version.h +++ b/SandboxiePlus/version.h @@ -10,10 +10,15 @@ #define STR(X) STR2(X) #endif -#define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV,VERSION_UPD -#define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV.VERSION_UPD) +#if VERSION_UPD > 0 + #define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV,VERSION_UPD + #define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV.VERSION_UPD) +#else + #define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV + #define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV) +#endif #define MY_PRODUCT_NAME_STRING "Sandboxie-Plus" #define MY_COMPANY_NAME_STRING "sandboxie-plus.com" -#define MY_COPYRIGHT_STRING "Copyright (C) 2020-2021 by David Xanatos (xanasoft.com)" +#define MY_COPYRIGHT_STRING "Copyright (C) 2020-2022 by David Xanatos (xanasoft.com)"