From da1c97b794545548ceb842a8f5b1daf43eb73caf Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Fri, 31 Dec 2021 22:41:13 +0100 Subject: [PATCH] 1.0.7 --- CHANGELOG.md | 14 ++ Sandboxie/common/my_version.h | 6 +- Sandboxie/core/drv/syscall.c | 241 ++------------------------------ Sandboxie/core/drv/token.c | 8 +- Sandboxie/core/drv/util_asm.asm | 130 +++++++++++++++-- SandboxiePlus/version.h | 2 +- 6 files changed, 152 insertions(+), 249 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ad5c9c9..b42928ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ This project adheres to [Semantic Versioning](http://semver.org/). + +## [1.0.7 / 5.55.7] - 2022-01-?? + + +### Changed +- reworked syscall invocation code in the driver + +### Fixed +- Win32k hooking is now compatible with HVCI [#1483](https://github.com/sandboxie-plus/Sandboxie/issues/1483) + + + + + ## [1.0.6 / 5.55.6] - 2021-12-31 ### Added diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h index 1f6089fa..2ca63657 100644 --- a/Sandboxie/common/my_version.h +++ b/Sandboxie/common/my_version.h @@ -21,8 +21,8 @@ #ifndef _MY_VERSION_H #define _MY_VERSION_H -#define MY_VERSION_BINARY 5,55,6 -#define MY_VERSION_STRING "5.55.6" +#define MY_VERSION_BINARY 5,55,7 +#define MY_VERSION_STRING "5.55.7" #define MY_VERSION_COMPAT "5.55.0" // this refers to the driver ABI compatibility // These #defines are used by either Resource Compiler, or by NSIC installer @@ -32,7 +32,7 @@ #define MY_PRODUCT_NAME_STRING "Sandboxie" #define MY_COMPANY_NAME_STRING "sandboxie-plus.com" -#define MY_COPYRIGHT_STRING "Copyright © 2020-2021 by David Xanatos (xanasoft.com)" +#define MY_COPYRIGHT_STRING "Copyright © 2020-2022 by David Xanatos (xanasoft.com)" #define MY_COPYRIGHT_STRING_OLD "Copyright © 2004-2020 by Sandboxie Holdings, LLC" #define SANDBOXIE L"Sandboxie" diff --git a/Sandboxie/core/drv/syscall.c b/Sandboxie/core/drv/syscall.c index c933978a..2f190fe6 100644 --- a/Sandboxie/core/drv/syscall.c +++ b/Sandboxie/core/drv/syscall.c @@ -108,86 +108,6 @@ static BOOLEAN Syscall_GetKernelAddr( #endif -//--------------------------------------------------------------------------- - - -typedef NTSTATUS (*P_SystemService00)(void); -typedef NTSTATUS (*P_SystemService01)( - ULONG_PTR arg01); -typedef NTSTATUS (*P_SystemService02)( - ULONG_PTR arg01, ULONG_PTR arg02); -typedef NTSTATUS (*P_SystemService03)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03); -typedef NTSTATUS (*P_SystemService04)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04); -typedef NTSTATUS (*P_SystemService05)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05); -typedef NTSTATUS (*P_SystemService06)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06); -typedef NTSTATUS (*P_SystemService07)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07); -typedef NTSTATUS (*P_SystemService08)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08); -typedef NTSTATUS (*P_SystemService09)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09); -typedef NTSTATUS (*P_SystemService10)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10); -typedef NTSTATUS (*P_SystemService11)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11); -typedef NTSTATUS (*P_SystemService12)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12); -typedef NTSTATUS (*P_SystemService13)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13); -typedef NTSTATUS (*P_SystemService14)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14); -typedef NTSTATUS (*P_SystemService15)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15); -typedef NTSTATUS (*P_SystemService16)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16); -typedef NTSTATUS (*P_SystemService17)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, - ULONG_PTR arg17); -typedef NTSTATUS (*P_SystemService18)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, - ULONG_PTR arg17, ULONG_PTR arg18); -typedef NTSTATUS (*P_SystemService19)( - ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, - ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, - ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, - ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, - ULONG_PTR arg17, ULONG_PTR arg18, ULONG_PTR arg19); -// (count & 0x0F) + 4 -> 19 is absolute maximum - //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- @@ -221,24 +141,7 @@ _FX BOOLEAN Syscall_Init(void) return FALSE; #ifdef HOOK_WIN32K - - // - // Win32k Hooking requirers 10 or later as only thre Win32u.dll is available - // - // Note: Win32k Hooking is not compatible with HVCI causing a BSOD - // KERNEL_SECURITY_CHECK_FAILURE (139) - // A kernel component has corrupted a critical data structure. - // Arguments: - // Arg1: 0000000000000000, A stack-based buffer has been overrun. - // Arg2: 0000000000000000, Address of the trap frame for the exception that caused the bugcheck - // Arg3: 0000000000000000, Address of the exception record for the exception that caused the bugcheck - // Arg4: ffffxxxxxxxxxxxx, Reserved - // - // Note: this feature applied to GdiDdDDI* solves HW Acceleration issues with chromium, hence we enable it if possible - // - - if (Driver_OsBuild >= 10041 && Conf_Get_Boolean(NULL, L"EnableWin32kHooks", 0, TRUE) - && Driver_GetRegDword(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceGuard\\Scenarios\\HypervisorEnforcedCodeIntegrity", L"Enabled") == 0) { + if (Driver_OsBuild >= 10041 && Conf_Get_Boolean(NULL, L"EnableWin32kHooks", 0, TRUE)) { if (!Syscall_Init_List32()) return FALSE; @@ -619,147 +522,23 @@ _FX void Syscall_ErrorForAsciiName(const UCHAR *name_a) //--------------------------------------------------------------------------- extern unsigned int g_TrapFrameOffset; +_FX NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args); + _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack) { NTSTATUS status; + // + // Note: when directly calling win32k functions with "Core Isolation" (HVCI) enabled + // the nt!guard_dispatch_icall will cause a bugcheck! + // Hence we use a call proxy Sbie_InvokeSyscall_asm instead of a direct call + // + __try { //DbgPrint("[syscall] request param count = %d\n", entry->param_count); - if (entry->param_count == 0) { - - P_SystemService00 nt = (P_SystemService00)entry->ntos_func; - status = nt(); - - } else if (entry->param_count == 1) { - - P_SystemService01 nt = (P_SystemService01)entry->ntos_func; - status = nt(stack[0]); - - } else if (entry->param_count == 2) { - - P_SystemService02 nt = (P_SystemService02)entry->ntos_func; - status = nt(stack[0], stack[1]); - - } else if (entry->param_count == 3) { - - P_SystemService03 nt = (P_SystemService03)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2]); - - } else if (entry->param_count == 4) { - - P_SystemService04 nt = (P_SystemService04)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3]); - - } else if (entry->param_count == 5) { - - P_SystemService05 nt = (P_SystemService05)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4]); - - } else if (entry->param_count == 6) { - - P_SystemService06 nt = (P_SystemService06)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5]); - - } else if (entry->param_count == 7) { - - P_SystemService07 nt = (P_SystemService07)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6]); - - } else if (entry->param_count == 8) { - - P_SystemService08 nt = (P_SystemService08)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7]); - - } else if (entry->param_count == 9) { - - P_SystemService09 nt = (P_SystemService09)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8]); - - } else if (entry->param_count == 10) { - - P_SystemService10 nt = (P_SystemService10)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9]); - - } else if (entry->param_count == 11) { - - P_SystemService11 nt = (P_SystemService11)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10]); - - } else if (entry->param_count == 12) { - - P_SystemService12 nt = (P_SystemService12)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11]); - - } else if (entry->param_count == 13) { - - P_SystemService13 nt = (P_SystemService13)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12]); - - } else if (entry->param_count == 14) { - - P_SystemService14 nt = (P_SystemService14)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13]); - - } else if (entry->param_count == 15) { - - P_SystemService15 nt = (P_SystemService15)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13], - stack[14]); - - } else if (entry->param_count == 16) { - - P_SystemService16 nt = (P_SystemService16)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13], - stack[14], stack[15]); - - } else if (entry->param_count == 17) { - - P_SystemService17 nt = (P_SystemService17)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13], - stack[14], stack[15], stack[16]); - - } else if (entry->param_count == 18) { - - P_SystemService18 nt = (P_SystemService18)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13], - stack[14], stack[15], stack[16], stack[17]); - - } else if (entry->param_count == 19) { - - P_SystemService19 nt = (P_SystemService19)entry->ntos_func; - status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], - stack[5], stack[6], stack[7], stack[8], stack[9], - stack[10], stack[11], stack[12], stack[13], - stack[14], stack[15], stack[16], stack[17], - stack[18]); - - } else { - - status = STATUS_INVALID_SYSTEM_SERVICE; - } + status = Sbie_InvokeSyscall_asm(entry->ntos_func, entry->param_count, stack); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); diff --git a/Sandboxie/core/drv/token.c b/Sandboxie/core/drv/token.c index e79c78e3..0ad16c7b 100644 --- a/Sandboxie/core/drv/token.c +++ b/Sandboxie/core/drv/token.c @@ -2026,7 +2026,7 @@ _FX NTSTATUS Sbie_SepFilterToken_KernelMode( return statusRet; } -_FX NTSTATUS Sbie_SepFilterTokenHandler_asm(void* TokenObject, ULONG_PTR SidCount, ULONG_PTR SidPtr, ULONG_PTR LengthIncrease, void** NewToken); +_FX NTSTATUS Sbie_SepFilterTokenHandler_asm(void* TokenObject, ULONG_PTR SidCount, ULONG_PTR SidPtr, ULONG_PTR LengthIncrease, void** NewToken); _FX NTSTATUS Sbie_SepFilterTokenHandler(void *TokenObject, ULONG_PTR SidCount, @@ -2038,9 +2038,9 @@ _FX NTSTATUS Sbie_SepFilterTokenHandler(void *TokenObject, #ifdef _WIN64 // - // When built with VS2019 on systems with enabled "Core Isolation" we get a BSOD pointing to _chkstk, - // this is a function added by the compiler under certain conditions. - // We work around this issue by providing a hand crafter wrapper function that performs the call. + // When built with VS2019 on systems with enabled "Core Isolation" (HVCI) we get a BSOD. + // This is caused by "Control Flow Guard", we could eider disable it for this file or, + // work around this issue by providing a hand crafted wrapper function that performs the call. // status = Sbie_SepFilterTokenHandler_asm(TokenObject, SidCount, SidPtr, LengthIncrease, NewToken); diff --git a/Sandboxie/core/drv/util_asm.asm b/Sandboxie/core/drv/util_asm.asm index 284eef3f..05c1623a 100644 --- a/Sandboxie/core/drv/util_asm.asm +++ b/Sandboxie/core/drv/util_asm.asm @@ -229,6 +229,7 @@ endif ;---------------------------------------------------------------------------- ifdef _WIN64 + EXTERN Token_SepFilterToken : QWORD Sbie_SepFilterTokenHandler_asm PROC @@ -237,32 +238,141 @@ Sbie_SepFilterTokenHandler_asm PROC mov qword ptr [rsp+18h],r8 mov qword ptr [rsp+10h],rdx mov qword ptr [rsp+8],rcx + sub rsp,78h + mov dword ptr [rsp+60h],0 - mov rax,qword ptr [rsp+00000000000000A0h] + mov rax,qword ptr [rsp+00000000000000A0h] ; NewToken mov qword ptr [rsp+50h],rax - mov rax,qword ptr [rsp+0000000000000098h] + mov rax,qword ptr [rsp+0000000000000098h] ; LengthIncrease mov qword ptr [rsp+48h],rax - mov rax,qword ptr [rsp+0000000000000090h] + mov rax,qword ptr [rsp+0000000000000090h] ; SidPtr mov qword ptr [rsp+40h],rax - mov rax,qword ptr [rsp+0000000000000088h] + mov rax,qword ptr [rsp+0000000000000088h] ; SidCount mov qword ptr [rsp+38h],rax mov qword ptr [rsp+30h],0 mov qword ptr [rsp+28h],0 mov qword ptr [rsp+20h],0 - xor r9d,r9d - xor r8d,r8d - xor edx,edx - mov rcx,qword ptr [rsp+0000000000000080h] + mov r9d,0 + mov r8d,0 + mov edx,0 + mov rcx,qword ptr [rsp+0000000000000080h] ; TokenObject call Token_SepFilterToken - mov dword ptr [rsp+60h],eax - mov eax,dword ptr [rsp+60h] + add rsp,78h + ret Sbie_SepFilterTokenHandler_asm ENDP + endif ;---------------------------------------------------------------------------- +ifdef _WIN64 + +Sbie_InvokeSyscall_asm PROC + + mov qword ptr [rsp+20h], r9 + mov qword ptr [rsp+18h], r8 + mov qword ptr [rsp+10h], rdx + mov qword ptr [rsp+8], rcx + + ; note: (count & 0x0F) + 4 = 19 arguments are the absolute maximum + + ; quick sanity check + cmp rdx, 13h ; if count > 19 + jle arg_count_ok + mov rax, 0C000001Ch ; return STATUS_INVALID_SYSTEM_SERVICE + ret +arg_count_ok: + + push rsi + push rdi + ; prepare enough stack for up to 19 arguments + sub rsp, 98h + + ; save our 3 relevant arguments to spare registers + mov r11, r8 ; args + mov r10, rdx ; count + mov rax, rcx ; func + + ; check if we have higher arguments and if not skip + cmp r10, 4 + jle copy_reg_args + ; copy arguments 5-19 + mov rsi, r11 ; source + add rsi, 20h + mov rdi, rsp ; destination + add rdi, 20h + mov rcx, r10 ; arg count + sub rcx, 4 ; skip the register passed args + rep movsq + +copy_reg_args: + ; copy arguments 1-4 + mov r9, qword ptr [r11+18h] + mov r8, qword ptr [r11+10h] + mov rdx, qword ptr [r11+08h] + mov rcx, qword ptr [r11+00h] + + ; call the function + call rax + + ; clear stack + add rsp, 98h + pop rdi + pop rsi + + ret + +Sbie_InvokeSyscall_asm ENDP + +else + +_Sbie_InvokeSyscall_asm@12 PROC + + ; NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args); + + ; quick sanity check + cmp dword ptr [esp+04h+4h], 13h ; @count + jle args_ok + mov eax, 0C000001Ch ; return STATUS_INVALID_SYSTEM_SERVICE + ret +args_ok: + + ; prepare enough stack for up to 19 arguments + push ebp + push esi + push edi + mov ebp, esp + sub esp, 4Ch + + ; copy arguments 0-19 + mov esi, dword ptr [ebp+10h+8h] ; source @args + mov edi, esp ; destination + mov ecx, dword ptr [ebp+10h+4h] ; arg count @count + rep movsd + + ; call the function + mov eax, dword ptr [ebp+10h+0h] ; @func + call eax + + ; clear stack +function_end: + + mov esp,ebp + pop edi + pop esi + pop ebp + ret + +_Sbie_InvokeSyscall_asm@12 ENDP +PUBLIC _Sbie_InvokeSyscall_asm@12 + +endif + +;---------------------------------------------------------------------------- + + end diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h index 48502e7c..e0c89928 100644 --- a/SandboxiePlus/version.h +++ b/SandboxiePlus/version.h @@ -2,7 +2,7 @@ #define VERSION_MJR 1 #define VERSION_MIN 0 -#define VERSION_REV 6 +#define VERSION_REV 7 #define VERSION_UPD 0 #ifndef STR