This commit is contained in:
DavidXanatos 2021-12-12 17:15:06 +01:00
parent 690376ef04
commit 36cc77873c
7 changed files with 274 additions and 57 deletions

View File

@ -7,7 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.3 / 5.55.3] - 2021-12-??
### Added
- added mechanism to hook Win32 system calls, this should resolve the issue with Chromium HW acceleration
- added mechanism to hook Win32 system calls on windows 10 and later, this should resolve the issue with Chromium HW acceleration
-- to enable it, add "EnableWin32kHooks=y" to the global ini section, this feature is highly experimental (!)
-- the hooks will be automatically applied to Chromium GPU processes
-- to force Win32k hooks for all processes in a selected box add "AlwaysUseWin32kHooks=y" [#1261](https://github.com/sandboxie-plus/Sandboxie/issues/1261) [#1395](https://github.com/sandboxie-plus/Sandboxie/issues/1395)

View File

@ -441,6 +441,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="syscall_util.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="syscall_win32.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>

View File

@ -156,6 +156,9 @@
<ClCompile Include="dll.c">
<Filter>syscall</Filter>
</ClCompile>
<ClCompile Include="syscall_util.c">
<Filter>syscall</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />

View File

@ -1489,6 +1489,20 @@ _FX NTSTATUS Conf_Api_Reload(PROCESS *proc, ULONG64 *parms)
Token_Init_SbieLogin();
}
/*
#ifdef HOOK_WIN32K
// must be windows 10 or later
if (Driver_OsBuild >= 10041) {
extern ULONG Syscall_MaxIndex32;
if (Conf_Get_Boolean(NULL, L"EnableWin32kHooks", 0, FALSE) && Syscall_MaxIndex32 == 0) {
if(Syscall_Init_List32()){
Syscall_Init_Table32();
}
}
}
#endif
*/
InterlockedExchange(&reconf_lock, 0);
}

View File

@ -30,7 +30,7 @@
#include "util.h"
#include "session.h"
#include "conf.h"
#include "common/pattern.h"
//---------------------------------------------------------------------------
@ -101,6 +101,7 @@ static BOOLEAN Syscall_GetKernelAddr(
#pragma alloc_text (INIT, Syscall_GetServiceTable)
#endif // ALLOC_PRAGMA
#include "syscall_util.c"
#ifdef HOOK_WIN32K
#include "syscall_win32.c"
@ -267,6 +268,7 @@ _FX BOOLEAN Syscall_Init(void)
_FX BOOLEAN Syscall_Init_List(void)
{
BOOLEAN success = FALSE;
UCHAR *name, *ntdll_code;
void *ntos_addr;
DLL_ENTRY *dll;
@ -276,17 +278,26 @@ _FX BOOLEAN Syscall_Init_List(void)
List_Init(&Syscall_List);
//
// preapre the enabled/disabled lists
//
//LIST enabled_hooks;
//LIST disabled_hooks;
//Syscall_LoadHookMap(L"EnableNtDllHook", &enabled_hooks);
//Syscall_LoadHookMap(L"DisableNtDllHook", &disabled_hooks);
//
// scan each ZwXxx export in NTDLL
//
dll = Dll_Load(Dll_NTDLL);
if (! dll)
return FALSE;
goto finish;
proc_offset = Dll_GetNextProc(dll, "Zw", &name, &proc_index);
if (! proc_offset)
return FALSE;
goto finish;
while (proc_offset) {
@ -321,12 +332,18 @@ _FX BOOLEAN Syscall_Init_List(void)
|| IS_PROC_NAME(18, "TerminateJobObject")
|| IS_PROC_NAME(16, "TerminateProcess")
|| IS_PROC_NAME(15, "TerminateThread")
|| IS_PROC_NAME(14, "YieldExecution") // ICD-10607 - McAfee uses it to pass its own data in the stack. The call is not important to us.
) {
goto next_zwxxx;
}
//BOOLEAN default_action = TRUE;
// ICD-10607 - McAfee uses it to pass its own data in the stack. The call is not important to us.
if ( IS_PROC_NAME(14, "YieldExecution"))
goto next_zwxxx;
// default_action = FALSE;
//
// the Google Chrome "wow_helper" process expects NtMapViewOfSection
// to not be already hooked. although this is needed only on 64-bit
@ -336,6 +353,17 @@ _FX BOOLEAN Syscall_Init_List(void)
if ( IS_PROC_NAME(16, "MapViewOfSection"))
goto next_zwxxx;
// default_action = FALSE;
//
// check our custom map
//
//if (!Syscall_TestHookMap(name, name_len, &enabled_hooks, &disabled_hooks, default_action)) {
// //DbgPrint(" NtDll Hook disabled for %s\n", name);
// goto next_zwxxx;
//}
//DbgPrint(" NtDll Hook enabled for %s\n", name);
//
// analyze each ZwXxx export to find the service index number
@ -368,7 +396,7 @@ _FX BOOLEAN Syscall_Init_List(void)
if (! ntos_addr) {
Syscall_ErrorForAsciiName(name);
return FALSE;
goto finish;
}
//
@ -378,7 +406,7 @@ _FX BOOLEAN Syscall_Init_List(void)
entry_len = sizeof(SYSCALL_ENTRY) + name_len + 1;
entry = Mem_AllocEx(Driver_Pool, entry_len, TRUE);
if (! entry)
return FALSE;
goto finish;
entry->syscall_index = (USHORT)syscall_index;
entry->param_count = (USHORT)param_count;
@ -405,21 +433,28 @@ next_zwxxx:
proc_offset = Dll_GetNextProc(dll, NULL, &name, &proc_index);
}
success = TRUE;
//
// report an error if we did not find a reasonable number of services
//
if (Syscall_MaxIndex < 100) {
Log_Msg1(MSG_1113, L"100");
return FALSE;
success = FALSE;
}
if (Syscall_MaxIndex >= 500) {
Log_Msg1(MSG_1113, L"500");
return FALSE;
success = FALSE;
}
return TRUE;
finish:
//Syscall_FreeHookMap(&enabled_hooks);
//Syscall_FreeHookMap(&disabled_hooks);
return success;
}

View File

@ -0,0 +1,136 @@
/*
* Copyright 2021 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/>.
*/
//---------------------------------------------------------------------------
// Syscall Management
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Syscall_LoadHookMap
//---------------------------------------------------------------------------
_FX BOOLEAN Syscall_LoadHookMap(const WCHAR* setting_name, LIST *list)
{
ULONG index;
const WCHAR *value;
PATTERN* pat;
List_Init(list);
Conf_AdjustUseCount(TRUE);
for (index = 0; ; ++index) {
//
// get next configuration setting for this path list
//
value = Conf_Get(NULL, setting_name, index);
if (! value)
break;
//
// create pattern and add to list
//
pat = Pattern_Create(Driver_Pool, value, FALSE, 0);
if (pat) {
List_Insert_After(list, NULL, pat);
}
}
Conf_AdjustUseCount(FALSE);
return TRUE;
}
//---------------------------------------------------------------------------
// Syscall_HookMapMatch
//---------------------------------------------------------------------------
_FX int Syscall_HookMapMatch(const WCHAR *name, ULONG name_len, LIST *list)
{
PATTERN* pat;
int match_len = 0;
pat = List_Head(list);
while (pat) {
int cur_len = Pattern_MatchX(pat, name, name_len);
if (cur_len > match_len) {
match_len = cur_len;
}
pat = List_Next(pat);
}
return match_len;
}
//---------------------------------------------------------------------------
// Syscall_TestHookMap
//---------------------------------------------------------------------------
_FX BOOLEAN Syscall_TestHookMap(const UCHAR* name, ULONG name_len, LIST* enabled_hooks, LIST* disabled_hooks, BOOLEAN default_action)
{
if(disabled_hooks->count == 0 && enabled_hooks->count == 0)
return default_action;
WCHAR wname[68];
ULONG i;
for (i = 0; i < max(name_len, 64); i++)
wname[i] = name[i];
wname[i] = 0;
int disabe_match = Syscall_HookMapMatch(wname, name_len, disabled_hooks);
int enable_match = Syscall_HookMapMatch(wname, name_len, enabled_hooks);
if (disabe_match >= enable_match)
return FALSE;
if (enable_match != 0)
return TRUE;
return default_action;
}
//---------------------------------------------------------------------------
// Syscall_FreeHookMap
//---------------------------------------------------------------------------
_FX VOID Syscall_FreeHookMap(LIST *list)
{
PATTERN* pat;
while (1) {
pat = List_Head(list);
if (! pat)
break;
List_Remove(list, pat);
Pattern_Free(pat);
}
}

View File

@ -128,18 +128,36 @@ _FX BOOLEAN Syscall_GetWin32kAddr(ULONG *Base_Copy,
_FX BOOLEAN Syscall_Init_List32(void)
{
BOOLEAN success = FALSE;
UCHAR *name, *win32k_code;
void *ntos_addr;
DLL_ENTRY *dll;
SYSCALL_ENTRY *entry;
ULONG proc_index, proc_offset, syscall_index, param_count;
ULONG name_len, entry_len;
ULONG* table_copy = NULL;
List_Init(&Syscall_List32);
//
// preapre the enabled/disabled lists
//
LIST enabled_hooks;
LIST disabled_hooks;
Syscall_LoadHookMap(L"EnableWin32Hook", &enabled_hooks);
Syscall_LoadHookMap(L"DisableWin32Hook", &disabled_hooks);
//BOOLEAN ignore_hook_blacklist = Conf_Get_Boolean(NULL, L"IgnoreHookBlacklist", 0, FALSE);
//
// get the syscall table
//
KSERVICE_TABLE_DESCRIPTOR *ShadowTable = (KSERVICE_TABLE_DESCRIPTOR *)Syscall_GetServiceTable();
if (!ShadowTable) {
Log_Msg1(MSG_1113, L"SHADOW_TABLE");
return FALSE;
goto finish;
}
//DbgPrint(" win32k.sys SysCalls: %d %p %p\n", ShadowTable->Limit, ShadowTable->Base, ShadowTable->Number);
ShadowTable += 1;
@ -147,26 +165,24 @@ _FX BOOLEAN Syscall_Init_List32(void)
if (ShadowTable->Limit > 0xFFF) { // not plausible
Log_Msg1(MSG_1113, L"SHADOW_TABLE");
return FALSE;
goto finish;
}
//
// We can not read ShadowTable->Base bemory, without being in a GUI thread
// hence we grab csrss.exe and attache to it, create a copy of this memory
// hence we grab csrss.exe and attach to it, create a copy of this memory
// and use it in the loop below instead
//
HANDLE csrssId = Util_GetProcessPidByName(L"csrss.exe");
if (csrssId == (HANDLE)-1) {
Log_Msg1(MSG_1113, L"csrss.exe");
return FALSE;
goto finish;
}
ULONG* table_copy = (ULONG*)Mem_AllocEx(Driver_Pool, ShadowTable->Limit * sizeof(long), TRUE);
if (!table_copy)
return FALSE;
BOOLEAN success = FALSE;
table_copy = (ULONG*)Mem_AllocEx(Driver_Pool, ShadowTable->Limit * sizeof(long), TRUE);
if (!table_copy)
goto finish;
PEPROCESS ProcessObject;
if (NT_SUCCESS(PsLookupProcessByProcessId(csrssId,&ProcessObject))) {
@ -182,26 +198,21 @@ _FX BOOLEAN Syscall_Init_List32(void)
if (!success) {
Log_Msg1(MSG_1113, L"WIN32K_TABLE");
return FALSE;
goto finish;
}
//
// ready
//
List_Init(&Syscall_List32);
success = FALSE;
//
// scan each NtXxx export in WIN32U
//
dll = Dll_Load(L"WIN32U");
if (! dll)
return FALSE;
if (!dll)
goto finish;
proc_offset = Dll_GetNextProc(dll, "Nt", &name, &proc_index);
if (! proc_offset)
return FALSE;
goto finish;
while (proc_offset) {
@ -221,35 +232,40 @@ _FX BOOLEAN Syscall_Init_List32(void)
// with out sys call interface, but also it would be a security issue
// to allow user code execution while we have restored the original token
//
// also some hooks cause BSOD's for now we just blacklist them
//
#define IS_PROC_NAME(ln,nm) (name_len == ln && memcmp(name, nm, ln) == 0)
/*if ( IS_PROC_NAME(18, "UserCreateWindowEx")
|| memcmp(name, "User", 4) == 0 // a lot of user stuff breaks genrally
|| IS_PROC_NAME(27, "UserSetProcessWindowStation") // bsod
|| IS_PROC_NAME(15, "UserCallNoParam")
|| IS_PROC_NAME(16, "UserCallOneParam")
|| IS_PROC_NAME(16, "UserCallTwoParam")
|| IS_PROC_NAME(20, "UserSetWindowLongPtr")
|| IS_PROC_NAME(33, "UserSetProcessDpiAwarenessContext") // bsod
//if(!ignore_hook_blacklist)
if ( IS_PROC_NAME(18, "UserCreateWindowEx")
|| IS_PROC_NAME( 7, "GdiInit") // bsod
|| IS_PROC_NAME(12, "GdiInitSpool") // probably too
|| IS_PROC_NAME(27, "UserSetProcessWindowStation") // bsod
|| IS_PROC_NAME(33, "UserSetProcessDpiAwarenessContext") // bsod
|| IS_PROC_NAME(20, "UserSetThreadDesktop") // bsod
) {
goto next_ntxxx;
}*/
#define IS_PROC_PREFIX(ln,nm) (name_len >= ln && memcmp(name, nm, ln) == 0)
if (!IS_PROC_PREFIX(8, "GdiDdDDI")
/*&& !IS_PROC_NAME(16, "UserSetCursorPos")*/) {
//DbgPrint(" Win32k Hook disabled for %s (blacklisted)\n", name);
goto next_ntxxx;
}
#define IS_PROC_PREFIX(ln,nm) (name_len >= ln && memcmp(name, nm, ln) == 0)
//
// Chrome and msedge need GdiDdDDI to be hooked in order for
// the HW acceleration to work
//
BOOLEAN default_action = IS_PROC_PREFIX(8, "GdiDdDDI");
if (!Syscall_TestHookMap(name, name_len, &enabled_hooks, &disabled_hooks, default_action)) {
//DbgPrint(" Win32k Hook disabled for %s\n", name);
goto next_ntxxx;
}
//DbgPrint(" Win32k Hook enabled for %s\n", name);
//
// analyze each NtXxx export to find the service index number
@ -288,7 +304,7 @@ _FX BOOLEAN Syscall_Init_List32(void)
if (! ntos_addr) {
Syscall_ErrorForAsciiName(name);
goto next_ntxxx;
//return FALSE;
//goto finish;
}
syscall_index = (syscall_index & 0xFFF);
@ -299,10 +315,8 @@ _FX BOOLEAN Syscall_Init_List32(void)
entry_len = sizeof(SYSCALL_ENTRY) + name_len + 1;
entry = Mem_AllocEx(Driver_Pool, entry_len, TRUE);
if (!entry) {
Syscall_MaxIndex32 = 0;
return FALSE;
}
if (!entry)
goto finish;
entry->syscall_index = (USHORT)syscall_index;
entry->param_count = (USHORT)param_count;
@ -330,6 +344,8 @@ next_ntxxx:
}
success = TRUE;
//DbgPrint("Found %d win32 SysCalls\n", Syscall_MaxIndex32);
//
@ -338,19 +354,26 @@ next_ntxxx:
if (Syscall_MaxIndex32 < 100) {
Log_Msg1(MSG_1113, L"100");
Syscall_MaxIndex32 = 0;
return FALSE;
success = FALSE;
}
if (Syscall_MaxIndex32 >= 2000) {
Log_Msg1(MSG_1113, L"2000");
Syscall_MaxIndex32 = 0;
return FALSE;
success = FALSE;
}
Mem_Free(table_copy, ShadowTable->Limit * sizeof(long));
finish:
return TRUE;
if(!success)
Syscall_MaxIndex32 = 0;
Syscall_FreeHookMap(&enabled_hooks);
Syscall_FreeHookMap(&disabled_hooks);
if (table_copy)
Mem_Free(table_copy, ShadowTable->Limit * sizeof(long));
return success;
}