diff --git a/CHANGELOG.md b/CHANGELOG.md index e066e287..627d0000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,43 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.0.0 / 5.55.0] - 2021-11-?? + +### Added +- added Privacy enhanced mode, sandboxes with "UsePrivacyMode=y" will not allow read access to locations containing user data +-- all locations except generic Windows system paths will need to be opened explicitly for read and/or write access +-- using "NormalFilePath=...", "NormalKeyPath=...", "NormalIpcPath=..." allows to open locations to be readable and sandboxed + +- added new "App Compartment" mode of operation, it's enabled by adding "NoSecurityIsolation=y" to the box configuration +-- in this mode, security is traded in for compatibility, it should not be used for untrusted applications +-- note: in this mode, file and registry filtering are still in place, hence processes run without administrative privileges +-- it is reasonably safe, all filtering can be disabled with "NoSecurityFiltering=y" + +- added experimental use of ObRegisterCallbacks to filter object creation and duplication +-- this filtering is independent from the regular SbieDrv's syscall-based filtering, hence it also applies to App Compartments +-- with it enabled, an application running in a compartment will not be able to manipulate processes running outside the sandbox +-- Note: this feature improves the security of unisolated App Compartment boxes +-- to enable this feature, set "EnableObjectFiltering=y" in the global section and reload the driver +-- when globally activated, the filtering can be disabled for individual boxes with "DisableObjectFilter=y" + +- added "DontOpenForBoxed=n", this option disables the discrimination of boxed processes for open file and open key directives +-- this behaviour does not really improve security anyways, but may be annoying, also app compartments always disable this + +- added setting to entirely open access to the COM infrastructure + + +### Changed +- reworked the resource access path matching mechanism to optionally apply more specific rules over less specific ones +-- for example "OpenFilePath=C:\User\Me\AppData\Firefox takes precedence over "WriteFilePath=C:\User\Me\" +-- to enable this new behaviour, add "UseRuleSpecificity=y" to your Sandboxie.ini, this behaviour is always enabled in Privacy enhanced mode +-- added "NormalFilePath=..." to restore default sandboxie behaviour on a given path +-- added "OpenConfPath=...", which similarly to "OpenPipePath=..." is a "OpenKeyPath=..." variant which applies to executables located in the sandbox +- removed option to copy a box during creation, instead the box context menu offers a duplication option +- reworked the box creation dialog to offer new box types + + + + ## [0.9.8d / 5.53.3] - 2021-11-01 diff --git a/Sandboxie/apps/com/BITS/bits.c b/Sandboxie/apps/com/BITS/bits.c index f9964ad0..f455d22b 100644 --- a/Sandboxie/apps/com/BITS/bits.c +++ b/Sandboxie/apps/com/BITS/bits.c @@ -125,6 +125,8 @@ int __stdcall WinMain( BOOL hook_success = TRUE; BOOL ok; + //while(!IsDebuggerPresent()) Sleep(500); __debugbreak(); + Check_Windows_7(); SetupExceptionHandler(); diff --git a/Sandboxie/apps/control/BoxPage.cpp b/Sandboxie/apps/control/BoxPage.cpp index 4c4dc372..890be97a 100644 --- a/Sandboxie/apps/control/BoxPage.cpp +++ b/Sandboxie/apps/control/BoxPage.cpp @@ -2343,7 +2343,7 @@ void CBoxPage::ForceLinger_OnCmdRemove() bool CBoxPage::ForceLinger_MatchPattern( const CString &pat, const CString &test) { - PATTERN *pattern = Pattern_Create(NULL, pat, TRUE); + PATTERN *pattern = Pattern_Create(NULL, pat, TRUE, 0); CString testlwr = test; testlwr.MakeLower(); BOOLEAN match = Pattern_Match(pattern, testlwr, testlwr.GetLength()); @@ -3660,8 +3660,8 @@ void CBoxPage::DoPropertySheet( CBoxPage pageBlockNetworkFiles( BoxPageNetworkFiles, BoxName, MSG_3911, MSG_3955); - //CBoxPage pageResourceAccess( - // BoxPageResourceAccess, BoxName, 0, MSG_3484); + CBoxPage pageResourceAccess( + BoxPageResourceAccess, BoxName, 0, MSG_3484); CBoxPage pageOpenFile( BoxPageOpenFile, BoxName, 0, MSG_4001); @@ -3721,7 +3721,7 @@ void CBoxPage::DoPropertySheet( sheet.AddPage(&pageBlockNetworkFiles); } - //sheet.AddPage(&pageResourceAccess); + sheet.AddPage(&pageResourceAccess); sheet.AddPage(&pageOpenFile); sheet.AddPage(&pageOpenPipe); sheet.AddPage(&pageReadFile); diff --git a/Sandboxie/apps/control/MonitorDialog.cpp b/Sandboxie/apps/control/MonitorDialog.cpp index bb38b4f6..9af4e8fc 100644 --- a/Sandboxie/apps/control/MonitorDialog.cpp +++ b/Sandboxie/apps/control/MonitorDialog.cpp @@ -100,6 +100,7 @@ void CMonitorDialog::OnIdle() static const WCHAR *_SysCall = L"SysCall "; static const WCHAR *_Pipe = L"Pipe "; static const WCHAR *_Ipc = L"Ipc "; + static const WCHAR *_Rpc = L"Rpc "; static const WCHAR *_WinClass = L"WinCls "; static const WCHAR *_Drive = L"(Drive) "; static const WCHAR *_Clsid = L"Clsid "; @@ -158,6 +159,8 @@ void CMonitorDialog::OnIdle() PrefixPtr = _Pipe; else if (type == MONITOR_IPC) PrefixPtr = _Ipc; + else if (type == MONITOR_RPC) + PrefixPtr = _Rpc; else if (type == MONITOR_WINCLASS) PrefixPtr = _WinClass; else if (type == MONITOR_DRIVE) diff --git a/Sandboxie/apps/control/ThirdPartyDialog.cpp b/Sandboxie/apps/control/ThirdPartyDialog.cpp index 59752e3d..29cd9061 100644 --- a/Sandboxie/apps/control/ThirdPartyDialog.cpp +++ b/Sandboxie/apps/control/ThirdPartyDialog.cpp @@ -926,7 +926,7 @@ BOOL CThirdPartyDialog::CheckTemplate(const CString &tmpl_name) continue; } - PATTERN *pat = Pattern_Create(NULL, value, TRUE); + PATTERN *pat = Pattern_Create(NULL, value, TRUE, 0); BOOLEAN match = FALSE; POSITION pos = list->GetHeadPosition(); diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h index 9230172d..8a70e8e4 100644 --- a/Sandboxie/common/my_version.h +++ b/Sandboxie/common/my_version.h @@ -21,9 +21,9 @@ #ifndef _MY_VERSION_H #define _MY_VERSION_H -#define MY_VERSION_BINARY 5,53,3 -#define MY_VERSION_STRING "5.53.3" -#define MY_VERSION_COMPAT "5.53.0" // this refers to the driver ABI compatibility +#define MY_VERSION_BINARY 5,55,0 +#define MY_VERSION_STRING "5.55.0" +#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 #define SBIE_INSTALLER_PATH "..\\Bin\\" diff --git a/Sandboxie/common/pattern.c b/Sandboxie/common/pattern.c index 1ff1d952..0a6e4506 100644 --- a/Sandboxie/common/pattern.c +++ b/Sandboxie/common/pattern.c @@ -55,6 +55,9 @@ struct _PATTERN { // this PATTERN object WCHAR *source; + // a value denoting the match level for the process + ULONG level; + // array of pointers to constant parts. the actual number of // elements is indicate by info.num_cons, and the strings are // allocated as part of this PATTERN object @@ -112,7 +115,7 @@ static const WCHAR *Pattern_Hex = L"__hex"; _FX PATTERN *Pattern_Create( - POOL *pool, const WCHAR *string, BOOLEAN lower) + POOL *pool, const WCHAR *string, BOOLEAN lower, ULONG level) { ULONG num_cons; const WCHAR *iptr; @@ -233,6 +236,8 @@ _FX PATTERN *Pattern_Create( *optr = L'\0'; pat->source = optr; + pat->level = level; + pat->info.v = 0; pat->info.num_cons = (USHORT)num_cons; @@ -282,6 +287,17 @@ _FX const WCHAR *Pattern_Source(PATTERN *pat) } +//--------------------------------------------------------------------------- +// Pattern_Level +//--------------------------------------------------------------------------- + + +_FX ULONG Pattern_Level(PATTERN *pat) +{ + return pat->level; +} + + //--------------------------------------------------------------------------- // Pattern_Match //--------------------------------------------------------------------------- diff --git a/Sandboxie/common/pattern.h b/Sandboxie/common/pattern.h index 003c522a..330488b9 100644 --- a/Sandboxie/common/pattern.h +++ b/Sandboxie/common/pattern.h @@ -50,7 +50,7 @@ typedef struct _PATTERN PATTERN; // LIST_ELEM member (see list.h), so it can be inserted into a list. // -PATTERN *Pattern_Create(POOL *pool, const WCHAR *string, BOOLEAN lower); +PATTERN *Pattern_Create(POOL *pool, const WCHAR *string, BOOLEAN lower, ULONG level); // // Pattern_Free: free the PATTERN object 'pattern' @@ -64,6 +64,12 @@ void Pattern_Free(PATTERN *pat); const WCHAR *Pattern_Source(PATTERN *pat); +// +// Pattern_Level: returns the match level with the process. +// + +ULONG Pattern_Level(PATTERN *pat); + // // Pattern_Match: returns TRUE if 'string' matches PATTERN object 'pattern'. // If 'lower' was TRUE at time of Pattern_Create(), the 'string' passed here diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj index 9ac89c34..e83a606a 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj +++ b/Sandboxie/core/dll/SboxDll.vcxproj @@ -172,6 +172,12 @@ + + true + true + true + true + true true @@ -378,6 +384,7 @@ + @@ -394,6 +401,7 @@ + diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters index 47e9c0ca..a301b2d6 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj.filters +++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters @@ -128,7 +128,6 @@ pst - api @@ -200,6 +199,15 @@ common + + common + + + gui + + + pst + @@ -266,6 +274,9 @@ common + + common + common diff --git a/Sandboxie/core/dll/SboxDll32.def b/Sandboxie/core/dll/SboxDll32.def index 085fae16..fc8e432e 100644 --- a/Sandboxie/core/dll/SboxDll32.def +++ b/Sandboxie/core/dll/SboxDll32.def @@ -41,7 +41,7 @@ SbieApi_OpenProcess=_SbieApi_OpenProcess@8 SbieApi_QueryBoxPath=_SbieApi_QueryBoxPath@28 SbieApi_QueryConf=_SbieApi_QueryConf@20 SbieApi_QueryConfBool=_SbieApi_QueryConfBool@12 -SbieApi_QueryPathList=_SbieApi_QueryPathList@16 +SbieApi_QueryPathList=_SbieApi_QueryPathList@20 SbieApi_QueryProcess=_SbieApi_QueryProcess@20 SbieApi_QueryProcessEx=_SbieApi_QueryProcessEx@24 SbieApi_QueryProcessInfo=_SbieApi_QueryProcessInfo@8 diff --git a/Sandboxie/core/dll/Win32.c b/Sandboxie/core/dll/Win32.c new file mode 100644 index 00000000..f37c81b1 --- /dev/null +++ b/Sandboxie/core/dll/Win32.c @@ -0,0 +1,444 @@ +/* + * Copyright 2020 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 . + */ + +//--------------------------------------------------------------------------- +// Win32 Services +//--------------------------------------------------------------------------- + + +#include "dll.h" + +NTSTATUS Win32_NtUserCreateWindowEx( + DWORD dwExStyle, + PUNICODE_STRING UnsafeClassName, + LPCWSTR VersionedClass, + PUNICODE_STRING UnsafeWindowName, + DWORD dwStyle, + LONG x, + LONG y, + LONG nWidth, + LONG nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam, + DWORD dwShowMode, + DWORD dwUnknown1, + DWORD dwUnknown2, + VOID* qwUnknown3); + + +typedef NTSTATUS (*P_NtUserCreateWindowEx)( + DWORD dwExStyle, + PUNICODE_STRING UnsafeClassName, + LPCWSTR VersionedClass, + PUNICODE_STRING UnsafeWindowName, + DWORD dwStyle, + LONG x, + LONG y, + LONG nWidth, + LONG nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam, + DWORD dwShowMode, + DWORD dwUnknown1, + DWORD dwUnknown2, + VOID* qwUnknown3); + +P_NtUserCreateWindowEx __sys_NtUserCreateWindowEx = NULL; + +#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) + +/* +#ifdef _WIN64 + +#define MAX_FUNC_SIZE 0x76 + +//Note any change to this function requires the same modification to the same function in sbiedll: see dllhook.c (findChromeTarget) +ULONGLONG * findChromeTarget(unsigned char* addr) +{ + int i = 0; + ULONGLONG target = 0; + 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] + //So far the offset has been positive between 0xa00000 and 0xb00000 bytes; + //This may change in a future version of chrome + for (i = 0; i < MAX_FUNC_SIZE; i++) { + if ((*(USHORT *)&addr[i] == 0x8b48)) { + //Look for mov rcx,[target 4 byte offset] or in some cases mov rax,[target 4 byte offset] + if ((addr[i + 2] == 0x0d || addr[i + 2] == 0x05)) { + LONG delta; + target = (ULONG_PTR)(addr + i + 7); + delta = *(LONG *)&addr[i + 3]; + //check if offset is close to the expected value (is positive and less than 0x100000 as of chrome 64) + // if (delta > 0 && delta < 0x100000 ) { //may need to check delta in a future version of chrome + target += delta; + ChromeTarget = *(ULONGLONG **)target; + // } + break; + } + } + } + return ChromeTarget; +} +#endif +*/ + +_FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) +{ + UCHAR *SystemServiceAsm, *ZwXxxPtr; + ULONG *SyscallPtr; + ULONG SyscallNum; + void *RegionBase; + SIZE_T RegionSize; + ULONG OldProtect; + + const ULONG OFFSET_ULONG_PTR = +#ifdef _WIN64 + 2; // on 64-bit Windows, "mov rax, 0" instruction is two bytes + //ULONGLONG *chrome64Target = NULL; +#else + 1; // on 32-bit Windows, "mov edx, 0" instruction is one byte +#endif + + SBIELOW_DATA* data = SbieApi_data; + SystemServiceAsm = (UCHAR*)0;// 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 + + + while (SyscallPtr[0] || SyscallPtr[1]) { + + // + // the ULONG at SyscallPtr[1] gives the offset of the ZwXxx export + // from the base address of ntdll + // + + ZwXxxPtr = (UCHAR *)((ULONG_PTR)SyscallPtr[1] + (UCHAR*)win32u_base); + + // + // in a chrome sandbox process, some syscalls are already hooked + // by chrome at this point, and we want to hook the syscall stub + // 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 + */ + + // + // make the syscall address writable + // + RegionBase = ZwXxxPtr; + +#ifdef _WIN64 + RegionSize = 12; + /*if (!chrome64Target) { + chrome64Target = (ULONG_PTR*)ZwXxxPtr; + }*/ +#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 + // + + SyscallNum = SyscallPtr[0] | 0x1000; + +#ifdef _WIN64 + /*if (chrome64Target && data->Sbie64bitJumpTable) { + RegionSize = 16; + ZwXxxPtr = (UCHAR *)chrome64Target; + RegionBase = ZwXxxPtr; + + 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]; + // 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> + jTableTarget[0] = 0x49; + jTableTarget[1] = 0xc7; + jTableTarget[2] = 0xc2; + *(ULONG *)&jTableTarget[3] = SyscallNum; + // jmp <4 byte SystemServiceAsm> + if (data->is_win10) { + jTableTarget[7] = 0x48; + jTableTarget[8] = 0xe9; + *(ULONG *)&jTableTarget[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (jTableTarget + 13)); + } + else { + + jTableTarget[7] = 0xe9; + *(ULONG *)&jTableTarget[8] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (jTableTarget + 12)); + + } + // *(ULONGLONG *) &jTableTarget[-8] = 0x9090909090909090; // patch location for sboxdll hook. jtable elements need to be at 0x18 in size for this + // jump table: using push rcx instead of push rax to differentiate from the chrome sandbox hook + // the sboxdll.dll needs this distinction to handle the chrome type hook properly and to not search + // for the chrome target in a sbox 64 bit jtable hook + + // using ret is not compatible with CET - Hardware-enforced Stack Protection + //ZwXxxPtr[0] = 0x51; //push rcx + //// mov rax,<8 byte address to jTableEntry> + //ZwXxxPtr[1] = 0x48; + //ZwXxxPtr[2] = 0xb8; + //*(ULONGLONG *)&ZwXxxPtr[3] = (ULONGLONG)jTableTarget; + //*(ULONG *)&ZwXxxPtr[11] = 0x24048948; // mov [rsp],rax + //ZwXxxPtr[15] = 0xc3; // ret + + // mov rax,<8 byte address to jTableEntry> + ZwXxxPtr[0] = 0x90; // start with a nop so that it does not look lile a chrome hook + ZwXxxPtr[1] = 0x48; + ZwXxxPtr[2] = 0xb8; + *(ULONGLONG*)&ZwXxxPtr[3] = (ULONGLONG)jTableTarget; + // jmp rax + ZwXxxPtr[11] = 0xFF; + ZwXxxPtr[12] = 0xE0; + + chrome64Target = NULL; + } + else*/ + { + RegionBase = ZwXxxPtr; + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + + ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber + //ZwXxxPtr[0] = 0xCC; // debug + ZwXxxPtr[1] = 0xC7; + ZwXxxPtr[2] = 0xC2; + *(ULONG *)&ZwXxxPtr[3] = SyscallNum; + if (!data->long_diff) { + + if (data->is_win10) { + ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm + ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm + *(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 + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + + ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber + *(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; + } + + HeapFree(GetProcessHeap(), 0, syscall_data); + return TRUE; +} +#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) + return TRUE; // just return on older builds + + if (!SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", FALSE)) { + + SbieDll_HookWin32SysCalls(hmodule); + } + + P_NtUserCreateWindowEx NtUserCreateWindowEx = (P_NtUserCreateWindowEx)GetProcAddress(hmodule, "NtUserCreateWindowEx"); + SBIEDLL_HOOK(Win32_, NtUserCreateWindowEx); +#endif + + return TRUE; +} + +_FX NTSTATUS Win32_NtUserCreateWindowEx( + DWORD dwExStyle, + PUNICODE_STRING UnsafeClassName, + LPCWSTR VersionedClass, + PUNICODE_STRING UnsafeWindowName, + DWORD dwStyle, + LONG x, + LONG y, + LONG nWidth, + LONG nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam, + DWORD dwShowMode, + DWORD dwUnknown1, + DWORD dwUnknown2, + VOID* qwUnknown3) +{ +#if 1 + + NTSTATUS ret = __sys_NtUserCreateWindowEx( + dwExStyle, + UnsafeClassName, + VersionedClass, + UnsafeWindowName, + dwStyle, + x, + y, + nWidth, + nHeight, + hWndParent, + hMenu, + hInstance, + lpParam, + dwShowMode, + dwUnknown1, + dwUnknown2, + qwUnknown3); + + return ret; + +#else + extern HANDLE SbieApi_DeviceHandle; + + ULONG syscall_index = 0x1074; // NtUserCreateWindowEx in 21H2 + + ULONG64 stack[17]; + + stack[0] = dwExStyle; + stack[1] = (ULONG64)UnsafeClassName; + stack[2] = (ULONG64)VersionedClass; + stack[3] = (ULONG64)UnsafeWindowName; + stack[4] = dwStyle; + stack[5] = x; + stack[6] = y; + stack[7] = nWidth; + stack[8] = nHeight; + stack[9] = (ULONG64)hWndParent; + stack[10] = (ULONG64)hMenu; + stack[11] = (ULONG64)hInstance; + stack[12] = (ULONG64)lpParam; + stack[13] = dwShowMode; + stack[14] = dwUnknown1; + stack[15] = dwUnknown2; + stack[16] = (ULONG64)qwUnknown3; + + NTSTATUS status; + __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; + + memset(parms, 0, sizeof(parms)); + parms[0] = API_INVOKE_SYSCALL32; + parms[1] = (ULONG64)(ULONG_PTR)syscall_index; + parms[2] = (ULONG64)(ULONG_PTR)stack; // pointer to system service arguments on stack + + IO_STATUS_BLOCK MyIoStatusBlock; + status = SbieApi_NtDeviceIoControlFile( + SbieApi_DeviceHandle, NULL, NULL, NULL, &MyIoStatusBlock, + API_SBIEDRV_CTLCODE, parms, sizeof(ULONG64) * 8, NULL, 0); + + return status; + +#endif +} diff --git a/Sandboxie/core/dll/com.c b/Sandboxie/core/dll/com.c index d5cfc450..d900bb80 100644 --- a/Sandboxie/core/dll/com.c +++ b/Sandboxie/core/dll/com.c @@ -163,6 +163,9 @@ static void Com_Monitor(REFCLSID rclsid, ULONG monflag); #define HSTRING void* static HRESULT Com_RoGetActivationFactory(HSTRING activatableClassId, REFIID iid, void** factory); +//static HRESULT Com_IClassFactoryEx_New( +// REFCLSID rclsid, const WCHAR* StringGUID, void** ppv); + //--------------------------------------------------------------------------- @@ -289,6 +292,10 @@ static const GUID IID_INetFwRule = { 0xAF230D27, 0xBABA, 0x4E42, { 0xAC, 0xED, 0xF5, 0x24, 0xF2, 0x2C, 0xFC, 0xE2 } }; +//static const GUID IID_VirtualDesktopManager = { +// 0xAA509086, 0x5CA9, 0x4C25, +// { 0x8F, 0x95, 0x58, 0x9D, 0x3C, 0x07, 0xB4, 0x8A } }; + //--------------------------------------------------------------------------- // Com_LoadClsidList @@ -691,7 +698,19 @@ _FX HRESULT Com_CoCreateInstance( return E_ACCESSDENIED; } - if (!Ipc_OpenCOM && SbieDll_IsOpenClsid(rclsid, clsctx, NULL)) { + /*if (memcmp(rclsid, &IID_VirtualDesktopManager, 16) == 0) { + + hr = Com_IClassFactoryEx_New(rclsid, NULL, (void **)&pFactory); + + if (SUCCEEDED(hr)) { + + hr = IClassFactory_CreateInstance( + pFactory, pUnkOuter, riid, ppv); + + IClassFactory_Release(pFactory); + } + + } else*/ if (!Ipc_OpenCOM && SbieDll_IsOpenClsid(rclsid, clsctx, NULL)) { hr = Com_IClassFactory_New(rclsid, NULL, (void **)&pFactory); @@ -3480,22 +3499,25 @@ _FX void Com_LoadRTList(const WCHAR* setting, WCHAR** pNames) _FX BOOLEAN Com_IsClosedRT(const wchar_t* strClassId) { - // - // Chrome uses the FindAppUriHandlersAsync, which fails returning a NULL value when we don't have com open and more rights - // than we should have. Chrome does not check for this failure mode and dereferences it, resulting in a fatal crash. - // Since we don't support modern app features anyways, the simplest workaround is to block this interface. - // - if (Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) { + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0) { // in complartment mode those should work fine as we have a normal token - if (wcscmp(strClassId, L"Windows.System.Launcher") == 0) - return TRUE; + // + // Chrome uses the FindAppUriHandlersAsync, which fails returning a NULL value when we don't have com open and more rights + // than we should have. Chrome does not check for this failure mode and dereferences it, resulting in a fatal crash. + // Since we don't support modern app features anyways, the simplest workaround is to block this interface. + // + if (Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) { + + if (wcscmp(strClassId, L"Windows.System.Launcher") == 0) + return TRUE; + } + + // + // this seems to be broken as well + //if (wcscmp(strClassId, L"Windows.UI.Notifications.ToastNotificationManager") == 0) + // return TRUE; } - // - // this seems to be broken as well - //if (wcscmp(strClassId, L"Windows.UI.Notifications.ToastNotificationManager") == 0) - // return TRUE; - static const WCHAR* setting = L"ClosedRT"; Com_LoadRTList(setting, &Com_ClosedRT); @@ -3528,4 +3550,92 @@ _FX HRESULT Com_RoGetActivationFactory(HSTRING activatableClassId, REFIID iid, SbieApi_MonitorPut(MONITOR_RTCLASS, strClassId); return __sys_RoGetActivationFactory(activatableClassId, iid, factory); -} \ No newline at end of file +} + + +/* +//--------------------------------------------------------------------------- +// Com_IClassFactoryEx_CreateInstance +//--------------------------------------------------------------------------- + +_FX HRESULT Com_OuterIUnknown_QueryInterface_NotImpl( + COM_IUNKNOWN* This, REFIID riid, void** ppv) +{ + SbieApi_Log(2205, L"IUnknown::QueryInterface"); + return E_NOTIMPL; +} + +_FX HRESULT Com_IsWindowOnCurrentVirtualDesktop(COM_IUNKNOWN* This, __RPC__in HWND topLevelWindow, __RPC__out BOOL* onCurrentDesktop) { + return E_NOTIMPL; +} +_FX HRESULT Com_GetWindowDesktopId(COM_IUNKNOWN* This, __RPC__in HWND topLevelWindow, __RPC__out GUID *desktopId) { + return E_NOTIMPL; +} +_FX HRESULT Com_MoveWindowToDesktop(COM_IUNKNOWN* This, __RPC__in HWND topLevelWindow, __RPC__in REFGUID desktopId) { + return E_NOTIMPL; +} + +void* Com_VirtualDesktopManager_vtbl[] = { Com_IsWindowOnCurrentVirtualDesktop,Com_GetWindowDesktopId,Com_MoveWindowToDesktop }; + +typedef struct _COM_ITF { + const GUID* Guid; + void** vtbl; + int vtblCnt; +} COM_ITF; + +COM_ITF Com_Interfaces[] = { {&IID_VirtualDesktopManager, Com_VirtualDesktopManager_vtbl, ARRAYSIZE(Com_VirtualDesktopManager_vtbl)} }; + + +_FX HRESULT Com_IClassFactoryEx_CreateInstance( + COM_IUNKNOWN *This, IUnknown *pUnkOuter, REFIID riid, void **ppv) +{ + ULONG hr; + COM_IUNKNOWN *pUnknown; + + if (pUnkOuter) + SbieApi_Log(2205, L"IClassFactory::CreateInstance"); + + for (ULONG i = 0; i < ARRAYSIZE(Com_Interfaces); i++) { + + if (memcmp(&This->Guid, Com_Interfaces[i].Guid, 16) == 0) { + + hr = Com_IUnknown_New(-1, 3, FLAG_REMOTE_REF | FLAG_PPROXY_AT_VTBL3, &pUnknown); + if (SUCCEEDED(hr)) { + + pUnknown->Vtbl[0] = Com_OuterIUnknown_QueryInterface_NotImpl; + memcpy(&pUnknown->Vtbl[3], Com_Interfaces[i].vtbl, sizeof(void*) * Com_Interfaces[i].vtblCnt); + memcpy(&pUnknown->Guid, riid, sizeof(GUID)); + + *ppv = pUnknown; + } + return hr; + } + } + + return E_NOTIMPL; +} + + +//--------------------------------------------------------------------------- +// Com_IClassFactoryEx_New +//--------------------------------------------------------------------------- + + +_FX HRESULT Com_IClassFactoryEx_New( + REFCLSID rclsid, const WCHAR* StringGUID, void** ppv) +{ + HRESULT hr; + COM_IUNKNOWN *This; + hr = Com_IUnknown_New(-1, 2, FLAG_REMOTE_REF, &This); + if (SUCCEEDED(hr)) { + + This->Vtbl[0] = Com_IClassFactory_QueryInterface; + This->Vtbl[3] = Com_IClassFactoryEx_CreateInstance; + This->Vtbl[4] = Com_IClassFactory_LockServer; + memcpy(&This->Guid, rclsid, sizeof(GUID)); + + *ppv = This; + } + return hr; +} +*/ \ No newline at end of file diff --git a/Sandboxie/core/dll/config.c b/Sandboxie/core/dll/config.c index 663022bb..7ad3b7af 100644 --- a/Sandboxie/core/dll/config.c +++ b/Sandboxie/core/dll/config.c @@ -68,14 +68,14 @@ _FX BOOLEAN Config_MatchImage( wcsncpy(tmp, pat_str, pat_len); tmp[pat_len] = L'\0'; - pat = Pattern_Create(Dll_PoolTemp, tmp, TRUE); + pat = Pattern_Create(Dll_PoolTemp, tmp, TRUE, 0); Dll_Free(tmp); } else { - pat = Pattern_Create(Dll_PoolTemp, pat_str, TRUE); + pat = Pattern_Create(Dll_PoolTemp, pat_str, TRUE, 0); } if (!pat) @@ -315,10 +315,11 @@ _FX BOOLEAN Config_InitPatternList(const WCHAR* setting, LIST* list) break; ++index; - WCHAR* value = Config_MatchImageAndGetValue(conf_buf, Dll_ImageName, NULL); + ULONG level; + WCHAR* value = Config_MatchImageAndGetValue(conf_buf, Dll_ImageName, &level); if (value) { - pat = Pattern_Create(Dll_Pool, value, TRUE); + pat = Pattern_Create(Dll_Pool, value, TRUE, level); List_Insert_After(list, NULL, pat); } diff --git a/Sandboxie/core/dll/crypt.c b/Sandboxie/core/dll/crypt.c index 32819861..ccacf2b1 100644 --- a/Sandboxie/core/dll/crypt.c +++ b/Sandboxie/core/dll/crypt.c @@ -392,6 +392,13 @@ _FX BOOLEAN Crypt_Init(HMODULE module) void *CryptUnprotectData; void *CertGetCertificateChain; + // + // in app mode we have our original token so no need to hook this + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0) + return TRUE; + // // hook cryptography services // diff --git a/Sandboxie/core/dll/custom.c b/Sandboxie/core/dll/custom.c index cf591624..9575c16e 100644 --- a/Sandboxie/core/dll/custom.c +++ b/Sandboxie/core/dll/custom.c @@ -73,6 +73,8 @@ _FX BOOLEAN CustomizeSandbox(void) if (GetSetCustomLevel(0) != '1') { + Key_CreateBaseKeys(); + Custom_CreateRegLinks(); DisableDCOM(); DisableRecycleBin(); diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h index 9d166d0b..58c6969a 100644 --- a/Sandboxie/core/dll/dll.h +++ b/Sandboxie/core/dll/dll.h @@ -495,6 +495,7 @@ NTSTATUS Key_OpenOrCreateIfBoxed( void Key_DeleteValueFromCLSID( const WCHAR *Xxxid, const WCHAR *Guid, const WCHAR *ValueName); +void Key_CreateBaseKeys(); //--------------------------------------------------------------------------- // Functions (sxs) @@ -592,6 +593,8 @@ BOOL Proc_ImpersonateSelf(BOOLEAN Enable); BOOLEAN Taskbar_SHCore_Init(HMODULE hmodule); +BOOLEAN Win32_Init(HMODULE hmodule); + //--------------------------------------------------------------------------- // Functions (init for DllMain) diff --git a/Sandboxie/core/dll/dllhook.c b/Sandboxie/core/dll/dllhook.c index ae463202..141504c3 100644 --- a/Sandboxie/core/dll/dllhook.c +++ b/Sandboxie/core/dll/dllhook.c @@ -670,7 +670,7 @@ _FX NTSTATUS Dll_GetSettingsForImageName( } else buf_ptr = buf; - image_pat = Pattern_Create(pool, buf_ptr, TRUE); + image_pat = Pattern_Create(pool, buf_ptr, TRUE, 0); if (Pattern_Match(image_pat, image_lwr, image_len)) { match = TRUE; @@ -887,7 +887,7 @@ _FX void Dll_FixWow64Syscall(void) static UCHAR *_code = NULL; // NoSysCallHooks BEGIN - if(SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) + if((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) return; // NoSysCallHooks END diff --git a/Sandboxie/core/dll/dllpath.c b/Sandboxie/core/dll/dllpath.c index a1f053fe..0044fb17 100644 --- a/Sandboxie/core/dll/dllpath.c +++ b/Sandboxie/core/dll/dllpath.c @@ -26,7 +26,9 @@ #include "common/pattern.c" #include "common/my_version.h" #include "core/drv/api_defs.h" +#include "core/drv/api_flags.h" +#define USE_MATCH_PATH_EX //--------------------------------------------------------------------------- // Structures and Types @@ -36,18 +38,38 @@ typedef struct _PATH_LIST_ANCHOR { POOL *pool; + BOOLEAN file_paths_initialized; BOOLEAN key_paths_initialized; BOOLEAN ipc_paths_initialized; BOOLEAN win_classes_initialized; + +#ifdef USE_MATCH_PATH_EX + LIST normal_file_path; +#endif LIST open_file_path; LIST closed_file_path; LIST write_file_path; +#ifdef USE_MATCH_PATH_EX + LIST read_file_path; +#endif + +#ifdef USE_MATCH_PATH_EX + LIST normal_key_path; +#endif LIST open_key_path; LIST closed_key_path; LIST write_key_path; +#ifdef USE_MATCH_PATH_EX + LIST read_key_path; +#endif + +#ifdef USE_MATCH_PATH_EX + LIST normal_ipc_path; +#endif LIST open_ipc_path; LIST closed_ipc_path; + LIST open_win_classes; } PATH_LIST_ANCHOR; @@ -58,8 +80,13 @@ typedef struct _PATH_LIST_ANCHOR { //--------------------------------------------------------------------------- +#ifdef USE_MATCH_PATH_EX +static BOOLEAN Dll_InitPathList2( + ULONG path_code, LIST *normal, LIST *open, LIST *closed, LIST *write, LIST *read); +#else static BOOLEAN Dll_InitPathList2( ULONG path_code, LIST *open, LIST *closed, LIST *write); +#endif static BOOLEAN Dll_InitPathList3( POOL *pool, ULONG path_code, LIST *list); @@ -111,12 +138,23 @@ _FX BOOLEAN Dll_InitPathList(void) // Dll_InitPathList2 //--------------------------------------------------------------------------- - +#ifdef USE_MATCH_PATH_EX +_FX BOOLEAN Dll_InitPathList2( + ULONG path_code, LIST *normal, LIST *open, LIST *closed, LIST *write, LIST *read) +#else _FX BOOLEAN Dll_InitPathList2( ULONG path_code, LIST *open, LIST *closed, LIST *write) +#endif { BOOLEAN ok = TRUE; +#ifdef USE_MATCH_PATH_EX + if (ok && normal) { + path_code = (path_code & 0xFF00) | 'n'; + ok = Dll_InitPathList3(Dll_PathListAnchor->pool, path_code, normal); + } +#endif + if (ok && open) { path_code = (path_code & 0xFF00) | 'o'; ok = Dll_InitPathList3(Dll_PathListAnchor->pool, path_code, open); @@ -132,6 +170,13 @@ _FX BOOLEAN Dll_InitPathList2( ok = Dll_InitPathList3(Dll_PathListAnchor->pool, path_code, write); } +#ifdef USE_MATCH_PATH_EX + if (ok && read) { + path_code = (path_code & 0xFF00) | 'r'; + ok = Dll_InitPathList3(Dll_PathListAnchor->pool, path_code, write); + } +#endif + if (! ok) { WCHAR str[2]; @@ -139,12 +184,20 @@ _FX BOOLEAN Dll_InitPathList2( str[1] = L'\0'; SbieApi_Log(2317, str); +#ifdef USE_MATCH_PATH_EX + if (normal) + List_Init(normal); +#endif if (open) List_Init(open); if (closed) List_Init(closed); if (write) List_Init(write); +#ifdef USE_MATCH_PATH_EX + if (read) + List_Init(read); +#endif } return ok; @@ -165,12 +218,12 @@ _FX BOOLEAN Dll_InitPathList3(POOL *pool, ULONG path_code, LIST *list) PATTERN *pat; BOOLEAN ok; - status = SbieApi_QueryPathList(path_code, &len, NULL, NULL); + status = SbieApi_QueryPathList(path_code, &len, NULL, NULL, TRUE); if (status != STATUS_SUCCESS) return FALSE; path = Dll_AllocTemp(len); - status = SbieApi_QueryPathList(path_code, NULL, path, NULL); + status = SbieApi_QueryPathList(path_code, NULL, path, NULL, TRUE); if (status != STATUS_SUCCESS) { Dll_Free(path); return FALSE; @@ -179,8 +232,11 @@ _FX BOOLEAN Dll_InitPathList3(POOL *pool, ULONG path_code, LIST *list) ok = TRUE; ptr = path; - while (*ptr) { - pat = Pattern_Create(pool, ptr, TRUE); + // while (*ptr) { + while (*((ULONG*)ptr) != -1) { + ULONG level = *((ULONG*)ptr); + ptr += sizeof(ULONG)/sizeof(WCHAR); + pat = Pattern_Create(pool, ptr, TRUE, level); if (! pat) { ok = FALSE; break; @@ -203,6 +259,95 @@ _FX ULONG SbieDll_MatchPath(WCHAR path_code, const WCHAR *path) return SbieDll_MatchPath2(path_code, path, TRUE, TRUE); } +#ifdef USE_MATCH_PATH_EX + +//--------------------------------------------------------------------------- +// SbieDll_GetReadablePaths +//--------------------------------------------------------------------------- + + +_FX void SbieDll_GetReadablePaths(WCHAR path_code, const WCHAR *path, LIST **lists) +{ + if (path_code == L'f') { + + EnterCriticalSection(&Dll_FilePathListCritSec); + + lists[0] = &Dll_PathListAnchor->normal_file_path; + lists[1] = &Dll_PathListAnchor->open_file_path; + lists[2] = &Dll_PathListAnchor->read_file_path; + lists[3] = NULL; + + } else if (path_code == L'k') { + + lists[0] = &Dll_PathListAnchor->normal_key_path; + lists[1] = &Dll_PathListAnchor->open_key_path; + lists[2] = &Dll_PathListAnchor->read_key_path; + lists[3] = NULL; + + } +} + +_FX void SbieDll_ReleaseFilePathLock() +{ + LeaveCriticalSection(&Dll_FilePathListCritSec); +} + + +//--------------------------------------------------------------------------- +// Process_MatchPathList +//--------------------------------------------------------------------------- + + +_FX int Process_MatchPathList( + WCHAR *path_lwr, ULONG path_len, LIST *list, ULONG* plevel, const WCHAR** patsrc) +{ + PATTERN *pat; + int match_len = 0; + ULONG level = plevel ? *plevel : -1; // lower is better, 3 is max value + + pat = List_Head(list); + while (pat) { + + ULONG cur_level = Pattern_Level(pat); + if (cur_level > level) + goto next; // no point testing patters with a to weak level + + int cur_len = Pattern_MatchX(pat, path_lwr, path_len); + if (cur_len > match_len) { + match_len = cur_len; + level = cur_level; + if (patsrc) *patsrc = Pattern_Source(pat); + + // we need to test all entries to find the best match, so we dont break here + } + + // + // if we have a pattern like C:\Windows\, + // we still want it to match a path like C:\Windows, + // hence we add a L'\\' to the path and check again + // + + else if (path_lwr[path_len - 1] != L'\\') { + path_lwr[path_len] = L'\\'; + cur_len = Pattern_MatchX(pat, path_lwr, path_len + 1); + path_lwr[path_len] = L'\0'; + if (cur_len > match_len) { + match_len = cur_len; + level = cur_level; + if (patsrc) *patsrc = Pattern_Source(pat); + } + } + + next: + pat = List_Next(pat); + } + + if (plevel) *plevel = level; + return match_len; +} +#endif + + //--------------------------------------------------------------------------- // SbieDll_MatchPath2 //--------------------------------------------------------------------------- @@ -210,8 +355,12 @@ _FX ULONG SbieDll_MatchPath(WCHAR path_code, const WCHAR *path) _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckObjectExists, BOOLEAN bMonitorLog) { +#ifdef USE_MATCH_PATH_EX + LIST *normal_list, *open_list, *closed_list, *write_list, *read_list; +#else LIST *open_list, *closed_list, *write_list; PATTERN *pat; +#endif WCHAR *path_lwr; ULONG path_len; ULONG mp_flags; @@ -253,12 +402,22 @@ _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckO EnterCriticalSection(&Dll_FilePathListCritSec); +#ifdef USE_MATCH_PATH_EX + normal_list = &Dll_PathListAnchor->normal_file_path; +#endif open_list = &Dll_PathListAnchor->open_file_path; closed_list = &Dll_PathListAnchor->closed_file_path; write_list = &Dll_PathListAnchor->write_file_path; +#ifdef USE_MATCH_PATH_EX + read_list = &Dll_PathListAnchor->read_file_path; +#endif if (! Dll_PathListAnchor->file_paths_initialized) { +#ifdef USE_MATCH_PATH_EX + Dll_InitPathList2('fx', normal_list, open_list, closed_list, write_list, read_list); +#else Dll_InitPathList2('fx', open_list, closed_list, write_list); +#endif Dll_PathListAnchor->file_paths_initialized = TRUE; } @@ -267,34 +426,64 @@ _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckO } else if (path_code == L'k') { +#ifdef USE_MATCH_PATH_EX + normal_list = &Dll_PathListAnchor->normal_key_path; +#endif open_list = &Dll_PathListAnchor->open_key_path; closed_list = &Dll_PathListAnchor->closed_key_path; write_list = &Dll_PathListAnchor->write_key_path; +#ifdef USE_MATCH_PATH_EX + read_list = &Dll_PathListAnchor->read_key_path; +#endif if (! Dll_PathListAnchor->key_paths_initialized) { +#ifdef USE_MATCH_PATH_EX + Dll_InitPathList2('kx', normal_list, open_list, closed_list, write_list, read_list); +#else Dll_InitPathList2('kx', open_list, closed_list, write_list); +#endif Dll_PathListAnchor->key_paths_initialized = TRUE; } } else if (path_code == L'i') { +#ifdef USE_MATCH_PATH_EX + normal_list = &Dll_PathListAnchor->normal_ipc_path; +#endif open_list = &Dll_PathListAnchor->open_ipc_path; closed_list = &Dll_PathListAnchor->closed_ipc_path; write_list = NULL; +#ifdef USE_MATCH_PATH_EX + read_list = NULL; +#endif if (! Dll_PathListAnchor->ipc_paths_initialized) { +#ifdef USE_MATCH_PATH_EX + Dll_InitPathList2('ix', normal_list, open_list, closed_list, NULL, NULL); +#else Dll_InitPathList2('ix', open_list, closed_list, NULL); +#endif Dll_PathListAnchor->ipc_paths_initialized = TRUE; } } else if (path_code == L'w') { +#ifdef USE_MATCH_PATH_EX + normal_list = NULL; +#endif open_list = &Dll_PathListAnchor->open_win_classes; closed_list = NULL; write_list = NULL; +#ifdef USE_MATCH_PATH_EX + read_list = NULL; +#endif if (! Dll_PathListAnchor->win_classes_initialized) { +#ifdef USE_MATCH_PATH_EX + Dll_InitPathList2('wx', NULL, open_list, NULL, NULL, NULL); +#else Dll_InitPathList2('wx', open_list, NULL, NULL); +#endif Dll_PathListAnchor->win_classes_initialized = TRUE; } @@ -315,6 +504,119 @@ _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckO path_lwr[path_len + 1] = L'\0'; _wcslwr(path_lwr); +#ifdef USE_MATCH_PATH_EX + + //const WCHAR* curpat; + ULONG cur_level; + int cur_len; + int match_len; + ULONG level; + + BOOLEAN use_rule_specificity = (path_code == L'f' || path_code == L'k') && (Dll_ProcessFlags & SBIE_FLAG_RULE_SPECIFICITY) != 0; + + // + // set default behavioure + // + + level = 3; // 3 - global default - lower is better, 3 is max value + match_len = 0; + if ((path_code != L'f' && path_code != L'k') || (Dll_ProcessFlags & SBIE_FLAG_PRIVACY_MODE) == 0) { + + mp_flags = 0; // normal mode + } + else { + + mp_flags = PATH_WRITE_FLAG; // write path mode + } + + // + // ClosedXxxPath + // + + if (closed_list && path_len) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, closed_list, &cur_level, NULL);// &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + //if (patsrc) *patsrc = curpat; + + mp_flags = PATH_CLOSED_FLAG; + if (!use_rule_specificity) goto finish; + } + } + + // + // WriteXxxPath + // + + if (write_list && path_len) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, write_list, &cur_level, NULL);// &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + //if (patsrc) *patsrc = curpat; + + mp_flags = PATH_WRITE_FLAG; + if (!use_rule_specificity) goto finish; + } + } + + // + // ReadXxxPath + // + + if (read_list && path_len) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len,read_list, &cur_level, NULL);// &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + //if (patsrc) *patsrc = curpat; + + mp_flags = PATH_OPEN_FLAG; // say its open and let the driver deny the write access + if (!use_rule_specificity) goto finish; + } + } + + // + // NormalXxxPath + // + + if (normal_list && path_len) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, normal_list, &cur_level, NULL);// &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + //if (patsrc) *patsrc = curpat; + + mp_flags = 0; + if (!use_rule_specificity) goto finish; + } + } + + // + // OpenXxxPath + // + + if (open_list && path_len) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, open_list, &cur_level, NULL);// &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + //if (patsrc) *patsrc = curpat; + + mp_flags = PATH_OPEN_FLAG; + if (!use_rule_specificity) goto finish; + } + } + +finish: + +#else // // ClosedXxxPath // @@ -348,7 +650,7 @@ _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckO // WriteXxxPath - only if ClosedXxxPath matched // - if (write_list && mp_flags && path_len) { + if (write_list /*&& mp_flags*/ && path_len) { pat = List_Head(write_list); while (pat) { @@ -403,6 +705,7 @@ _FX ULONG SbieDll_MatchPath2(WCHAR path_code, const WCHAR *path, BOOLEAN bCheckO pat = List_Next(pat); } } +#endif if (path_code == L'f') LeaveCriticalSection(&Dll_FilePathListCritSec); @@ -463,21 +766,44 @@ _FX void Dll_RefreshPathList(void) if (SbieApi_Call(API_REFRESH_FILE_PATH_LIST, 0) == STATUS_SUCCESS) { +#ifdef USE_MATCH_PATH_EX + LIST normal_paths, open_paths, closed_paths, write_paths, read_paths; +#else LIST open_paths, closed_paths, write_paths; +#endif +#ifdef USE_MATCH_PATH_EX + List_Init(&normal_paths); +#endif List_Init(&open_paths); List_Init(&closed_paths); List_Init(&write_paths); +#ifdef USE_MATCH_PATH_EX + List_Init(&read_paths); +#endif +#ifdef USE_MATCH_PATH_EX + if (Dll_InitPathList2('fx', + &normal_paths, &open_paths, &closed_paths, &write_paths, &read_paths)) { +#else if (Dll_InitPathList2('fx', &open_paths, &closed_paths, &write_paths)) { +#endif +#ifdef USE_MATCH_PATH_EX + memcpy(&Dll_PathListAnchor->normal_file_path, &normal_paths, + sizeof(LIST)); +#endif memcpy(&Dll_PathListAnchor->open_file_path, &open_paths, sizeof(LIST)); memcpy(&Dll_PathListAnchor->closed_file_path, &closed_paths, sizeof(LIST)); memcpy(&Dll_PathListAnchor->write_file_path, &write_paths, sizeof(LIST)); +#ifdef USE_MATCH_PATH_EX + memcpy(&Dll_PathListAnchor->read_file_path, &read_paths, + sizeof(LIST)); +#endif Dll_PathListAnchor->file_paths_initialized = TRUE; } diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c index 8381eac1..5786b0d1 100644 --- a/Sandboxie/core/dll/file.c +++ b/Sandboxie/core/dll/file.c @@ -2498,7 +2498,22 @@ _FX NTSTATUS File_NtCreateFileImpl( if (status == STATUS_OBJECT_PATH_SYNTAX_BAD) { - SbieApi_MonitorPut2(MONITOR_PIPE | MONITOR_DENY, TruePath, FALSE); + // + // teh driver usually blocks this anyways so try only in app mode + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0){ + + SbieApi_MonitorPut2(MONITOR_PIPE, TruePath, FALSE); + + return __sys_NtCreateFile( + FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, + AllocationSize, FileAttributes, ShareAccess, CreateDisposition, + CreateOptions, EaBuffer, EaLength); + + } else { + SbieApi_MonitorPut2(MONITOR_PIPE | MONITOR_DENY, TruePath, FALSE); + } } } @@ -6964,4 +6979,4 @@ _FX BOOLEAN DigitalGuardian_Init(HMODULE hModule) Dll_DigitalGuardian = hModule; return TRUE; -} \ No newline at end of file +} diff --git a/Sandboxie/core/dll/file_dir.c b/Sandboxie/core/dll/file_dir.c index f8acf4f2..f5322d35 100644 --- a/Sandboxie/core/dll/file_dir.c +++ b/Sandboxie/core/dll/file_dir.c @@ -23,6 +23,7 @@ #include "common/pool.h" #include "common/map.h" +#include "common/pattern.h" //--------------------------------------------------------------------------- // Structures and Types @@ -150,6 +151,9 @@ static NTSTATUS File_MergeCacheWin2000( FILE_MERGE_FILE *qfile, UNICODE_STRING *FileMask, FILE_ID_BOTH_DIR_INFORMATION *info_area, ULONG info_area_len); +static NTSTATUS File_MergeDummy( + WCHAR *TruePath, FILE_MERGE_FILE *qfile, UNICODE_STRING *FileMask); + static void File_MergeFree(FILE_MERGE *merge); static NTSTATUS File_GetMergedInformation( @@ -339,10 +343,12 @@ _FX NTSTATUS File_NtQueryDirectoryFile( ULONG mp_flags = File_MatchPath(TruePath, &FileFlags); + BOOLEAN use_rule_specificity = (Dll_ProcessFlags & SBIE_FLAG_RULE_SPECIFICITY) != 0; + if (PATH_IS_CLOSED(mp_flags)) status = STATUS_ACCESS_DENIED; - else if (PATH_IS_WRITE(mp_flags)) + else if (PATH_IS_WRITE(mp_flags) && !use_rule_specificity) status = STATUS_BAD_INITIAL_PC; else if (PATH_IS_OPEN(mp_flags)) @@ -872,6 +878,25 @@ _FX NTSTATUS File_OpenForMerge( // for any other error opening the true directory, we abort. // + if (status == STATUS_OBJECT_NAME_NOT_FOUND || + status == STATUS_OBJECT_PATH_NOT_FOUND || + status == STATUS_ACCESS_DENIED) { + + BOOLEAN use_rule_specificity = (Dll_ProcessFlags & SBIE_FLAG_RULE_SPECIFICITY) != 0; + + // + // if rule specificity is enabled we may not have access to this true path + // but still have access to some sub paths, in this case instead of listing the + // true directory we parse the rule list and construst a cached dummy directory + // + + if (use_rule_specificity && File_MergeDummy(TruePath, merge->true_ptr, &merge->file_mask) == STATUS_SUCCESS) { + + merge->true_ptr->handle = NULL; + status = STATUS_SUCCESS; + } + } + if (!NT_SUCCESS(status)) { merge->true_ptr->handle = NULL; @@ -935,9 +960,16 @@ skip_true_file: ForceCache = TRUE; } - status = File_MergeCache( - merge->true_ptr, &merge->file_mask, ForceCache); + // + // true dir may be actually a dummy dir + // + if (merge->true_ptr->handle) { + + status = File_MergeCache( + merge->true_ptr, &merge->file_mask, ForceCache); + } + if (NT_SUCCESS(status)) { BOOLEAN HaveTrueCache = (merge->true_ptr->cache_pool != NULL); @@ -1276,6 +1308,181 @@ _FX NTSTATUS File_MergeCacheWin2000( } +//--------------------------------------------------------------------------- +// File_MergeDummy +//--------------------------------------------------------------------------- + + +_FX NTSTATUS File_MergeDummy( + WCHAR *TruePath, FILE_MERGE_FILE *qfile, UNICODE_STRING *FileMask) +{ + NTSTATUS status = STATUS_SUCCESS; + FILE_ID_BOTH_DIR_INFORMATION *info_area; + FILE_ID_BOTH_DIR_INFORMATION *info_ptr; + LIST *cache_list; + FILE_MERGE_CACHE_FILE *cache_file; + FILE_MERGE_CACHE_FILE *ins_point; + ULONG len; + const ULONG INFO_AREA_LEN = 0x10000; // the size used by cmd.exe + + + if (qfile->cache_pool) { + Pool_Delete(qfile->cache_pool); + qfile->cache_pool = NULL; + } + + // + // prepare the cache pool + // + + qfile->cache_pool = Pool_Create(); + if (! qfile->cache_pool) + return STATUS_INSUFFICIENT_RESOURCES; + + cache_list = &qfile->cache_list; + List_Init(cache_list); + + info_area = Pool_Alloc(qfile->cache_pool, INFO_AREA_LEN); + if (! info_area) + return STATUS_INSUFFICIENT_RESOURCES; + + // + // create a dummy directory, build a sorted files list + // + + PATTERN* mask = NULL; + if (FileMask->Buffer) + mask = Pattern_Create(qfile->cache_pool, FileMask->Buffer, TRUE, 0); + WCHAR test_buf[MAX_PATH]; + + LIST* lists[4]; + extern void SbieDll_GetReadablePaths(WCHAR path_code, const WCHAR *path, LIST **lists); + SbieDll_GetReadablePaths(L'f', TruePath, lists); + + ULONG TruePathLen = wcslen(TruePath); + if (TruePathLen > 1 && TruePath[TruePathLen - 1] == L'\\') + TruePathLen--; // never take last \ into account + + ULONG* PrevEntry = NULL; + info_ptr = info_area; + for (int i=0; lists[i] != NULL; i++) + { + + PATTERN* pat = List_Head(lists[i]); + while (pat) { + + const WCHAR* patstr = Pattern_Source(pat); + + if (_wcsnicmp(TruePath, patstr, TruePathLen) == 0 && patstr[TruePathLen] == L'\\'){ + + const WCHAR* ptr = &patstr[TruePathLen + 1]; + const WCHAR* end = wcschr(ptr, L'\\'); + if(end == NULL) end = wcschr(ptr, L'*'); + if(end == NULL) end = wcschr(ptr, L'\0'); + ULONG len = (ULONG)(end - ptr); + + if (mask) { + + memcpy(test_buf, ptr, (len + 1) * sizeof(WCHAR)); + _wcslwr(test_buf); + + if (!Pattern_Match(mask, test_buf, len)) + goto next; + } + + info_ptr->FileNameLength = len * sizeof(WCHAR); + memcpy(info_ptr->FileName, ptr, info_ptr->FileNameLength); + info_ptr->FileName[info_ptr->FileNameLength] = L'\0'; + + info_ptr->FileAttributes = FILE_ATTRIBUTE_DIRECTORY; + + PrevEntry = &info_ptr->NextEntryOffset; + info_ptr->NextEntryOffset = sizeof(FILE_ID_BOTH_DIR_INFORMATION) + info_ptr->FileNameLength + sizeof(WCHAR) + 16; // +16 some buffer space + info_ptr = (FILE_ID_BOTH_DIR_INFORMATION*) + ((UCHAR*)info_ptr + info_ptr->NextEntryOffset); + // todo: fix-me possible info_area buffer overflow!!!! + + } + + next: + pat = List_Next(pat); + } + } + + extern void SbieDll_ReleaseFilePathLock(); + SbieDll_ReleaseFilePathLock(); + + if(mask) + Pattern_Free(mask); + + if (PrevEntry == NULL) { + // no dummys created + status = STATUS_NO_MORE_ENTRIES; + goto finish; + } + *PrevEntry = 0; + + qfile->RestartScan = FALSE; + + info_ptr = info_area; + while (1) { + int cmp; + + len = sizeof(FILE_MERGE_CACHE_FILE) + + info_ptr->FileNameLength; + + cache_file = Pool_Alloc(qfile->cache_pool, len); + if (! cache_file) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + len = sizeof(FILE_ID_BOTH_DIR_INFORMATION) + - sizeof(WCHAR) // the [1] from FileName[1] + + info_ptr->FileNameLength; + memcpy(&cache_file->info, info_ptr, len); + cache_file->info.NextEntryOffset = 0; + cache_file->info_len = len; + + cache_file->name_uni.Length = (USHORT)info_ptr->FileNameLength; + cache_file->name_uni.MaximumLength = cache_file->name_uni.Length; + cache_file->name_uni.Buffer = cache_file->info.FileName; + + // insert file into the ordered list + + ins_point = List_Head(cache_list); + cmp = -1; + while (ins_point) { + cmp = RtlCompareUnicodeString( + &ins_point->name_uni, &cache_file->name_uni, + TRUE); // CaseInSensitive + if ( (cmp > 0) || (cmp == 0) ) + break; + ins_point = List_Next(ins_point); + } + + if (cmp != 0) { // skip duplicates + + if (ins_point) + List_Insert_Before(cache_list, ins_point, cache_file); + else + List_Insert_After(cache_list, NULL, cache_file); + } + + if (info_ptr->NextEntryOffset == 0) + break; + info_ptr = (FILE_ID_BOTH_DIR_INFORMATION *) + ((UCHAR *)info_ptr + info_ptr->NextEntryOffset); + } + +finish: + + Pool_Free(info_area, INFO_AREA_LEN); + + return status; +} + + //--------------------------------------------------------------------------- // File_MergeFree //--------------------------------------------------------------------------- @@ -3569,6 +3776,7 @@ _FX void File_DoAutoRecover_2(BOOLEAN force, ULONG ticks) break; } + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0) // don't try that in app mode, we had a proepr token if (status == STATUS_ACCESS_DENIED) { // diff --git a/Sandboxie/core/dll/file_pipe.c b/Sandboxie/core/dll/file_pipe.c index a1e8a977..c5cd11a9 100644 --- a/Sandboxie/core/dll/file_pipe.c +++ b/Sandboxie/core/dll/file_pipe.c @@ -496,7 +496,7 @@ _FX NTSTATUS File_NtCreateNamedPipeFile( InitializeObjectAttributes(&objattrs, &objname, OBJECT_ATTRIBUTES_ATTRIBUTES, NULL, NULL); - mp_flags = File_MatchPath(TruePath, NULL); + mp_flags = File_MatchPath2(TruePath, NULL, FALSE, TRUE); // File_MatchPath(TruePath, NULL); if (PATH_IS_CLOSED(mp_flags)) { status = STATUS_ACCESS_DENIED; @@ -622,6 +622,7 @@ _FX NTSTATUS File_NtCreateFilePipe( // SbieSvc::NamedPipeServer::OpenHandler // + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0) // don't do that in app mode if (PipeType == TYPE_NAMED_PIPE) { name = wcsrchr(TruePath, L'\\'); diff --git a/Sandboxie/core/dll/gdi.c b/Sandboxie/core/dll/gdi.c index ee75e2b2..b37b1268 100644 --- a/Sandboxie/core/dll/gdi.c +++ b/Sandboxie/core/dll/gdi.c @@ -212,7 +212,7 @@ _FX ULONG_PTR Gdi_GdiDllInitialize_Common( // // NoSbieDesk BEGIN - if(!SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) + if((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) // NoSbieDesk END if (! _Initialized) { @@ -276,7 +276,7 @@ _FX void Gdi_SplWow64(BOOLEAN Register) // // NoSbieDesk BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) return; // NoSbieDesk END diff --git a/Sandboxie/core/dll/gui.c b/Sandboxie/core/dll/gui.c index d57ad8f9..16b21d9b 100644 --- a/Sandboxie/core/dll/gui.c +++ b/Sandboxie/core/dll/gui.c @@ -364,7 +364,14 @@ _FX BOOLEAN Gui_Init(HMODULE module) return FALSE; // NoSbieDesk BEGIN - Gui_UseProxyService = !SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE); + + // + // Sandboxie is routing many gui related things through teh service, + // when we operate in app mode we dont need to do that hence + // disable the use of the gui proxy + // + + Gui_UseProxyService = (Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE); // NoSbieDesk END GUI_IMPORT___(GetWindowThreadProcessId); @@ -409,7 +416,7 @@ _FX BOOLEAN Gui_Init(HMODULE module) GUI_IMPORT___(ExitWindowsEx); GUI_IMPORT___(EndTask); // NoSbieCons BEGIN - if (!SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) // NoSbieCons END if (Dll_OsBuild >= 8400) { GUI_IMPORT___(ConsoleControl); @@ -568,7 +575,7 @@ _FX BOOLEAN Gui_Init2(void) SBIEDLL_HOOK_GUI(ExitWindowsEx); SBIEDLL_HOOK_GUI(EndTask); // NoSbieCons BEGIN - if (!SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) // NoSbieCons END if (__sys_ConsoleControl) { SBIEDLL_HOOK_GUI(ConsoleControl); @@ -823,7 +830,7 @@ _FX BOOLEAN Gui_ConnectToWindowStationAndDesktop(HMODULE User32) ULONG errlvl = 0; // NoSbieDesk BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) return TRUE; // NoSbieDesk END @@ -989,7 +996,7 @@ _FX BOOLEAN Gui_ConnectToWindowStationAndDesktop(HMODULE User32) rc = (ULONG_PTR)NtCurrentThread(); // OriginalToken BEGIN - if (SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) rc = 0; else // OriginalToken END @@ -2647,4 +2654,4 @@ _FX BOOLEAN ComDlg32_Init(HMODULE hModule) //} return TRUE; -} \ No newline at end of file +} diff --git a/Sandboxie/core/dll/guicon.c b/Sandboxie/core/dll/guicon.c index 127eea54..857d1871 100644 --- a/Sandboxie/core/dll/guicon.c +++ b/Sandboxie/core/dll/guicon.c @@ -80,7 +80,7 @@ static P_GetMessage __sys_GetMessageW = NULL; _FX BOOLEAN Gui_InitConsole1(void) { // NoSbieCons BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) { + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSandboxieConsole", FALSE)) { // // We need to set Gui_ConsoleHwnd in order for Gui_InitConsole2 to start up properly, @@ -112,7 +112,7 @@ _FX BOOLEAN Gui_InitConsole1(void) // application which has used Gui_SetWindowsHookEx before creating // any windows (which would be needed to apply the hooks) // - + Gui_ConsoleHwnd = GetConsoleWindow(); if (! Gui_ConsoleHwnd) { diff --git a/Sandboxie/core/dll/guimisc.c b/Sandboxie/core/dll/guimisc.c index 02de896f..7622d90d 100644 --- a/Sandboxie/core/dll/guimisc.c +++ b/Sandboxie/core/dll/guimisc.c @@ -1316,7 +1316,7 @@ static P_ImmCreateContext __sys_ImmCreateContext = NULL; _FX BOOLEAN Gui_Init_IMM32(HMODULE module) { // NoSbieDesk BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) return TRUE; // NoSbieDesk END diff --git a/Sandboxie/core/dll/ipc.c b/Sandboxie/core/dll/ipc.c index b1f43ac2..a7070e24 100644 --- a/Sandboxie/core/dll/ipc.c +++ b/Sandboxie/core/dll/ipc.c @@ -343,8 +343,13 @@ _FX BOOLEAN Ipc_Init(void) SBIEDLL_HOOK_IF(NtAlpcQueryInformation); SBIEDLL_HOOK_IF(NtAlpcQueryInformationMessage); - SBIEDLL_HOOK(Ipc_,NtImpersonateClientOfPort); - SBIEDLL_HOOK_IF(NtAlpcImpersonateClientOfPort); + // OriginalToken BEGIN + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + // OriginalToken END + { + SBIEDLL_HOOK(Ipc_, NtImpersonateClientOfPort); + SBIEDLL_HOOK_IF(NtAlpcImpersonateClientOfPort); + } SBIEDLL_HOOK(Ipc_,NtRequestWaitReplyPort); SBIEDLL_HOOK_IF(NtAlpcSendWaitReceivePort); @@ -366,8 +371,13 @@ _FX BOOLEAN Ipc_Init(void) SBIEDLL_HOOK(Ipc_,NtCreateSection); SBIEDLL_HOOK(Ipc_,NtOpenSection); - SBIEDLL_HOOK(Ipc_,NtImpersonateAnonymousToken); - SBIEDLL_HOOK(Ipc_,NtImpersonateThread); + // OriginalToken BEGIN + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + // OriginalToken END + { + SBIEDLL_HOOK(Ipc_, NtImpersonateAnonymousToken); + SBIEDLL_HOOK(Ipc_, NtImpersonateThread); + } Ipc_CreateObjects(); @@ -724,7 +734,7 @@ _FX BOOLEAN Ipc_GetName_AdjustSplWow64Path(WCHAR *TruePath, BOOLEAN adj) // // NoSbieDesk BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) return TRUE; // NoSbieDesk END @@ -1143,6 +1153,8 @@ _FX NTSTATUS Ipc_NtConnectPort( if (status != STATUS_BAD_INITIAL_PC) __leave; + if (status == STATUS_BAD_INITIAL_STACK) + goto OpenTruePath; // // if trying to connect to a COM port, start our COM servers first @@ -1269,6 +1281,8 @@ _FX NTSTATUS Ipc_NtSecureConnectPort( if (status != STATUS_BAD_INITIAL_PC) __leave; + if (status == STATUS_BAD_INITIAL_STACK) + goto OpenTruePath; // // if trying to connect to a COM port, start our COM servers first @@ -1519,6 +1533,8 @@ _FX NTSTATUS Ipc_NtAlpcConnectPort( if (status != STATUS_BAD_INITIAL_PC) __leave; + if (status == STATUS_BAD_INITIAL_STACK) + goto OpenTruePath; // // if trying to connect to a COM port, start our COM servers first @@ -1693,6 +1709,8 @@ _FX NTSTATUS Ipc_NtAlpcConnectPortEx( if (status != STATUS_BAD_INITIAL_PC) __leave; + if (status == STATUS_BAD_INITIAL_STACK) + goto OpenTruePath; // // if trying to connect to a COM port, start our COM servers first @@ -3235,6 +3253,13 @@ _FX NTSTATUS Ipc_ConnectProxyPort( _wcsicmp(TruePath, L"\\RPC Control\\plugplay") != 0) return STATUS_BAD_INITIAL_PC; + // + // check if we are in app mode in which case proxying is not needed, but we must indicate to open true path + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0) + return STATUS_BAD_INITIAL_STACK; + status = STATUS_SUCCESS; // diff --git a/Sandboxie/core/dll/iphlp.c b/Sandboxie/core/dll/iphlp.c index c73d1416..8b3c4939 100644 --- a/Sandboxie/core/dll/iphlp.c +++ b/Sandboxie/core/dll/iphlp.c @@ -190,7 +190,7 @@ _FX BOOLEAN IpHlp_Init(HMODULE module) void *NotifyRouteChange2; void *CancelMibChangeNotify2; - if (Dll_OsBuild < 6000) { + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || Dll_OsBuild < 6000) { // in compartment mode we have a full token so no need to hook anythign here // // earlier than Windows Vista, don't hook diff --git a/Sandboxie/core/dll/key.c b/Sandboxie/core/dll/key.c index ef733894..e15bac6b 100644 --- a/Sandboxie/core/dll/key.c +++ b/Sandboxie/core/dll/key.c @@ -773,6 +773,12 @@ _FX NTSTATUS Key_FixNameWow64( if (! (DesiredAccess & KEY_WOW64_32KEY)) return STATUS_SUCCESS; + // ToDo: ??? + // NoSysCallHooks BEGIN + //if((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) + // return STATUS_SUCCESS; + // NoSysCallHooks END + return Key_FixNameWow64_2(OutTruePath, OutCopyPath); } @@ -4280,3 +4286,36 @@ _FX ULONG Key_NtQueryObjectName(UNICODE_STRING *ObjectName, ULONG MaxLen) return 0; } + + +//--------------------------------------------------------------------------- +// Key_CreateBaseKeys +//--------------------------------------------------------------------------- + + +_FX void Key_CreateBaseKeys() +{ + WCHAR buff[2048]; + OBJECT_ATTRIBUTES objattrs; + UNICODE_STRING objname; + WCHAR* base_keys[] = { + L"\\machine\\system", L"\\machine\\software", + L"\\user\\current\\software", L"\\user\\current_Classes", NULL}; + + // + // in privacy mode we need to pre create some keys or else the box initialization will fail + // + + InitializeObjectAttributes( + &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL); + + for (WCHAR** base_key = base_keys; *base_key; base_key++) { + + wcscpy(buff, Dll_BoxKeyPath); + wcscat(buff, *base_key); + + RtlInitUnicodeString(&objname, buff); + + Key_CreatePath(&objattrs, NULL); + } +} \ No newline at end of file diff --git a/Sandboxie/core/dll/netapi.c b/Sandboxie/core/dll/netapi.c index a0927ad7..ac47c57d 100644 --- a/Sandboxie/core/dll/netapi.c +++ b/Sandboxie/core/dll/netapi.c @@ -201,6 +201,13 @@ _FX BOOLEAN NetApi_Hook_NetUseAdd(HMODULE module) if (PATH_IS_CLOSED(mp_flags)) return TRUE; } + + // + // In in app mode we have a full token and this wil be successfull, hence no need for a hook + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0) + return TRUE; // // otherwise hook NetUseAdd diff --git a/Sandboxie/core/dll/proc.c b/Sandboxie/core/dll/proc.c index f3671bfd..0364defe 100644 --- a/Sandboxie/core/dll/proc.c +++ b/Sandboxie/core/dll/proc.c @@ -883,13 +883,19 @@ _FX BOOL Proc_CreateProcessInternalW( lpApplicationName = TlsData->proc_image_path; } + // const wchar_t* imageName = L"DcomLaunch.exe"; + // if ((lpApplicationName && wcsstr(lpApplicationName,imageName) != NULL) || (lpCommandLine && wcsstr(lpCommandLine,imageName) != NULL)) { + // while (!IsDebuggerPresent()) + // Sleep(500); + // __debugbreak(); + //} // // create the new process // // OriginalToken BEGIN - if (SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) { extern BOOLEAN Scm_MsiServer_Systemless; if (Dll_ImageType == DLL_IMAGE_MSI_INSTALLER && Scm_MsiServer_Systemless diff --git a/Sandboxie/core/dll/pst.cpp b/Sandboxie/core/dll/pst.cpp index f69da1ee..fe2b8cf6 100644 --- a/Sandboxie/core/dll/pst.cpp +++ b/Sandboxie/core/dll/pst.cpp @@ -89,6 +89,13 @@ extern "C" _FX BOOLEAN Pst_Init(HMODULE module) if (SbieApi_QueryConfBool(NULL, Pst_OpenProtectedStorage, FALSE)) return TRUE; + // + // in app mode we dont need these hooks as we have a full token + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0) + return TRUE; + // // hook Protected Storage entry point // diff --git a/Sandboxie/core/dll/rpcrt.c b/Sandboxie/core/dll/rpcrt.c index ece03f7b..d015947b 100644 --- a/Sandboxie/core/dll/rpcrt.c +++ b/Sandboxie/core/dll/rpcrt.c @@ -673,6 +673,10 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW( WCHAR wstrPortName[MAX_PATH]; memset(wstrPortName, 0, sizeof(wstrPortName)); + /*if (wcsstr(StringBinding, L"epmapper") != NULL) { + __debugbreak(); + }*/ + static const WCHAR* dynamicFalse = L"ncalrpc:[,Security=Impersonation Dynamic False]"; //static const WCHAR* dynamicTrue = L"ncalrpc:[,Security=Impersonation Dynamic True]"; diff --git a/Sandboxie/core/dll/sbieapi.c b/Sandboxie/core/dll/sbieapi.c index 7f7ab576..73f6cfc4 100644 --- a/Sandboxie/core/dll/sbieapi.c +++ b/Sandboxie/core/dll/sbieapi.c @@ -758,7 +758,8 @@ _FX LONG SbieApi_QueryPathList( ULONG path_code, ULONG *path_len, WCHAR *path_str, - HANDLE process_id) + HANDLE process_id, + BOOLEAN prepend_level) { NTSTATUS status; __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; @@ -770,6 +771,7 @@ _FX LONG SbieApi_QueryPathList( args->path_len.val64 = (ULONG64)(ULONG_PTR)path_len; args->path_str.val64 = (ULONG64)(ULONG_PTR)path_str; args->process_id.val64 = (ULONG64)(ULONG_PTR)process_id; + args->prepend_level.val = prepend_level; status = SbieApi_Ioctl(parms); return status; diff --git a/Sandboxie/core/dll/sbieapi.h b/Sandboxie/core/dll/sbieapi.h index f4b5c7b7..859c0563 100644 --- a/Sandboxie/core/dll/sbieapi.h +++ b/Sandboxie/core/dll/sbieapi.h @@ -156,7 +156,8 @@ LONG SbieApi_QueryPathList( ULONG path_code, ULONG *path_len, WCHAR *path_str, - HANDLE process_id); + HANDLE process_id, + BOOLEAN prepend_level); SBIEAPI_EXPORT LONG SbieApi_EnumProcessEx( @@ -249,7 +250,7 @@ LONG SbieApi_CheckInternetAccess( const WCHAR *DeviceName32, BOOLEAN IssueMessage); -//SBIEAPI_EXPORT +SBIEAPI_EXPORT LONG SbieApi_GetBlockedDll( WCHAR *DllNameBuf, ULONG DllNameLen); diff --git a/Sandboxie/core/dll/scm_msi.c b/Sandboxie/core/dll/scm_msi.c index 1ff3b216..e8abab88 100644 --- a/Sandboxie/core/dll/scm_msi.c +++ b/Sandboxie/core/dll/scm_msi.c @@ -51,6 +51,13 @@ static BOOL Scm_OpenProcessToken( _Outptr_ PHANDLE TokenHandle ); +static BOOL Scm_OpenThreadToken( + _In_ HANDLE ThreadHandle, + _In_ DWORD DesiredAccess, + _In_ BOOL OpenAsSelf, + _Outptr_ PHANDLE TokenHandle + ); + static BOOL Scm_GetTokenInformation( _In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, @@ -74,6 +81,13 @@ typedef BOOL (*P_OpenProcessToken)( _Outptr_ PHANDLE TokenHandle ); +typedef BOOL (*P_OpenThreadToken)( + _In_ HANDLE ThreadHandle, + _In_ DWORD DesiredAccess, + _In_ BOOL OpenAsSelf, + _Outptr_ PHANDLE TokenHandle + ); + typedef BOOL (*P_GetTokenInformation)( _In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, @@ -90,6 +104,7 @@ typedef BOOL (*P_GetTokenInformation)( static P_CreateWaitableTimerW __sys_CreateWaitableTimerW = NULL; static P_OpenProcessToken __sys_OpenProcessToken = NULL; +static P_OpenThreadToken __sys_OpenThreadToken = NULL; static P_GetTokenInformation __sys_GetTokenInformation = NULL; @@ -163,6 +178,10 @@ _FX BOOLEAN Scm_SetupMsiHooks() void* OpenProcessToken = (P_OpenProcessToken)GetProcAddress(hAdvapi32, "OpenProcessToken"); SBIEDLL_HOOK(Scm_, OpenProcessToken); + //void* OpenThreadToken = (P_OpenThreadToken)GetProcAddress(hAdvapi32, "OpenThreadToken"); + //SBIEDLL_HOOK(Scm_, OpenThreadToken); + + void* GetTokenInformation = (P_GetTokenInformation)GetProcAddress(hAdvapi32, "GetTokenInformation"); SBIEDLL_HOOK(Scm_, GetTokenInformation); } @@ -226,6 +245,27 @@ _FX BOOL Scm_OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE } +//--------------------------------------------------------------------------- +// Scm_OpenThreadToken +//--------------------------------------------------------------------------- + + +_FX BOOL Scm_OpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE phTokenOut) +{ + THREAD_DATA *TlsData = Dll_GetTlsData(NULL); + + NTSTATUS status = __sys_OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, phTokenOut); + + if (NT_SUCCESS(status) && ThreadHandle == GetCurrentThread()) { + + File_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler); + TlsData->scm_last_own_token = *phTokenOut; + } + + return status; +} + + //--------------------------------------------------------------------------- // Scm_GetTokenInformation //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/secure.c b/Sandboxie/core/dll/secure.c index 72d74e7a..08647ee3 100644 --- a/Sandboxie/core/dll/secure.c +++ b/Sandboxie/core/dll/secure.c @@ -359,7 +359,7 @@ _FX BOOLEAN Secure_Init(void) // // intercept NTDLL entry points // - if (!SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) { + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE)) { SBIEDLL_HOOK(Secure_, NtOpenProcess); SBIEDLL_HOOK(Secure_, NtOpenThread); SBIEDLL_HOOK(Secure_, NtDuplicateObject); @@ -369,7 +369,7 @@ _FX BOOLEAN Secure_Init(void) SBIEDLL_HOOK(Secure_,NtSetInformationToken); SBIEDLL_HOOK(Secure_,NtAdjustPrivilegesToken); // OriginalToken BEGIN - if (!SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) == 0 && !SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) // OriginalToken END if (Dll_OsBuild >= 21286) { // Windows 11 SBIEDLL_HOOK(Secure_, NtDuplicateToken); @@ -893,7 +893,7 @@ _FX void Ldr_TestToken(HANDLE token, PHANDLE hTokenReal) return; // OriginalToken BEGIN - if (SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"OriginalToken", FALSE)) return; // OriginalToken END diff --git a/Sandboxie/core/dll/terminal.c b/Sandboxie/core/dll/terminal.c index 76b0379e..f41c2de7 100644 --- a/Sandboxie/core/dll/terminal.c +++ b/Sandboxie/core/dll/terminal.c @@ -232,6 +232,12 @@ extern const WCHAR *Ipc_SandboxieRpcSs; _FX BOOLEAN Terminal_DontHook(void) { + // + // In in app mode we have a full token and this wil be successfull, hence no need for a hook + // + + if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0) + return TRUE; // // On win 10 this endpoint does not exist, so hook always diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj b/Sandboxie/core/drv/SboxDrv.vcxproj index 58fca4bf..13e7c7c4 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj +++ b/Sandboxie/core/drv/SboxDrv.vcxproj @@ -21,7 +21,7 @@ Win32Proj {4019C5EB-8D1E-40E4-B7D1-5601B4B27288} - $(LatestTargetPlatformVersion) + 10.0.19041.0 @@ -110,10 +110,11 @@ POOL_NX_OPTIN=1;%(PreprocessorDefinitions) true + false Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;ntstrsafe.lib;%(AdditionalDependencies) DriverEntry @@ -126,9 +127,6 @@ false false - - SHA256 - @@ -148,7 +146,7 @@ Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;ntstrsafe.lib;%(AdditionalDependencies) DriverEntry @@ -171,9 +169,6 @@ false false - - SHA256 - @@ -204,9 +199,6 @@ false false - - SHA256 - @@ -247,9 +239,6 @@ false false - - SHA256 - @@ -259,6 +248,12 @@ + + true + true + true + true + true true @@ -351,14 +346,20 @@ true true + true + true true true + true + true true true + true + true @@ -402,6 +403,8 @@ true true + true + true @@ -426,6 +429,12 @@ true true + + true + true + true + true + true @@ -488,7 +497,12 @@ - + + true + true + true + true + @@ -511,4 +525,4 @@ - + \ No newline at end of file diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj.filters b/Sandboxie/core/drv/SboxDrv.vcxproj.filters index 722c25ea..9b55f882 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj.filters +++ b/Sandboxie/core/drv/SboxDrv.vcxproj.filters @@ -6,7 +6,6 @@ - @@ -148,6 +147,15 @@ obj + + common + + + syscall + + + syscall + @@ -155,7 +163,6 @@ - @@ -228,6 +235,9 @@ obj + + syscall + diff --git a/Sandboxie/core/drv/api.c b/Sandboxie/core/drv/api.c index 819af719..e5421328 100644 --- a/Sandboxie/core/drv/api.c +++ b/Sandboxie/core/drv/api.c @@ -1293,13 +1293,27 @@ _FX NTSTATUS Api_QueryDriverInfo(PROCESS* proc, ULONG64* parms) if (WFP_Enabled) FeatureFlags |= SBIE_FEATURE_FLAG_WFP; + extern BOOLEAN Obj_CallbackInstalled; + if (Obj_CallbackInstalled) + FeatureFlags |= SBIE_FEATURE_FLAG_OB_CALLBACKS; + extern UCHAR SandboxieLogonSid[SECURITY_MAX_SID_SIZE]; if (SandboxieLogonSid[0] != 0) FeatureFlags |= SBIE_FEATURE_FLAG_SBIE_LOGIN; - if (Driver_Certified) +#ifdef HOOK_WIN32K + extern ULONG Syscall_MaxIndex32; + if (Syscall_MaxIndex32 != 0) + FeatureFlags |= SBIE_FEATURE_FLAG_WIN32K_HOOK; +#endif + + if (Driver_Certified) { + FeatureFlags |= SBIE_FEATURE_FLAG_CERTIFIED; + FeatureFlags |= SBIE_FEATURE_FLAG_PRIVACY_MODE; + FeatureFlags |= SBIE_FEATURE_FLAG_COMPARTMENTS; + } *data = FeatureFlags; } diff --git a/Sandboxie/core/drv/api_defs.h b/Sandboxie/core/drv/api_defs.h index 1bea859e..46c6ab90 100644 --- a/Sandboxie/core/drv/api_defs.h +++ b/Sandboxie/core/drv/api_defs.h @@ -265,6 +265,7 @@ API_ARGS_FIELD(ULONG,path_code) API_ARGS_FIELD(ULONG *,path_len) API_ARGS_FIELD(WCHAR *,path_str) API_ARGS_FIELD(HANDLE,process_id) +API_ARGS_FIELD(BOOLEAN,prepend_level) API_ARGS_CLOSE(API_QUERY_PATH_LIST_ARGS) diff --git a/Sandboxie/core/drv/api_flags.h b/Sandboxie/core/drv/api_flags.h index e6f5d570..41bfa480 100644 --- a/Sandboxie/core/drv/api_flags.h +++ b/Sandboxie/core/drv/api_flags.h @@ -121,7 +121,12 @@ #define SBIE_FEATURE_FLAG_WFP 0x00000001 +#define SBIE_FEATURE_FLAG_OB_CALLBACKS 0x00000002 +#define SBIE_FEATURE_FLAG_PRIVACY_MODE 0x00000004 +#define SBIE_FEATURE_FLAG_COMPARTMENTS 0x00000008 #define SBIE_FEATURE_FLAG_SBIE_LOGIN 0x00000010 +#define SBIE_FEATURE_FLAG_WIN32K_HOOK 0x00000020 + #define SBIE_FEATURE_FLAG_CERTIFIED 0x80000000 //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/conf.c b/Sandboxie/core/drv/conf.c index 6f34729e..b82f2389 100644 --- a/Sandboxie/core/drv/conf.c +++ b/Sandboxie/core/drv/conf.c @@ -1472,6 +1472,17 @@ _FX NTSTATUS Conf_Api_Reload(PROCESS *proc, ULONG64 *parms) } } + BOOLEAN obj_filter_enabled = Conf_Get_Boolean(NULL, L"EnableObjectFiltering", 0, FALSE); + extern BOOLEAN Obj_CallbackInstalled; + if (Obj_CallbackInstalled != obj_filter_enabled && Driver_OsVersion > DRIVER_WINDOWS_VISTA) { + if (obj_filter_enabled) { + Obj_Load_Filter(); + } + else { + Obj_Unload_Filter(); + } + } + extern UCHAR SandboxieLogonSid[SECURITY_MAX_SID_SIZE]; if (Conf_Get_Boolean(NULL, L"AllowSandboxieLogon", 0, FALSE) && SandboxieLogonSid[0] == 0) { extern BOOLEAN Token_Init_SbieLogin(void); diff --git a/Sandboxie/core/drv/driver.h b/Sandboxie/core/drv/driver.h index 9d857627..aa80e43c 100644 --- a/Sandboxie/core/drv/driver.h +++ b/Sandboxie/core/drv/driver.h @@ -69,6 +69,8 @@ #define USE_PROCESS_MAP +#define USE_MATCH_PATH_EX + //new FILE_INFORMATION_CLASS type not defined in current wdm.h used in windows 10 FCU #define SB_FileRenameInformationEx 65 //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/file.c b/Sandboxie/core/drv/file.c index 6b4c8e4f..e9245293 100644 --- a/Sandboxie/core/drv/file.c +++ b/Sandboxie/core/drv/file.c @@ -86,6 +86,9 @@ static void File_CreateBoxPath_2(HANDLE FileHandle); static void File_AdjustBoxFilePath(PROCESS *proc, HANDLE handle); static BOOLEAN File_InitPaths(PROCESS *proc, +#ifdef USE_MATCH_PATH_EX + LIST *normal_file_paths, +#endif LIST *open_file_paths, LIST *closed_file_paths, LIST *read_file_paths, LIST *write_file_paths); @@ -559,15 +562,30 @@ _FX void File_AdjustBoxFilePath(PROCESS *proc, HANDLE handle) _FX BOOLEAN File_InitPaths(PROCESS *proc, +#ifdef USE_MATCH_PATH_EX + LIST *normal_file_paths, +#endif LIST *open_file_paths, LIST *closed_file_paths, LIST *read_file_paths, LIST *write_file_paths) { static const WCHAR *_PstPipe = L"\\Device\\NamedPipe\\protected_storage"; +#ifdef USE_MATCH_PATH_EX + static const WCHAR *_NormalPath = L"NormalFilePath"; +#endif static const WCHAR *_OpenFile = L"OpenFilePath"; static const WCHAR *_OpenPipe = L"OpenPipePath"; static const WCHAR *_ClosedPath = L"ClosedFilePath"; static const WCHAR *_ReadPath = L"ReadFilePath"; static const WCHAR *_WritePath = L"WriteFilePath"; +#ifdef USE_MATCH_PATH_EX + static const WCHAR *normalpaths[] = { + L"%SystemRoot%\\*", + L"%SbieHome%\\*", + L"%ProgramFiles%\\*", + L"%ProgramFiles% (x86)\\*", + NULL + }; +#endif static const WCHAR *openpipes[] = { L"\\Device\\NamedPipe\\", // named pipe root L"\\Device\\MailSlot\\", // mail slot root @@ -637,6 +655,28 @@ _FX BOOLEAN File_InitPaths(PROCESS *proc, BOOLEAN ok; ULONG i; +#ifdef USE_MATCH_PATH_EX + + // + // normal paths + // + + ok = Process_GetPaths(proc, normal_file_paths, _NormalPath, TRUE); + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + return FALSE; + } + + for (i = 0; normalpaths[i] && ok; ++i) { + ok = Process_AddPath(proc, normal_file_paths, _NormalPath, TRUE, normalpaths[i], FALSE); + } + + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + return FALSE; + } +#endif + // // open paths // @@ -647,7 +687,7 @@ _FX BOOLEAN File_InitPaths(PROCESS *proc, return FALSE; } - if (! proc->image_from_box) { + if (! proc->dont_open_for_boxed || ! proc->image_from_box) { ok = Process_GetPaths(proc, open_file_paths, _OpenFile, TRUE); @@ -703,8 +743,10 @@ _FX BOOLEAN File_InitPaths(PROCESS *proc, // read-only paths (stored also as open paths) // +#ifndef USE_MATCH_PATH_EX ok = Process_GetPaths(proc, open_file_paths, _ReadPath, TRUE); if (ok) +#endif ok = Process_GetPaths(proc, read_file_paths, _ReadPath, TRUE); if (! ok) { Log_MsgP1(MSG_INIT_PATHS, _ReadPath, proc->pid); @@ -715,6 +757,9 @@ _FX BOOLEAN File_InitPaths(PROCESS *proc, // write-only paths (stored also as closed paths) // +#ifdef USE_MATCH_PATH_EX + ok = Process_GetPaths(proc, write_file_paths, _WritePath, TRUE); +#else ok = Process_GetPaths2( proc, write_file_paths, closed_file_paths, _WritePath, TRUE); @@ -722,6 +767,7 @@ _FX BOOLEAN File_InitPaths(PROCESS *proc, ok = Process_GetPaths( proc, closed_file_paths, _WritePath, TRUE); } +#endif if (! ok) { Log_MsgP1(MSG_INIT_PATHS, _WritePath, proc->pid); return FALSE; @@ -877,14 +923,11 @@ _FX BOOLEAN File_BlockInternetAccess2( _FX BOOLEAN File_InitProcess(PROCESS *proc) { - // - // by default, Close[...]=!,path includes all boxed images - // use AlwaysCloseInBox=n to disable this behaviour - // - - proc->always_close_for_boxed = Conf_Get_Boolean(proc->box->name, L"AlwaysCloseForBoxed", 0, TRUE); - - BOOLEAN ok = File_InitPaths(proc, &proc->open_file_paths, + BOOLEAN ok = File_InitPaths(proc, +#ifdef USE_MATCH_PATH_EX + &proc->normal_file_paths, +#endif + &proc->open_file_paths, &proc->closed_file_paths, &proc->read_file_paths, &proc->write_file_paths); @@ -894,15 +937,9 @@ _FX BOOLEAN File_InitProcess(PROCESS *proc) if (ok) ok = WFP_UpdateProcess(proc); - if (ok) { - - // - // check if should we warn on direct access to disk devices - // - - proc->file_warn_direct_access = Conf_Get_Boolean( - proc->box->name, L"NotifyDirectDiskAccess", 0, FALSE); - } + proc->file_block_network_files = Conf_Get_Boolean(proc->box->name, L"BlockNetworkFiles", 0, FALSE); + + proc->file_warn_direct_access = Conf_Get_Boolean(proc->box->name, L"NotifyDirectDiskAccess", 0, FALSE); proc->file_open_devapi_cmapi = Conf_Get_Boolean(proc->box->name, L"OpenDevCMApi", 0, FALSE); @@ -912,6 +949,14 @@ _FX BOOLEAN File_InitProcess(PROCESS *proc) // make sure the image path does not match a ClosedFilePath setting // +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags = Process_MatchPathEx(proc, proc->image_path, wcslen(proc->image_path), L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); + + if ((mp_flags & (proc->image_from_box ? COPY_PATH_READ_FLAG : TRUE_PATH_READ_FLAG)) == 0) + ok = FALSE; +#else BOOLEAN is_open, is_closed; Process_MatchPath( proc->pool, proc->image_path, wcslen(proc->image_path), @@ -920,6 +965,7 @@ _FX BOOLEAN File_InitProcess(PROCESS *proc) if (is_closed) ok = FALSE; +#endif } return ok; @@ -1202,8 +1248,12 @@ _FX NTSTATUS File_Generic_MyParseProc( // allow/deny access to paths outside the sandbox // +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags; +#else LIST *open_file_paths; BOOLEAN is_open, is_closed; +#endif WCHAR *path = Name->Name.Buffer; ULONG path_len = Name->Name.Length / sizeof(WCHAR); @@ -1268,6 +1318,13 @@ _FX NTSTATUS File_Generic_MyParseProc( // and this is a write access // +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, path, path_len, L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); + + if ((!write_access || (mp_flags & TRUE_PATH_WRITE_FLAG) != 0) && ((mp_flags & TRUE_PATH_MASK) != 0)) { +#else if (write_access) open_file_paths = &proc->open_file_paths; else @@ -1279,18 +1336,19 @@ _FX NTSTATUS File_Generic_MyParseProc( &is_open, &is_closed); if ((! is_open) && (! is_closed)) { +#endif - // - // if we have a path that looks like any of these - // \Device\LanmanRedirector\server\shr\f1.txt - // \Device\LanmanRedirector\;Q:000000000000b09f\server\shr\f1.txt - // \Device\Mup\;LanmanRedirector\server\share\f1.txt - // \Device\Mup\;LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt - // then translate to - // \Device\Mup\server\shr\f1.txt - // and test again. We do this because open/closed paths are - // recorded in the \Device\Mup format. See File_TranslateShares. - // + // + // if we have a path that looks like any of these + // \Device\LanmanRedirector\server\shr\f1.txt + // \Device\LanmanRedirector\;Q:000000000000b09f\server\shr\f1.txt + // \Device\Mup\;LanmanRedirector\server\share\f1.txt + // \Device\Mup\;LanmanRedirector\;Q:000000000000b09f\server\share\f1.txt + // then translate to + // \Device\Mup\server\shr\f1.txt + // and test again. We do this because open/closed paths are + // recorded in the \Device\Mup format. See File_TranslateShares. + // ULONG PrefixLen; if (_wcsnicmp(path, File_Redirector, File_RedirectorLen) == 0) @@ -1315,6 +1373,10 @@ _FX NTSTATUS File_Generic_MyParseProc( if (ptr && ptr[0] && ptr[1]) { + // + // the path represents a network share + // + ULONG len1 = wcslen(ptr + 1); ULONG len2 = (File_MupLen + len1 + 8) * sizeof(WCHAR); WCHAR *path2 = Mem_Alloc(proc->pool, len2); @@ -1327,6 +1389,11 @@ _FX NTSTATUS File_Generic_MyParseProc( wmemcpy(path2 + File_MupLen + 1, ptr + 1, len1 + 1); len1 += File_MupLen + 1; +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, path2, len1, L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); +#else Process_MatchPath( proc->pool, path2, len1, open_file_paths, &proc->closed_file_paths, @@ -1356,11 +1423,25 @@ _FX NTSTATUS File_Generic_MyParseProc( is_open = TRUE; } } +#endif //DbgPrint("MyParseProc %S, desired = %x, type = %x\n", path2, MyContext->OriginalDesiredAccess, device_type); +#ifdef USE_MATCH_PATH_EX if ((MyContext->OriginalDesiredAccess != FILE_READ_ATTRIBUTES) && (MyContext->OriginalDesiredAccess != SYNCHRONIZE) && - !is_open && Conf_Get_Boolean(proc->box->name, L"BlockNetworkFiles", 0, FALSE)) + (mp_flags & TRUE_PATH_MASK) != TRUE_PATH_OPEN_FLAG && proc->file_block_network_files) + { + // + // if BlockNetworkFiles=y is set ant this path is not explicitly set as open, + // deny also reading from it + // + + mp_flags &= ~TRUE_PATH_READ_FLAG; + } +#else + if ((MyContext->OriginalDesiredAccess != FILE_READ_ATTRIBUTES) && + (MyContext->OriginalDesiredAccess != SYNCHRONIZE) && + !is_open && proc->file_block_network_files) { if (!write_access) { @@ -1373,13 +1454,26 @@ _FX NTSTATUS File_Generic_MyParseProc( if (!is_open) is_closed = TRUE; } - +#endif Mem_Free(path2, len2); } } } } +#ifdef USE_MATCH_PATH_EX + //if ((mp_flags & (write_access ? TRUE_PATH_WRITE_FLAG : TRUE_PATH_READ_FLAG)) != 0) { + if ((mp_flags & TRUE_PATH_MASK) == 0 || (write_access && (mp_flags & TRUE_PATH_WRITE_FLAG) == 0)) { + + if((mp_flags & COPY_PATH_WRITE_FLAG) != 0) // if we could create this file in the sandbox + status = STATUS_OBJECT_NAME_NOT_FOUND; // hide it instead of returning access denided + else + status = STATUS_ACCESS_DENIED; + + if ((mp_flags & TRUE_PATH_MASK) == 0) + ShouldMonitorAccess = TRUE; + } +#else if (is_closed || (write_access && (! is_open))) { status = STATUS_ACCESS_DENIED; @@ -1388,6 +1482,7 @@ _FX NTSTATUS File_Generic_MyParseProc( ShouldMonitorAccess = TRUE; } + // // read-only paths are also listed as open paths, so if we granted // write access to an open path, we need to check that this isn't @@ -1407,6 +1502,7 @@ _FX NTSTATUS File_Generic_MyParseProc( ShouldMonitorAccess = TRUE; } } +#endif // // release lock @@ -1738,7 +1834,11 @@ _FX NTSTATUS File_Api_Rename(PROCESS *proc, ULONG64 *parms) OBJECT_ATTRIBUTES objattrs; UNICODE_STRING objname; IO_STATUS_BLOCK IoStatusBlock; +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags; +#else BOOLEAN is_open, is_closed; +#endif KIRQL irql; // @@ -1799,12 +1899,20 @@ _FX NTSTATUS File_Api_Rename(PROCESS *proc, ULONG64 *parms) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceSharedLite(proc->file_lock, TRUE); +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, path, path_len, L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); + + if ((mp_flags & TRUE_PATH_WRITE_FLAG) == 0) { +#else Process_MatchPath( proc->pool, path, wcslen(path), &proc->open_file_paths, &proc->closed_file_paths, &is_open, &is_closed); if ((! is_open) || is_closed) { +#endif ExReleaseResourceLite(proc->file_lock); KeLowerIrql(irql); @@ -1819,16 +1927,25 @@ _FX NTSTATUS File_Api_Rename(PROCESS *proc, ULONG64 *parms) *name = L'\0'; +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, path, path_len, L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); +#else Process_MatchPath( proc->pool, path, wcslen(path), &proc->open_file_paths, &proc->closed_file_paths, &is_open, &is_closed); +#endif ExReleaseResourceLite(proc->file_lock); KeLowerIrql(irql); +#ifdef USE_MATCH_PATH_EX + if ((mp_flags & TRUE_PATH_MASK) == TRUE_PATH_OPEN_FLAG || (mp_flags & TRUE_PATH_MASK) == 0) { +#else if (is_open || is_closed) { - +#endif Mem_Free(path, path_len); return STATUS_BAD_INITIAL_PC; } @@ -2050,6 +2167,9 @@ _FX NTSTATUS File_Api_GetName(PROCESS *proc, ULONG64 *parms) _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) { NTSTATUS status; +#ifdef USE_MATCH_PATH_EX + LIST normal_paths, *p_normal_paths; +#endif LIST open_paths, *p_open_paths; LIST closed_paths, *p_closed_paths; LIST read_paths, *p_read_paths; @@ -2069,13 +2189,22 @@ _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) // build a new path list in a temporary space // +#ifdef USE_MATCH_PATH_EX + List_Init(&normal_paths); +#endif List_Init(&open_paths); List_Init(&closed_paths); List_Init(&read_paths); List_Init(&write_paths); ok = File_InitPaths(proc, - &open_paths, &closed_paths, &read_paths, &write_paths); +#ifdef USE_MATCH_PATH_EX + &normal_paths, +#endif + &open_paths, + &closed_paths, + &read_paths, + &write_paths); // // select which set of path lists to delete, the currently active set @@ -2087,6 +2216,9 @@ _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) if (ok) { +#ifdef USE_MATCH_PATH_EX + p_normal_paths = &proc->normal_file_paths; +#endif p_open_paths = &proc->open_file_paths; p_closed_paths = &proc->closed_file_paths; p_read_paths = &proc->read_file_paths; @@ -2094,6 +2226,9 @@ _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) } else { +#ifdef USE_MATCH_PATH_EX + p_normal_paths = &normal_paths; +#endif p_open_paths = &open_paths; p_closed_paths = &closed_paths; p_read_paths = &read_paths; @@ -2105,6 +2240,16 @@ _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) // delete the selected path lists // +#ifdef USE_MATCH_PATH_EX + while (1) { + pat = List_Head(p_normal_paths); + if (! pat) + break; + List_Remove(p_normal_paths, pat); + Pattern_Free(pat); + } +#endif + while (1) { pat = List_Head(p_open_paths); if (! pat) @@ -2143,6 +2288,9 @@ _FX NTSTATUS File_Api_RefreshPathList(PROCESS *proc, ULONG64 *parms) if (ok) { +#ifdef USE_MATCH_PATH_EX + memcpy(&proc->normal_file_paths, &normal_paths, sizeof(LIST)); +#endif memcpy(&proc->open_file_paths, &open_paths, sizeof(LIST)); memcpy(&proc->closed_file_paths, &closed_paths, sizeof(LIST)); memcpy(&proc->read_file_paths, &read_paths, sizeof(LIST)); @@ -2195,7 +2343,11 @@ _FX NTSTATUS File_Api_Open(PROCESS *proc, ULONG64 *parms) ULONG CreateOptions; ULONG AccessCheckOptions; KIRQL irql; +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags; +#else BOOLEAN is_open, is_closed; +#endif // // this API must be invoked by a sandboxed process on Windows XP @@ -2238,16 +2390,25 @@ _FX NTSTATUS File_Api_Open(PROCESS *proc, ULONG64 *parms) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceSharedLite(proc->file_lock, TRUE); +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, path, path_len, L'f', + &proc->normal_file_paths, &proc->open_file_paths, &proc->closed_file_paths, + &proc->read_file_paths, &proc->write_file_paths, NULL); +#else Process_MatchPath( proc->pool, path, wcslen(path), NULL, &proc->closed_file_paths, &is_open, &is_closed); +#endif ExReleaseResourceLite(proc->file_lock); KeLowerIrql(irql); +#ifdef USE_MATCH_PATH_EX + if ((mp_flags & TRUE_PATH_MASK) == 0) { +#else if (is_closed) { - +#endif DesiredAccess = FILE_READ_ATTRIBUTES | SYNCHRONIZE; CreateOptions |= FILE_DIRECTORY_FILE; } @@ -2257,7 +2418,11 @@ _FX NTSTATUS File_Api_Open(PROCESS *proc, ULONG64 *parms) WCHAR access_str[48]; WCHAR letter; +#ifdef USE_MATCH_PATH_EX + if ((mp_flags & TRUE_PATH_MASK) == 0 && (proc->file_trace & TRACE_DENY)) +#else if (is_closed && (proc->file_trace & TRACE_DENY)) +#endif letter = L'D'; else if (proc->file_trace & TRACE_ALLOW) letter = L'A'; @@ -2275,7 +2440,11 @@ _FX NTSTATUS File_Api_Open(PROCESS *proc, ULONG64 *parms) Log_Debug_Msg(mon_type, access_str, path); } } +#ifdef USE_MATCH_PATH_EX + else if ((mp_flags & TRUE_PATH_MASK) == 0 && Session_MonitorCount && !proc->disable_monitor) { +#else else if (is_closed && Session_MonitorCount && !proc->disable_monitor) { +#endif Session_MonitorPut(MONITOR_FILE | MONITOR_DENY, path, proc->pid); } diff --git a/Sandboxie/core/drv/ipc.c b/Sandboxie/core/drv/ipc.c index f4c08cc2..69067ab2 100644 --- a/Sandboxie/core/drv/ipc.c +++ b/Sandboxie/core/drv/ipc.c @@ -151,6 +151,24 @@ _FX BOOLEAN Ipc_Init(void) } } + // + // register object filter callbacks on Vista SP1 and later + // + + if (Driver_OsVersion > DRIVER_WINDOWS_VISTA) { + + // Don't use experimental features by default + if (Conf_Get_Boolean(NULL, L"EnableObjectFiltering", 0, FALSE)) { + + if (!Obj_Load_Filter()) + return FALSE; + } + } + + // + // set up port request filter handlers + // + if (! Syscall_Set1("ImpersonateClientOfPort", Ipc_ImpersonatePort)) return FALSE; @@ -358,6 +376,9 @@ _FX BOOLEAN Ipc_CreateBoxPath(PROCESS *proc) _FX BOOLEAN Ipc_InitPaths(PROCESS *proc) { +#ifdef USE_MATCH_PATH_EX + static const WCHAR *_NormalPath = L"NormalIpcPath"; +#endif static const WCHAR *_OpenPath = L"OpenIpcPath"; static const WCHAR *_ClosedPath = L"ClosedIpcPath"; static const WCHAR *openpaths[] = { @@ -550,9 +571,35 @@ _FX BOOLEAN Ipc_InitPaths(PROCESS *proc) L"*\\BaseNamedObjects\\SM*:WilStaging_*", // 22449.1000 accesses this before sbiedll load NULL }; +#ifdef USE_MATCH_PATH_EX + //static const WCHAR *normalpaths[] = { + // NULL + //}; +#endif ULONG i; BOOLEAN ok; + + // + // normal paths + // + +#ifdef USE_MATCH_PATH_EX + ok = Process_GetPaths(proc, &proc->normal_ipc_paths, _NormalPath, FALSE); + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + return FALSE; + } + + //for (i = 0; normalpaths[i] && ok; ++i) { + // ok = Process_AddPath(proc, &proc->normal_ipc_paths, _NormalPath, TRUE, normalpaths[i], FALSE); + //} + // + //if (! ok) { + // Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + // return FALSE; + //} +#endif // // open paths @@ -856,7 +903,11 @@ _FX NTSTATUS Ipc_CheckGenericObject( if (! IsBoxedPath) { const WCHAR *pattern; +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags; +#else BOOLEAN is_open, is_closed; +#endif // // deny access in two cases: @@ -864,25 +915,40 @@ _FX NTSTATUS Ipc_CheckGenericObject( // - if unsandboxed path does not match an open path // +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, + Name->Buffer, Name->Length / sizeof(WCHAR), L'i', + &proc->normal_ipc_paths, &proc->open_ipc_paths, &proc->closed_ipc_paths, + NULL, NULL, &pattern); +#else pattern = Process_MatchPath( proc->pool, Name->Buffer, Name->Length / sizeof(WCHAR), &proc->open_ipc_paths, &proc->closed_ipc_paths, &is_open, &is_closed); +#endif // // KnownDll objects: prevent DELETE access // +#ifdef USE_MATCH_PATH_EX + if (((mp_flags & TRUE_PATH_MASK) == TRUE_PATH_OPEN_FLAG) && pattern[0] == L'\\' && pattern[1] == L'K' + && (wcsncmp(pattern, L"\\KnownDlls", 10) == 0)) { // L"\\KnownDlls\\*", L"\\KnownDlls32\\*", +#else if (is_open && pattern[0] == L'\\' && pattern[1] == L'K' && (wcsncmp(pattern, L"\\KnownDlls", 10) == 0)) { // L"\\KnownDlls\\*", L"\\KnownDlls32\\*", +#endif if (GrantedAccess & (DELETE | SECTION_EXTEND_SIZE)) status = STATUS_ACCESS_DENIED; } - +#ifdef USE_MATCH_PATH_EX + else if (((mp_flags & TRUE_PATH_MASK) != TRUE_PATH_OPEN_FLAG) && ((mp_flags & COPY_PATH_MASK) == COPY_PATH_OPEN_FLAG)) +#else else if (!is_open && !is_closed) +#endif { if (Ipc_Dynamic_Ports.pPortLock) { @@ -896,7 +962,11 @@ _FX NTSTATUS Ipc_CheckGenericObject( { // dynamic version of RPC ports, see also ipc_spl.c // and RpcBindingFromStringBindingW in core/dll/rpcrt.c +#ifdef USE_MATCH_PATH_EX + mp_flags = TRUE_PATH_OPEN_FLAG; +#else is_open = TRUE; +#endif break; } @@ -908,7 +978,11 @@ _FX NTSTATUS Ipc_CheckGenericObject( } } +#ifdef USE_MATCH_PATH_EX + if ((mp_flags & TRUE_PATH_MASK) == 0 || ((mp_flags & TRUE_PATH_MASK) != TRUE_PATH_OPEN_FLAG)) +#else if (is_closed || (! is_open)) +#endif status = STATUS_ACCESS_DENIED; } diff --git a/Sandboxie/core/drv/key.c b/Sandboxie/core/drv/key.c index 52f5e83b..5237e0b1 100644 --- a/Sandboxie/core/drv/key.c +++ b/Sandboxie/core/drv/key.c @@ -230,24 +230,64 @@ _FX void Key_Unload(void) _FX BOOLEAN Key_InitProcess(PROCESS *proc) { +#ifdef USE_MATCH_PATH_EX + static const WCHAR *_NormalPath = L"NormalKeyPath"; +#endif static const WCHAR *_OpenPath = L"OpenKeyPath"; + static const WCHAR *_OpenConf = L"OpenConfPath"; static const WCHAR *_ClosedPath = L"ClosedKeyPath"; static const WCHAR *_ReadPath = L"ReadKeyPath"; static const WCHAR *_WritePath = L"WriteKeyPath"; +#ifdef USE_MATCH_PATH_EX + static const WCHAR *normalpaths[] = { + L"HKEY_LOCAL_MACHINE\\*", + NULL + }; +#endif + BOOLEAN ok; +#ifdef USE_MATCH_PATH_EX + ULONG i; + + // + // normal paths + // + + ok = Process_GetPaths(proc, &proc->normal_key_paths, _NormalPath, TRUE); + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + return FALSE; + } + + for (i = 0; normalpaths[i] && ok; ++i) { + ok = Process_AddPath(proc, &proc->normal_key_paths, _NormalPath, TRUE, normalpaths[i], FALSE); + } + + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _NormalPath, proc->pid); + return FALSE; + } +#endif + // // open paths // - if (proc->image_from_box) - ok = TRUE; - else + ok = Process_GetPaths(proc, &proc->open_key_paths, _OpenConf, TRUE); + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _OpenConf, proc->pid); + return FALSE; + } + + if (! proc->dont_open_for_boxed || ! proc->image_from_box) { + ok = Process_GetPaths(proc, &proc->open_key_paths, _OpenPath, TRUE); - if (! ok) { - Log_MsgP1(MSG_INIT_PATHS, _OpenPath, proc->pid); - return FALSE; + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _OpenPath, proc->pid); + return FALSE; + } } // @@ -264,8 +304,10 @@ _FX BOOLEAN Key_InitProcess(PROCESS *proc) // read-only paths (stored also as open paths) // +#ifndef USE_MATCH_PATH_EX ok = Process_GetPaths(proc, &proc->open_key_paths, _ReadPath, TRUE); if (ok) +#endif ok = Process_GetPaths(proc, &proc->read_key_paths, _ReadPath, TRUE); if (! ok) { Log_MsgP1(MSG_INIT_PATHS, _ReadPath, proc->pid); @@ -276,19 +318,20 @@ _FX BOOLEAN Key_InitProcess(PROCESS *proc) // write-only paths (stored also as closed paths) // - if (Driver_OsVersion >= DRIVER_WINDOWS_XP) { - - ok = Process_GetPaths2( - proc, &proc->write_key_paths, &proc->closed_key_paths, - _WritePath, TRUE); - if (ok) { - ok = Process_GetPaths( - proc, &proc->closed_key_paths, _WritePath, TRUE); - } - if (! ok) { - Log_MsgP1(MSG_INIT_PATHS, _WritePath, proc->pid); - return FALSE; - } +#ifdef USE_MATCH_PATH_EX + ok = Process_GetPaths(proc, &proc->write_key_paths, _WritePath, TRUE); +#else + ok = Process_GetPaths2( + proc, &proc->write_key_paths, &proc->closed_key_paths, + _WritePath, TRUE); + if (ok) { + ok = Process_GetPaths( + proc, &proc->closed_key_paths, _WritePath, TRUE); + } +#endif + if (! ok) { + Log_MsgP1(MSG_INIT_PATHS, _WritePath, proc->pid); + return FALSE; } // @@ -383,8 +426,12 @@ _FX NTSTATUS Key_MyParseProc_2(OBJ_PARSE_PROC_ARGS_2) if (! IsBoxedPath) { +#ifdef USE_MATCH_PATH_EX + ULONG mp_flags; +#else LIST *open_key_paths; BOOLEAN is_open, is_closed; +#endif // // deny access in two cases: @@ -393,6 +440,24 @@ _FX NTSTATUS Key_MyParseProc_2(OBJ_PARSE_PROC_ARGS_2) // and this is a write access // +#ifdef USE_MATCH_PATH_EX + mp_flags = Process_MatchPathEx(proc, + Name->Name.Buffer, Name->Name.Length / sizeof(WCHAR), L'k', + &proc->normal_key_paths, &proc->open_key_paths, &proc->closed_key_paths, + &proc->read_key_paths, &proc->write_key_paths, NULL); + + //if ((mp_flags & (write_access ? TRUE_PATH_WRITE_FLAG : TRUE_PATH_READ_FLAG)) != 0) { + if ((mp_flags & TRUE_PATH_MASK) == 0 || (write_access && (mp_flags & TRUE_PATH_WRITE_FLAG) == 0)) { + + if((mp_flags & COPY_PATH_WRITE_FLAG) != 0) + status = STATUS_OBJECT_NAME_NOT_FOUND; + else + status = STATUS_ACCESS_DENIED; + + if ((mp_flags & TRUE_PATH_MASK) == 0) + ShouldMonitorAccess = TRUE; + } +#else if (write_access) open_key_paths = &proc->open_key_paths; else @@ -432,6 +497,7 @@ _FX NTSTATUS Key_MyParseProc_2(OBJ_PARSE_PROC_ARGS_2) ShouldMonitorAccess = TRUE; } } +#endif // // when Software Restriction Policies is in effect, ADVAPI32 opens diff --git a/Sandboxie/core/drv/obj.c b/Sandboxie/core/drv/obj.c index 745716bf..ecfe6392 100644 --- a/Sandboxie/core/drv/obj.c +++ b/Sandboxie/core/drv/obj.c @@ -21,6 +21,7 @@ #include "obj.h" +#include "thread.h" #include "conf.h" @@ -83,14 +84,14 @@ P_ObQueryNameInfo pObQueryNameInfo = NULL; _FX BOOLEAN Obj_Init(void) { // - // register as a object filter on Vista SP1 and later + // prepare object filter callback registration on Vista SP1 and later // - //if (Driver_OsVersion > DRIVER_WINDOWS_VISTA) { + if (Driver_OsVersion > DRIVER_WINDOWS_VISTA) { - // if (!Obj_Init_Filter()) - // return FALSE; - //} + if (!Obj_Init_Filter()) + return FALSE; + } if (Driver_OsVersion >= DRIVER_WINDOWS_7) { @@ -135,10 +136,10 @@ _FX void Obj_Unload(void) // deregister as a object filter on Vista SP1 and later // - //if (Driver_OsVersion > DRIVER_WINDOWS_VISTA) { + if (Driver_OsVersion > DRIVER_WINDOWS_VISTA) { - // Obj_Unload_Filter(); - //} + Obj_Unload_Filter(); + } } diff --git a/Sandboxie/core/drv/obj.h b/Sandboxie/core/drv/obj.h index 485a26f1..d4978dc6 100644 --- a/Sandboxie/core/drv/obj.h +++ b/Sandboxie/core/drv/obj.h @@ -47,6 +47,10 @@ BOOLEAN Obj_Init(void); void Obj_Unload(void); +BOOLEAN Obj_Load_Filter(void); + +void Obj_Unload_Filter(void); + NTSTATUS Obj_GetName( POOL *pool, void *Object, OBJECT_NAME_INFORMATION **Name, ULONG *NameLength); diff --git a/Sandboxie/core/drv/obj_flt.c b/Sandboxie/core/drv/obj_flt.c index d2a94d26..31605094 100644 --- a/Sandboxie/core/drv/obj_flt.c +++ b/Sandboxie/core/drv/obj_flt.c @@ -27,8 +27,6 @@ static BOOLEAN Obj_Init_Filter(void); -static void Obj_Unload_Filter(void); - static OB_PREOP_CALLBACK_STATUS Obj_PreOperationCallback( _In_ PVOID RegistrationContext, _Inout_ POB_PRE_OPERATION_INFORMATION PreInfo); @@ -52,7 +50,7 @@ static PVOID Obj_FilterCookie = NULL; static OB_CALLBACK_REGISTRATION Obj_CallbackRegistration = { 0 }; static OB_OPERATION_REGISTRATION Obj_OperationRegistrations[2] = { { 0 }, { 0 } }; -static BOOLEAN Obj_CallbackInstalled = FALSE; +BOOLEAN Obj_CallbackInstalled = FALSE; //--------------------------------------------------------------------------- @@ -62,19 +60,63 @@ static BOOLEAN Obj_CallbackInstalled = FALSE; _FX BOOLEAN Obj_Init_Filter(void) { - NTSTATUS status; UNICODE_STRING uni; - // Don't use experimental features by default - if (!Conf_Get_Boolean(NULL, L"UseObjectKernelCallbacks", 0, FALSE)) - return TRUE; - RtlInitUnicodeString(&uni, L"ObRegisterCallbacks"); pObRegisterCallbacks = (P_ObRegisterCallbacks)MmGetSystemRoutineAddress(&uni); RtlInitUnicodeString(&uni, L"ObUnRegisterCallbacks"); pObUnRegisterCallbacks = (P_ObUnRegisterCallbacks)MmGetSystemRoutineAddress(&uni); + // note: Obj_Load_Filter needs a few other things to be initialized first, hence it will be called by Ipc_Init + + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Obj_Load_Filter +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Obj_Load_Filter(void) +{ + NTSTATUS status; + + if (Obj_CallbackInstalled) + return TRUE; + + // + // from Syscall_DuplicateHandle_2: + // note that files and registry keys [...] don't support adding new permissions + // on the handle during duplication. (this is true for any + // object type which specifies a SecurityProcedure.) + // + // opening/creation of files is handled by a minifilter installed with FltRegisterFilter + // and opening/creation of registry keys is handled by CmRegisterCallbackEx + // + // The types handled by the Syscall_DuplicateHandle are as follows + // + // "Process" -> Thread_CheckProcessObject + // "Thread" -> Thread_CheckThreadObject + // + // "File" -> File_CheckFileObject <- given the the note above why do we double filter for files ??? + // + // "Event" -> Ipc_CheckGenericObject + // "EventPair" -> Ipc_CheckGenericObject <- ExEventPairObjectType not exported + // "KeyedEvent" -> Ipc_CheckGenericObject <- ExpKeyedEventObjectType not exported + // "Mutant" -> Ipc_CheckGenericObject <- ExMutantObjectType not exported + // "Semaphore" -> Ipc_CheckGenericObject + // "Section" -> Ipc_CheckGenericObject + // + // "JobObject" -> Ipc_CheckJobObject + // + // "Port" / "ALPC Port" -> Ipc_CheckPortObject <- AlpcPortObjectType and LpcWaitablePortObjectType not exported, LpcPortObjectType exported + // Note: proper IPC isolation requires filering of NtRequestPort, NtRequestWaitReplyPort, and NtAlpcSendWaitReceivePort calls + // + // "Token" -> Thread_CheckTokenObject + // + if (!pObRegisterCallbacks || !pObUnRegisterCallbacks) status = STATUS_PROCEDURE_NOT_FOUND; else { @@ -101,6 +143,7 @@ _FX BOOLEAN Obj_Init_Filter(void) if (! NT_SUCCESS(status)) { Log_Status_Ex(MSG_OBJ_HOOK_ANY_PROC, 0x81, status, L"Objects"); + Obj_FilterCookie = NULL; return FALSE; } @@ -120,6 +163,7 @@ _FX void Obj_Unload_Filter(void) if (Obj_CallbackInstalled) { pObUnRegisterCallbacks(Obj_FilterCookie); + Obj_FilterCookie = NULL; Obj_CallbackInstalled = FALSE; } @@ -134,189 +178,100 @@ _FX void Obj_Unload_Filter(void) _FX OB_PREOP_CALLBACK_STATUS Obj_PreOperationCallback( _In_ PVOID RegistrationContext, _Inout_ POB_PRE_OPERATION_INFORMATION PreInfo) { - PROCESS *proc = NULL; - NTSTATUS status = STATUS_SUCCESS; + // + // Filter only if request made outside of the kernel + // - if (ExGetPreviousMode() == KernelMode) - return status; - - proc = Process_Find(NULL, NULL); - if (!proc || (proc == PROCESS_TERMINATED)) + //if (ExGetPreviousMode() == KernelMode) + if (PreInfo->KernelHandle == 1) return OB_PREOP_SUCCESS; + // + // Get the sandboxed process if this request comes form one, + // filter only requests from sandboxed processes + // - DbgPrint("Obj_PreOperationCallback for %S\r\n", proc->image_name); - - - /* - typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION { - _Inout_ ACCESS_MASK DesiredAccess; - _In_ ACCESS_MASK OriginalDesiredAccess; - } OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION; - - typedef struct _OB_PRE_DUPLICATE_HANDLE_INFORMATION { - _Inout_ ACCESS_MASK DesiredAccess; - _In_ ACCESS_MASK OriginalDesiredAccess; - _In_ PVOID SourceProcess; - _In_ PVOID TargetProcess; - } OB_PRE_DUPLICATE_HANDLE_INFORMATION, * POB_PRE_DUPLICATE_HANDLE_INFORMATION; - */ - - /*PTD_CALLBACK_REGISTRATION CallbackRegistration; - - ACCESS_MASK AccessBitsToClear = 0; - ACCESS_MASK AccessBitsToSet = 0; - ACCESS_MASK InitialDesiredAccess = 0; - ACCESS_MASK OriginalDesiredAccess = 0; + PROCESS *proc = NULL; + proc = Process_Find(NULL, NULL); + if (!proc || (proc == PROCESS_TERMINATED) || proc->bHostInject || proc->disable_object_flt) + return OB_PREOP_SUCCESS; + // + // Get information about the intended operation + // PACCESS_MASK DesiredAccess = NULL; - - LPCWSTR ObjectTypeName = NULL; - LPCWSTR OperationName = NULL; - - // Not using driver specific values at this time - CallbackRegistration = (PTD_CALLBACK_REGISTRATION)RegistrationContext; - - - TD_ASSERT (PreInfo->CallContext == NULL); - - // Only want to filter attempts to access protected process - // all other processes are left untouched - - if (PreInfo->ObjectType == *PsProcessType) { - - //HANDLE pid = PsGetProcessId((PEPROCESS)PreInfo->Object); - //char szProcName[16] = { 0 }; - //UNREFERENCED_PARAMETER(RegistrationContext); - //strcpy(szProcName, GetProcessNameByProcessID(pid)); - - // - // Ignore requests for processes other than our target process. - // - - // if (TdProtectedTargetProcess != NULL && - // TdProtectedTargetProcess != PreInfo->Object) - if (TdProtectedTargetProcess != PreInfo->Object) - { - goto Exit; - } - - // - // Also ignore requests that are trying to open/duplicate the current - // process. - // - - if (PreInfo->Object == PsGetCurrentProcess()) { - DbgPrintEx ( - DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, - "ObCallbackTest: CBTdPreOperationCallback: ignore process open/duplicate from the protected process itself\n"); - goto Exit; - } - - ObjectTypeName = L"PsProcessType"; - AccessBitsToClear = CB_PROCESS_TERMINATE; - AccessBitsToSet = 0; - } - else if (PreInfo->ObjectType == *PsThreadType) { - HANDLE ProcessIdOfTargetThread = PsGetThreadProcessId ((PETHREAD)PreInfo->Object); - - // - // Ignore requests for threads belonging to processes other than our - // target process. - // - - // if (CallbackRegistration->TargetProcess != NULL && - // CallbackRegistration->TargetProcessId != ProcessIdOfTargetThread) - if (TdProtectedTargetProcessId != ProcessIdOfTargetThread) { - goto Exit; - } - - // - // Also ignore requests for threads belonging to the current processes. - // - - if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { - DbgPrintEx ( - DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, - "ObCallbackTest: CBTdPreOperationCallback: ignore thread open/duplicate from the protected process itself\n"); - goto Exit; - } - - ObjectTypeName = L"PsThreadType"; - AccessBitsToClear = CB_THREAD_TERMINATE; - AccessBitsToSet = 0; - } - else { - DbgPrintEx ( - DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, - "ObCallbackTest: CBTdPreOperationCallback: unexpected object type\n"); - goto Exit; - } + ACCESS_MASK InitialDesiredAccess = 0; + //ACCESS_MASK OriginalDesiredAccess = 0; switch (PreInfo->Operation) { case OB_OPERATION_HANDLE_CREATE: DesiredAccess = &PreInfo->Parameters->CreateHandleInformation.DesiredAccess; - OriginalDesiredAccess = PreInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess; - - OperationName = L"OB_OPERATION_HANDLE_CREATE"; + //OriginalDesiredAccess = PreInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess; + //OperationName = L"OB_OPERATION_HANDLE_CREATE"; break; case OB_OPERATION_HANDLE_DUPLICATE: DesiredAccess = &PreInfo->Parameters->DuplicateHandleInformation.DesiredAccess; - OriginalDesiredAccess = PreInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess; - - OperationName = L"OB_OPERATION_HANDLE_DUPLICATE"; + //OriginalDesiredAccess = PreInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess; + //OperationName = L"OB_OPERATION_HANDLE_DUPLICATE"; break; default: - TD_ASSERT (FALSE); - break; + DbgPrint("Sbie ObCallback: unexpected callback type\n"); + goto Exit; } InitialDesiredAccess = *DesiredAccess; - // Filter only if request made outside of the kernel - if (PreInfo->KernelHandle != 1) { - *DesiredAccess &= ~AccessBitsToClear; - *DesiredAccess |= AccessBitsToSet; + // + // Based on the object type apply the apropriate filter + // + + if (PreInfo->ObjectType == *PsProcessType) { + + HANDLE TargetProcessId = PsGetProcessId((PEPROCESS)PreInfo->Object); + + // + // Ignore requests for threads belonging to the current processes. + // + + if (TargetProcessId == PsGetCurrentProcessId()) + goto Exit; + + PEPROCESS ProcessObject = (PEPROCESS)PreInfo->Object; + ACCESS_MASK WriteAccess = (InitialDesiredAccess & PROCESS_DENIED_ACCESS_MASK); + if (!NT_SUCCESS(Thread_CheckObject_Common( + proc, ProcessObject, InitialDesiredAccess, WriteAccess, L'P'))) { + *DesiredAccess = 0; // deny any access + } + //ObjectTypeName = L"PsProcessType"; + } + else if (PreInfo->ObjectType == *PsThreadType) { + + HANDLE TargetProcessId = PsGetThreadProcessId ((PETHREAD)PreInfo->Object); + + // + // Ignore requests that are trying to open/duplicate the current process. + // + + if (TargetProcessId == PsGetCurrentProcessId()) + goto Exit; + + PEPROCESS ProcessObject = PsGetThreadProcess((PETHREAD)PreInfo->Object); + ACCESS_MASK WriteAccess = (InitialDesiredAccess & THREAD_DENIED_ACCESS_MASK); + if (!NT_SUCCESS(Thread_CheckObject_Common( + proc, ProcessObject, InitialDesiredAccess, WriteAccess, L'T'))) { + *DesiredAccess = 0; // deny any access + } + //ObjectTypeName = L"PsThreadType"; + } + else { + DbgPrint("Sbie ObCallback: unexpected object type\n"); + goto Exit; } - // - // Set call context. - // - - TdSetCallContext (PreInfo, CallbackRegistration); - - - DbgPrintEx ( - DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: PROTECTED process %p (ID 0x%p)\n", - TdProtectedTargetProcess, - (PVOID)TdProtectedTargetProcessId - ); - - DbgPrintEx ( - DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, - "ObCallbackTest: CBTdPreOperationCallback\n" - " Client Id: %p:%p\n" - " Object: %p\n" - " Type: %ls\n" - " Operation: %ls (KernelHandle=%d)\n" - " OriginalDesiredAccess: 0x%x\n" - " DesiredAccess (in): 0x%x\n" - " DesiredAccess (out): 0x%x\n", - PsGetCurrentProcessId(), - PsGetCurrentThreadId(), - PreInfo->Object, - ObjectTypeName, - OperationName, - PreInfo->KernelHandle, - OriginalDesiredAccess, - InitialDesiredAccess, - *DesiredAccess - ); - -Exit:*/ +Exit: return OB_PREOP_SUCCESS; } diff --git a/Sandboxie/core/drv/process.c b/Sandboxie/core/drv/process.c index e60a34f3..842296fd 100644 --- a/Sandboxie/core/drv/process.c +++ b/Sandboxie/core/drv/process.c @@ -708,6 +708,73 @@ _FX PROCESS *Process_Create( return NULL; } + // + // initialize box options + // + + proc->bAppCompartment = Conf_Get_Boolean(proc->box->name, L"NoSecurityIsolation", 0, FALSE); + + // + // by default, Close[...]=!,path includes all boxed images + // use AlwaysCloseForBoxed=n to disable this behaviour + // + + proc->always_close_for_boxed = !proc->bAppCompartment && Conf_Get_Boolean(proc->box->name, L"AlwaysCloseForBoxed", 0, TRUE); + + // + // by default OpenFile and OpenKey apply only to unboxed processes + // use DontOpenForBoxed=n to thread boxed and unboxed programs the same way + // + + proc->dont_open_for_boxed = !proc->bAppCompartment && Conf_Get_Boolean(proc->box->name, L"DontOpenForBoxed", 0, TRUE); + + // + // privacy mode requirers Rule Specificity + // + +#ifdef USE_MATCH_PATH_EX + proc->use_privacy_mode = Conf_Get_Boolean(proc->box->name, L"UsePrivacyMode", 0, FALSE); + proc->use_rule_specificity = proc->use_privacy_mode || Conf_Get_Boolean(proc->box->name, L"UseRuleSpecificity", 0, FALSE); +#endif + + // + // check certificate + // + + if (!Driver_Certified && !proc->image_sbie) { + if ( +#ifdef USE_MATCH_PATH_EX + proc->use_rule_specificity || + proc->use_privacy_mode || +#endif + proc->bAppCompartment) { + + Log_Msg_Process(MSG_6004, proc->box->name, proc->image_name, box->session_id, proc->pid); + + //Pool_Delete(pool); + //Process_CreateTerminated(ProcessId, box->session_id); + //return NULL; + + // allow the process to run for a sort while to allow the features to be avaluated + Process_ScheduleKill(proc, 5*60*1000); // 5 minutes + } + } + + // + // configure monitor options + // + + proc->disable_monitor = Conf_Get_Boolean(proc->box->name, L"DisableResourceMonitor", 0, FALSE); + + // + // initialize filtering options + // + + BOOLEAN no_filtering = proc->bAppCompartment && Conf_Get_Boolean(proc->box->name, L"NoSecurityFiltering", 0, FALSE); // only in effect in app mode + proc->disable_file_flt = no_filtering || Conf_Get_Boolean(proc->box->name, L"DisableFileFilter", 0, FALSE); + proc->disable_key_flt = no_filtering || Conf_Get_Boolean(proc->box->name, L"DisableKeyFilter", 0, FALSE); + proc->disable_object_flt = no_filtering || Conf_Get_Boolean(proc->box->name, L"DisableObjectFilter", 0, FALSE); + // // initialize various locks // @@ -736,16 +803,6 @@ _FX PROCESS *Process_Create( return NULL; } - proc->disable_monitor = Conf_Get_Boolean(proc->box->name, L"DisableResourceMonitor", 0, FALSE); - - // - // initialize debug options - // - - proc->disable_file_flt = Conf_Get_Boolean(proc->box->name, L"DisableFileFilter", 0, FALSE); - proc->disable_key_flt = Conf_Get_Boolean(proc->box->name, L"DisableKeyFilter", 0, FALSE); - //proc->disable_object_flt = Conf_Get_Boolean(proc->box->name, L"DisableObjectFilter", 0, FALSE); - // // initialize trace flags // @@ -1219,7 +1276,7 @@ _FX BOOLEAN Process_NotifyProcess_Create( // don't put the process into a job if OpenWinClass=* // - if (new_proc->open_all_win_classes || Conf_Get_Boolean(new_proc->box->name, L"NoAddProcessToJob", 0, FALSE)) { + if (new_proc->open_all_win_classes || new_proc->bAppCompartment || Conf_Get_Boolean(new_proc->box->name, L"NoAddProcessToJob", 0, FALSE)) { new_proc->can_use_jobs = TRUE; add_process_to_job = FALSE; diff --git a/Sandboxie/core/drv/process.h b/Sandboxie/core/drv/process.h index c03fc6fa..7db8bc61 100644 --- a/Sandboxie/core/drv/process.h +++ b/Sandboxie/core/drv/process.h @@ -125,6 +125,8 @@ struct _PROCESS { BOOLEAN change_notify_token_flag; + BOOLEAN bAppCompartment; + BOOLEAN in_pca_job; BOOLEAN can_use_jobs; @@ -132,16 +134,26 @@ struct _PROCESS { BOOLEAN disable_monitor; + BOOLEAN always_close_for_boxed; + BOOLEAN dont_open_for_boxed; +#ifdef USE_MATCH_PATH_EX + BOOLEAN use_rule_specificity; + BOOLEAN use_privacy_mode; +#endif + ULONG call_trace; // file-related PERESOURCE file_lock; +#ifdef USE_MATCH_PATH_EX + LIST normal_file_paths; // PATTERN elements +#endif LIST open_file_paths; // PATTERN elements LIST closed_file_paths; // PATTERN elements LIST read_file_paths; // PATTERN elements LIST write_file_paths; // PATTERN elements - BOOLEAN always_close_for_boxed; + BOOLEAN file_block_network_files; LIST blocked_dlls; ULONG file_trace; ULONG pipe_trace; @@ -155,6 +167,9 @@ struct _PROCESS { PERESOURCE key_lock; KEY_MOUNT *key_mount; +#ifdef USE_MATCH_PATH_EX + LIST normal_key_paths; // PATTERN elements +#endif LIST open_key_paths; // PATTERN elements LIST closed_key_paths; // PATTERN elements LIST read_key_paths; // PATTERN elements @@ -165,9 +180,13 @@ struct _PROCESS { // ipc-related PERESOURCE ipc_lock; +#ifdef USE_MATCH_PATH_EX + LIST normal_ipc_paths; // PATTERN elements +#endif LIST open_ipc_paths; // PATTERN elements LIST closed_ipc_paths; // PATTERN elements ULONG ipc_trace; + BOOLEAN disable_object_flt; BOOLEAN ipc_warn_startrun; BOOLEAN ipc_block_password; BOOLEAN ipc_open_lsa_endpoint; @@ -271,6 +290,30 @@ const WCHAR *Process_MatchPath( LIST *open_list, LIST *closed_list, BOOLEAN *is_open, BOOLEAN *is_closed); +// Process_MatchPathEx: given a list that was previously initialized with +// Process_GetPaths, tests if the passed string 'path' matches any pattern. +// path_len specifies the number of characters in path, excluding the +// null terminator, or in other words, path_len is wcslen(path). +// Returns the highest priority true path permission + +#define TRUE_PATH_CLOSED_FLAG 0x00 +#define TRUE_PATH_READ_FLAG 0x10 +#define TRUE_PATH_WRITE_FLAG 0x20 +#define TRUE_PATH_OPEN_FLAG 0x30 +#define TRUE_PATH_MASK 0x30 + +#define COPY_PATH_CLOSED_FLAG 0x00 +#define COPY_PATH_READ_FLAG 0x01 +#define COPY_PATH_WRITE_FLAG 0x02 +#define COPY_PATH_OPEN_FLAG 0x03 +#define COPY_PATH_MASK 0x03 + +ULONG Process_MatchPathEx( + PROCESS *proc, const WCHAR *path, ULONG path_len, WCHAR path_code, + LIST *normal_list, + LIST *open_list, LIST *closed_list, + LIST *read_list, LIST *write_list, + const WCHAR** patsrc); // Process_GetConf: retrives a configuration data value for a given process // use with Conf_AdjustUseCount to make sure the returned pointer is valid @@ -389,7 +432,7 @@ BOOLEAN Process_CancelProcess(PROCESS *proc); // Terminate a process using a helper thread -BOOLEAN Process_ScheduleKill(PROCESS *proc); +BOOLEAN Process_ScheduleKill(PROCESS *proc, LONG delay_ms); // Check if process is running within a // Program Compatibility Assistant (PCA) job diff --git a/Sandboxie/core/drv/process_api.c b/Sandboxie/core/drv/process_api.c index 9d2e64ef..3b8a21f3 100644 --- a/Sandboxie/core/drv/process_api.c +++ b/Sandboxie/core/drv/process_api.c @@ -380,6 +380,13 @@ _FX NTSTATUS Process_Api_QueryInfo(PROCESS *proc, ULONG64 *parms) if (proc->open_all_win_classes) flags |= SBIE_FLAG_OPEN_ALL_WIN_CLASS; + + if (proc->use_rule_specificity) + flags |= SBIE_FLAG_RULE_SPECIFICITY; + if (proc->use_privacy_mode) + flags |= SBIE_FLAG_PRIVACY_MODE; + if (proc->bAppCompartment) + flags |= SBIE_FLAG_APP_COMPARTMENT; } else { @@ -693,6 +700,7 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) ULONG path_len; KIRQL irql; BOOLEAN process_list_locked; + BOOLEAN prepend_level; // // caller can either be a sandboxed process asking its own path list, @@ -724,6 +732,12 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) // select path list based on the parameter given // +#ifdef USE_MATCH_PATH_EX + if (args->path_code.val == 'fn') { + list = &proc->normal_file_paths; + lock = proc->file_lock; + } else +#endif if (args->path_code.val == 'fo') { list = &proc->open_file_paths; lock = proc->file_lock; @@ -737,6 +751,11 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) list = &proc->write_file_paths; lock = proc->file_lock; +#ifdef USE_MATCH_PATH_EX + } else if (args->path_code.val == 'kn') { + list = &proc->normal_key_paths; + lock = proc->key_lock; +#endif } else if (args->path_code.val == 'ko') { list = &proc->open_key_paths; lock = proc->key_lock; @@ -750,6 +769,11 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) list = &proc->write_key_paths; lock = proc->key_lock; +#ifdef USE_MATCH_PATH_EX + } else if (args->path_code.val == 'in') { + list = &proc->normal_ipc_paths; + lock = proc->ipc_lock; +#endif } else if (args->path_code.val == 'io') { list = &proc->open_ipc_paths; lock = proc->ipc_lock; @@ -781,6 +805,13 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) ExAcquireResourceSharedLite(lock, TRUE); + prepend_level = args->prepend_level.val; + + // + // path format: ([level 4])[wchar 2*n][0x0000] + // level is optional + // + // // count the length of the desired path list // @@ -789,10 +820,12 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) pat = List_Head(list); while (pat) { + if (prepend_level) path_len += sizeof(ULONG); path_len += (wcslen(Pattern_Source(pat)) + 1) * sizeof(WCHAR); pat = List_Next(pat); } + if (prepend_level) path_len += sizeof(ULONG); path_len += sizeof(WCHAR); // @@ -800,6 +833,41 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) // __try { + + if(args->path_str.val) { + + // + // if a output buffer was specified store the paths into it + // + + if (args->path_len.val && *args->path_len.val < path_len) { + + status = STATUS_BUFFER_TOO_SMALL; + __leave; + } + + path = args->path_str.val; + ProbeForWrite(path, path_len, sizeof(WCHAR)); + + pat = List_Head(list); + while (pat) { + if (prepend_level) { + *((ULONG*)path) = Pattern_Level(pat); + path += sizeof(ULONG)/sizeof(WCHAR); + } + const WCHAR *pat_src = Pattern_Source(pat); + ULONG pat_len = wcslen(pat_src) + 1; + wmemcpy(path, pat_src, pat_len); + path += pat_len; + pat = List_Next(pat); + } + + if (prepend_level){ + *((ULONG*)path) = -1; + path += sizeof(ULONG)/sizeof(WCHAR); + } + *path = L'\0'; + } if (args->path_len.val) { @@ -810,26 +878,7 @@ _FX NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms) ProbeForWrite(args->path_len.val, sizeof(ULONG), sizeof(ULONG)); *args->path_len.val = path_len; - } else { - - // - // otherwise store the paths into the output buffer - // - - path = args->path_str.val; - ProbeForWrite(path, path_len, sizeof(WCHAR)); - - pat = List_Head(list); - while (pat) { - const WCHAR *pat_src = Pattern_Source(pat); - ULONG pat_len = wcslen(pat_src) + 1; - wmemcpy(path, pat_src, pat_len); - path += pat_len; - pat = List_Next(pat); - } - - *path = L'\0'; - } + } status = STATUS_SUCCESS; diff --git a/Sandboxie/core/drv/process_force.c b/Sandboxie/core/drv/process_force.c index ee0f38dc..012f5d22 100644 --- a/Sandboxie/core/drv/process_force.c +++ b/Sandboxie/core/drv/process_force.c @@ -962,7 +962,7 @@ _FX void Process_CreateForceData( if (wcschr(buf, L'*')) { folder->pat = - Pattern_Create(box->box->expand_args->pool, buf, TRUE); + Pattern_Create(box->box->expand_args->pool, buf, TRUE, 0); Mem_Free(buf, buf_len); @@ -1090,7 +1090,7 @@ _FX void Process_CreateForceData( if (wcschr(buf, L'*')) { folder->pat = - Pattern_Create(box->box->expand_args->pool, buf, TRUE); + Pattern_Create(box->box->expand_args->pool, buf, TRUE, 0); Mem_Free(buf, buf_len); diff --git a/Sandboxie/core/drv/process_low.c b/Sandboxie/core/drv/process_low.c index 66a2398e..a74ee158 100644 --- a/Sandboxie/core/drv/process_low.c +++ b/Sandboxie/core/drv/process_low.c @@ -283,7 +283,7 @@ _FX BOOLEAN Process_Low_InitConsole(PROCESS *proc) NTSTATUS status; // NoSbieCons BEGIN - if (Conf_Get_Boolean(proc->box->name, L"NoSandboxieConsole", 0, FALSE)) + if (proc->bAppCompartment || Conf_Get_Boolean(proc->box->name, L"NoSandboxieConsole", 0, FALSE)) return TRUE; // NoSbieCons END diff --git a/Sandboxie/core/drv/process_util.c b/Sandboxie/core/drv/process_util.c index 916b22ab..79adc231 100644 --- a/Sandboxie/core/drv/process_util.c +++ b/Sandboxie/core/drv/process_util.c @@ -42,14 +42,14 @@ static BOOLEAN Process_MatchImageGroup( static BOOLEAN Process_AddPath_2( PROCESS *proc, LIST *list, const WCHAR *value, const WCHAR *setting_name, BOOLEAN AddFirst, BOOLEAN AddStar, - BOOLEAN RemoveBackslashes, BOOLEAN CheckReparse, BOOLEAN* Reparsed); + BOOLEAN RemoveBackslashes, BOOLEAN CheckReparse, BOOLEAN* Reparsed, ULONG Level); //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- - +static const WCHAR *Process_Normal = L"Normal"; static const WCHAR *Process_Open = L"Open"; static const WCHAR *Process_Read = L"Read"; static const WCHAR *Process_Write = L"Write"; @@ -154,7 +154,7 @@ _FX BOOLEAN Process_MatchImage( if (! expnd) return FALSE; - pat = Pattern_Create(box->expand_args->pool, expnd, TRUE); + pat = Pattern_Create(box->expand_args->pool, expnd, TRUE, 0); Mem_FreeString(expnd); @@ -328,7 +328,7 @@ _FX const WCHAR* Process_MatchImageAndGetValue(BOX *box, const WCHAR* value, con } else { - if (pLevel) *pLevel = 2; // 2 - global default + if (pLevel) *pLevel = 3; // 3 - global default } if (! *value) @@ -531,6 +531,7 @@ _FX BOOLEAN Process_AddPath( BOOLEAN CheckReparse = FALSE; BOOLEAN Reparsed; BOOLEAN ok; + ULONG Level; // // if this is a file/pipe/key setting, remove duplicate backslashes @@ -540,7 +541,8 @@ _FX BOOLEAN Process_AddPath( if (setting_name) { const WCHAR *setting_name_ptr = setting_name; - if (_wcsnicmp(setting_name, Process_Closed, 6) == 0) + if (_wcsnicmp(setting_name, Process_Normal, 6) == 0 || + _wcsnicmp(setting_name, Process_Closed, 6) == 0) setting_name_ptr = setting_name + 6; else if (_wcsnicmp(setting_name, Process_Write, 5) == 0) setting_name_ptr = setting_name + 5; @@ -564,7 +566,7 @@ _FX BOOLEAN Process_AddPath( } } - value = Process_MatchImageAndGetValue(proc->box, value, proc->image_name, NULL); + value = Process_MatchImageAndGetValue(proc->box, value, proc->image_name, &Level); if (!value) return TRUE; @@ -588,13 +590,13 @@ _FX BOOLEAN Process_AddPath( // ok = Process_AddPath_2(proc, list, value, setting_name, - AddFirst, AddStar, RemoveBackslashes, CheckReparse, &Reparsed); + AddFirst, AddStar, RemoveBackslashes, CheckReparse, &Reparsed, Level); if (ok && CheckReparse && Reparsed) { // // If the path was reparsed, add also the original path to the list // ok = Process_AddPath_2(proc, list, value, setting_name, - AddFirst, AddStar, RemoveBackslashes, FALSE, NULL); + AddFirst, AddStar, RemoveBackslashes, FALSE, NULL, Level); } // @@ -611,10 +613,10 @@ _FX BOOLEAN Process_AddPath( for (len = L'A'; (len <= L'Z') && ok; ++len) { *tmp = (WCHAR)len; ok = Process_AddPath_2(proc, list, tmp, setting_name, - AddFirst, AddStar, RemoveBackslashes, CheckReparse, &Reparsed); + AddFirst, AddStar, RemoveBackslashes, CheckReparse, &Reparsed, Level); if (ok && CheckReparse && Reparsed) { ok = Process_AddPath_2(proc, list, tmp, setting_name, - AddFirst, AddStar, RemoveBackslashes, FALSE, NULL); + AddFirst, AddStar, RemoveBackslashes, FALSE, NULL, Level); } } Mem_FreeString(tmp); @@ -632,7 +634,7 @@ _FX BOOLEAN Process_AddPath( _FX BOOLEAN Process_AddPath_2( PROCESS *proc, LIST *list, const WCHAR *value, const WCHAR *setting_name, BOOLEAN AddFirst, BOOLEAN AddStar, - BOOLEAN RemoveBackslashes, BOOLEAN CheckReparse, BOOLEAN* Reparsed) + BOOLEAN RemoveBackslashes, BOOLEAN CheckReparse, BOOLEAN* Reparsed, ULONG Level) { PATTERN *pat; WCHAR *expand, *tmp; @@ -712,7 +714,7 @@ _FX BOOLEAN Process_AddPath_2( // add the pattern // - pat = Pattern_Create(proc->pool, tmp, TRUE); + pat = Pattern_Create(proc->pool, tmp, TRUE, Level); if (pat) { if (AddFirst) @@ -833,6 +835,239 @@ _FX const WCHAR *Process_MatchPath( } +//--------------------------------------------------------------------------- +// Process_MatchPathList +//--------------------------------------------------------------------------- + + +_FX int Process_MatchPathList( + WCHAR *path_lwr, ULONG path_len, LIST *list, ULONG* plevel, const WCHAR** patsrc) +{ + PATTERN *pat; + int match_len = 0; + ULONG level = plevel ? *plevel : -1; // lower is better, 3 is max value + + pat = List_Head(list); + while (pat) { + + ULONG cur_level = Pattern_Level(pat); + if (cur_level > level) + goto next; // no point testing patters with a to weak level + + int cur_len = Pattern_MatchX(pat, path_lwr, path_len); + if (cur_len > match_len) { + match_len = cur_len; + level = cur_level; + if (patsrc) *patsrc = Pattern_Source(pat); + + // we need to test all entries to find the best match, so we dont break here + } + + // + // if we have a pattern like C:\Windows\, + // we still want it to match a path like C:\Windows, + // hence we add a L'\\' to the path and check again + // + + else if (path_lwr[path_len - 1] != L'\\') { + path_lwr[path_len] = L'\\'; + cur_len = Pattern_MatchX(pat, path_lwr, path_len + 1); + path_lwr[path_len] = L'\0'; + if (cur_len > match_len) { + match_len = cur_len; + level = cur_level; + if (patsrc) *patsrc = Pattern_Source(pat); + } + } + + next: + pat = List_Next(pat); + } + + if (plevel) *plevel = level; + return match_len; +} + + +//--------------------------------------------------------------------------- +// Process_MatchPathEx +//--------------------------------------------------------------------------- + + +_FX ULONG Process_MatchPathEx( + PROCESS *proc, const WCHAR *path, ULONG path_len, WCHAR path_code, + LIST *normal_list, + LIST *open_list, LIST *closed_list, + LIST *read_list, LIST *write_list, + const WCHAR** patsrc) +{ + PATTERN *pat; + WCHAR *path_lwr; + ULONG path_lwr_len; + const WCHAR* curpat; + ULONG cur_level; + int cur_len; + int match_len; + ULONG level; + ULONG mp_flags; + + path_lwr_len = (path_len + 4) * sizeof(WCHAR); + path_lwr = Mem_Alloc(proc->pool, path_lwr_len); + if (! path_lwr) + return 0; + + wmemcpy(path_lwr, path, path_len); + path_lwr[path_len] = L'\0'; + path_len = wcslen(path_lwr); + if (! path_len) { + Mem_Free(path_lwr, path_lwr_len); + return 0; + } + path_lwr[path_len] = L'\0'; + path_lwr[path_len + 1] = L'\0'; + _wcslwr(path_lwr); + + // + // Rule priorities are implemented based on their specificity and match level with the process. + // The specificity describes how well a pattern matches a given path, + // i.e. how many charakters of the path it matches, disregarding the last wild card. + // The process match level describes in which way a rule applies to a given process: + // 0 - exact match, eg. ...Path=program.exe,... + // 1 - match by negation, eg. ...Path=!program.exe,... + // 2 - match all, eg. ...Path=*,... + // 3 - global default, eg. ...Path=... + // Rules with the most exact matches overrule the more generic once. + // The match level overrules the specificity. + // + // Adding UseRuleSpecificity=n disables this behavioure and reverts to the old classical one + // + + // + // set default behavioure + // + + level = 3; // 3 - global default - lower is better, 3 is max value + match_len = 0; + if (!proc->use_privacy_mode || path_code == L'i') { + + // + // in normal sandbox mode we have read access to all locations unless restricted, + // and all writes are redirected to the sandbox + // + + mp_flags = TRUE_PATH_READ_FLAG | COPY_PATH_OPEN_FLAG; // normal mode + } + else { + + // + // in privacy mode we only have read access to selected generic locations, + // and read access to user data must be explicityl grated, + // also all writes are redirected to the sandbox + // + // To enable privacy enchanced mode add UsePrivacyMode=y + // + + mp_flags = TRUE_PATH_CLOSED_FLAG | COPY_PATH_OPEN_FLAG; // write path mode + } + + // + // closed path list, in non specific mode has the higher priority + // these paths are inaccessible for true and copy locations + // + + if (closed_list) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, closed_list, &cur_level, &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + if (patsrc) *patsrc = curpat; + + mp_flags = TRUE_PATH_CLOSED_FLAG | COPY_PATH_CLOSED_FLAG; + if (!proc->use_rule_specificity) goto finish; + } + } + + // + // write path list, behaved on the driver side like closed path list + // these paths allow read acces to true location and read/write access to copy location + // + + if (write_list) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, write_list, &cur_level, &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + if (patsrc) *patsrc = curpat; + + mp_flags = TRUE_PATH_CLOSED_FLAG | COPY_PATH_OPEN_FLAG; + if (!proc->use_rule_specificity) goto finish; + } + } + + // + // read path list behaves in the kernel like the default normal behavioure + // these paths allow read only acces to true path and copy locations + // + + if (read_list) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len,read_list, &cur_level, &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + if (patsrc) *patsrc = curpat; + + mp_flags = TRUE_PATH_READ_FLAG | COPY_PATH_READ_FLAG; + if (!proc->use_rule_specificity) goto finish; + } + } + + // + // normal path list restores normal behavioure when used in specific mode + // these paths allow reading the true location and write to the copy location + // + + if (normal_list) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, normal_list, &cur_level, &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + if (patsrc) *patsrc = curpat; + + mp_flags = TRUE_PATH_READ_FLAG | COPY_PATH_OPEN_FLAG; + if (!proc->use_rule_specificity) goto finish; + } + } + + // + // open path has lowest priority in non specific mode + // these paths allow read/write access to the true location + // + + if (open_list) { + cur_level = level; + cur_len = Process_MatchPathList(path_lwr, path_len, open_list, &cur_level, &curpat); + if (cur_level <= level && cur_len > match_len) { + level = cur_level; + match_len = cur_len; + if (patsrc) *patsrc = curpat; + + mp_flags = TRUE_PATH_OPEN_FLAG; + if (!proc->use_rule_specificity) goto finish; + } + } + + +finish: + Mem_Free(path_lwr, path_lwr_len); + + return mp_flags; +} + + //--------------------------------------------------------------------------- // Process_GetProcessName //--------------------------------------------------------------------------- @@ -1107,7 +1342,7 @@ _FX BOOLEAN Process_TerminateProcess(PROCESS* proc) // else fall back to the kernel method } - return Process_ScheduleKill(proc); + return Process_ScheduleKill(proc, 0); } @@ -1195,22 +1430,40 @@ _FX BOOLEAN Process_IsInPcaJob(HANDLE ProcessId) _FX VOID Process_ScheduleKillProc(IN PVOID StartContext) { + PVOID* params = (PVOID*)StartContext; + HANDLE process_id = (HANDLE)(params[0]); + LONG delay_ms = (LONG)(params[1]); + Mem_Free(params, sizeof(PVOID)*2); + NTSTATUS status; - HANDLE process_id = (HANDLE)StartContext; HANDLE handle = NULL; PEPROCESS ProcessObject; __try { - + retry: status = PsLookupProcessByProcessId(process_id, &ProcessObject); if (NT_SUCCESS(status)) { status = ObOpenObjectByPointer(ProcessObject, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, NULL, KernelMode, &handle); ObDereferenceObject(ProcessObject); + if (NT_SUCCESS(status)) { - ZwTerminateProcess(handle, STATUS_PROCESS_IS_TERMINATING); - ZwClose(handle); + if (delay_ms > 0) { + ZwClose(handle); + + LARGE_INTEGER time; + time.QuadPart = -(SECONDS(1) / 20); // wait half a second = 50ms + KeDelayExecutionThread(KernelMode, FALSE, &time); + + delay_ms -= 50; + goto retry; + } + else { + + ZwTerminateProcess(handle, STATUS_PROCESS_IS_TERMINATING); + ZwClose(handle); + } } } @@ -1227,18 +1480,25 @@ _FX VOID Process_ScheduleKillProc(IN PVOID StartContext) //--------------------------------------------------------------------------- -_FX BOOLEAN Process_ScheduleKill(PROCESS *proc) +_FX BOOLEAN Process_ScheduleKill(PROCESS *proc, LONG delay_ms) { NTSTATUS status; OBJECT_ATTRIBUTES objattrs; HANDLE handle; + PVOID *params = Mem_Alloc(Driver_Pool, sizeof(PVOID)*2); + params[0] = proc->pid; + params[1] = (PVOID)delay_ms; + InitializeObjectAttributes(&objattrs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); - status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, &objattrs, NULL, NULL, Process_ScheduleKillProc, proc->pid); + status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, &objattrs, NULL, NULL, Process_ScheduleKillProc, params); if (NT_SUCCESS(status)) { ZwClose(handle); + if (delay_ms != 0) + return TRUE; + ULONG len = proc->image_name_len + 32 * sizeof(WCHAR); WCHAR *text = Mem_Alloc(Driver_Pool, len); if (text) { diff --git a/Sandboxie/core/drv/session.c b/Sandboxie/core/drv/session.c index 99eb7a92..27ac8ec0 100644 --- a/Sandboxie/core/drv/session.c +++ b/Sandboxie/core/drv/session.c @@ -72,7 +72,7 @@ struct _SESSION { // resource monitor // - LOG_BUFFER* monitor_log; + LOG_BUFFER* monitor_log; BOOLEAN monitor_overflow; diff --git a/Sandboxie/core/drv/syscall.c b/Sandboxie/core/drv/syscall.c index fd7a0f84..f5e5348e 100644 --- a/Sandboxie/core/drv/syscall.c +++ b/Sandboxie/core/drv/syscall.c @@ -102,6 +102,11 @@ static BOOLEAN Syscall_GetKernelAddr( #endif // ALLOC_PRAGMA +#ifdef HOOK_WIN32K +#include "syscall_win32.c" +#endif + + //--------------------------------------------------------------------------- @@ -152,7 +157,35 @@ typedef NTSTATUS (*P_SystemService14)( 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 @@ -186,6 +219,18 @@ _FX BOOLEAN Syscall_Init(void) if (! Syscall_Init_ServiceData()) return FALSE; +#ifdef HOOK_WIN32K + // must be windows 10 or later // Don't use experimental features by default + if (Driver_OsBuild >= 10041 && Conf_Get_Boolean(NULL, L"EnableWin32kHooks", 0, FALSE)) { + + if (!Syscall_Init_List32()) + return FALSE; + + if (!Syscall_Init_Table32()) + return FALSE; + } +#endif + if (! Syscall_Set1("DuplicateObject", Syscall_DuplicateHandle)) return FALSE; @@ -650,6 +695,47 @@ _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack) 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; @@ -692,6 +778,12 @@ _FX NTSTATUS Syscall_Api_Invoke(PROCESS *proc, ULONG64 *parms) syscall_index = (ULONG)parms[1]; +#ifdef HOOK_WIN32K + if ((syscall_index & 0x1000) != 0) { // win32k syscall + return Syscall_Api_Invoke32(proc, parms); + } +#endif + //DbgPrint("[syscall] request for service %d / %08X\n", syscall_index, syscall_index); if (Syscall_Table && (syscall_index <= Syscall_MaxIndex)) @@ -935,6 +1027,15 @@ _FX NTSTATUS Syscall_Api_Query(PROCESS *proc, ULONG64 *parms) ULONG *ptr; SYSCALL_ENTRY *entry; +#ifdef HOOK_WIN32K + if (parms[2] == 1) { // win32k + return Syscall_Api_Query32(proc, parms); + } + else if (parms[2] != 0) { // ntoskrnl + return STATUS_INVALID_PARAMETER; + } +#endif + // // caller must be our service process // diff --git a/Sandboxie/core/drv/syscall_win32.c b/Sandboxie/core/drv/syscall_win32.c new file mode 100644 index 00000000..f47ab444 --- /dev/null +++ b/Sandboxie/core/drv/syscall_win32.c @@ -0,0 +1,606 @@ +/* + * Copyright 2020-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 . + */ + +//--------------------------------------------------------------------------- +// Syscall Management +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// Functions +//--------------------------------------------------------------------------- + + +static BOOLEAN Syscall_Init_List32(void); + +static BOOLEAN Syscall_Init_Table32(void); + + +//--------------------------------------------------------------------------- + + +static NTSTATUS Syscall_Api_Query32(PROCESS *proc, ULONG64 *parms); + +static NTSTATUS Syscall_Api_Invoke32(PROCESS *proc, ULONG64 *parms); + + +//--------------------------------------------------------------------------- + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, Syscall_Init_List32) +#pragma alloc_text (INIT, Syscall_Init_Table32) +#endif // ALLOC_PRAGMA + + + +//--------------------------------------------------------------------------- +// Variables +//--------------------------------------------------------------------------- + + +static LIST Syscall_List32; + +static SYSCALL_ENTRY **Syscall_Table32 = NULL; + +ULONG Syscall_MaxIndex32 = 0; + + + + +//--------------------------------------------------------------------------- +// Syscall_GetWin32kAddr +//--------------------------------------------------------------------------- + +//struct _EX_FAST_REF +//{ +// void *Object; +// unsigned long RefCnt:3; +// unsigned long Value; +//}; +// +//struct _EX_CALLBACK +//{ +// struct _EX_FAST_REF RoutineBlock; +//}; +// +//struct _PS_WIN32K_GLOBALS +//{ +// struct _EX_CALLBACK Win32CallBack; +// struct _KSERVICE_TABLE_DESCRIPTOR ServiceDescriptorTableShadow[2]; +// struct _KSERVICE_TABLE_DESCRIPTOR ServiceDescriptorTableFilter[2]; +//}; + +typedef struct _KSERVICE_TABLE_DESCRIPTOR +{ + unsigned long *Base; + unsigned long *Reserved1; + unsigned long Limit; + unsigned int *Number; +} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR ; + + +_FX BOOLEAN Syscall_GetWin32kAddr(ULONG *Base_Copy, + ULONG index, void **pKernelAddr, ULONG *pParamCount) +{ + KSERVICE_TABLE_DESCRIPTOR *ShadowTable = (KSERVICE_TABLE_DESCRIPTOR *)Syscall_GetServiceTable(); + ShadowTable += 1; // ServiceDescriptorTableShadow[0] -> ntoskrnl.exe, ServiceDescriptorTableShadow[1] -> win32k.sys + + if (ShadowTable) { + + ULONG MaxSyscallIndexPlusOne = ShadowTable->Limit; + if ((index >= 0x1000) && + ((index & 0xFFF) < MaxSyscallIndexPlusOne)) { + + long EntryValue = Base_Copy[index & 0xFFF]; + + *pKernelAddr = (UCHAR *)ShadowTable->Base + (EntryValue >> 4); + *pParamCount = (ULONG)(EntryValue & 0x0F) + 4; + //DbgPrint(" SysCall32 offset: %d\r\n", (ULONG)(EntryValue >> 4)); + return TRUE; + } + + Log_Msg1(MSG_1113, L"ADDRESS"); + } + + return FALSE; +} + + +//--------------------------------------------------------------------------- +// Syscall_Init_List32 +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Syscall_Init_List32(void) +{ + 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; + + + KSERVICE_TABLE_DESCRIPTOR *ShadowTable = (KSERVICE_TABLE_DESCRIPTOR *)Syscall_GetServiceTable(); + if (!ShadowTable) { + Log_Msg1(MSG_1113, L"SHADOW_TABLE"); + return FALSE; + } + //DbgPrint(" win32k.sys SysCalls: %d %p %p\n", ShadowTable->Limit, ShadowTable->Base, ShadowTable->Number); + ShadowTable += 1; + //DbgPrint(" win32k.sys SysCalls: %d %p %p\n", ShadowTable->Limit, ShadowTable->Base, ShadowTable->Number); + + if (ShadowTable->Limit > 0xFFF) { // not plausible + Log_Msg1(MSG_1113, L"SHADOW_TABLE"); + return FALSE; + } + + // + // 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 + // 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; + } + + ULONG* table_copy = (ULONG*)Mem_AllocEx(Driver_Pool, ShadowTable->Limit * sizeof(long), TRUE); + if (!table_copy) + return FALSE; + + BOOLEAN success = FALSE; + + PEPROCESS ProcessObject; + if (NT_SUCCESS(PsLookupProcessByProcessId(csrssId,&ProcessObject))) { + KAPC_STATE ApcState; + KeStackAttachProcess(ProcessObject, &ApcState); + if (MmIsAddressValid(ShadowTable->Base)) { + memcpy(table_copy, ShadowTable->Base, ShadowTable->Limit * sizeof(long)); + success = TRUE; + } + KeUnstackDetachProcess(&ApcState); + ObDereferenceObject(ProcessObject); + } + + if (!success) { + Log_Msg1(MSG_1113, L"WIN32K_TABLE"); + return FALSE; + } + + // + // ready + // + + List_Init(&Syscall_List32); + + // + // scan each NtXxx export in WIN32U + // + + dll = Dll_Load(L"WIN32U"); + if (! dll) + return FALSE; + + proc_offset = Dll_GetNextProc(dll, "Nt", &name, &proc_index); + if (! proc_offset) + return FALSE; + + while (proc_offset) { + + if (name[0] != 'N' || name[1] != 't') + break; + name += 2; // skip Nt prefix + for (name_len = 0; (name_len < 64) && name[name_len]; ++name_len) + ; + + //DbgPrint(" Found SysCall32 %s\n", name); + + entry = NULL; + + // + // we don't hook UserCreateWindowEx as it uses callbacks into + // user space from teh kernel, for ocne this dies not play well + // 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 + // + + #define IS_PROC_NAME(ln,nm) (name_len == ln && memcmp(name, nm, ln) == 0) + + if ( IS_PROC_NAME(18, "UserCreateWindowEx") + || IS_PROC_NAME( 7, "GdiInit") // bsod + || IS_PROC_NAME(12, "GdiInitSpool") // probably too + || IS_PROC_NAME(20, "UserSetThreadDesktop") // bsod + + ) { + goto next_ntxxx; + } + + // + // analyze each NtXxx export to find the service index number + // + + ntos_addr = NULL; + param_count = 0; + + win32k_code = Dll_RvaToAddr(dll, proc_offset); + if (win32k_code) { + + syscall_index = + Syscall_GetIndexFromNtdll(win32k_code, name, name_len); + + if (syscall_index == -2) { + // + // if ZwXxx export is not a real syscall, then skip it + // + goto next_ntxxx; + } + + if (syscall_index != -1) { + + Syscall_GetWin32kAddr(table_copy, + syscall_index, &ntos_addr, ¶m_count); + + //BOOLEAN test; + //KeStackAttachProcess(pProcess, &ApcState); + //test = MmIsAddressValid(ntos_addr); + //KeUnstackDetachProcess(&ApcState); + //DbgPrint(" Found SysCall32: %s, pcnt %d; idx: %d; addr: %p %s\r\n", name, param_count, syscall_index, ntos_addr, test ? "valid" : "invalid"); + //DbgPrint(" Found SysCall32: %s, pcnt %d; idx: %d\r\n", name, param_count, syscall_index); + } + } + + if (! ntos_addr) { + Syscall_ErrorForAsciiName(name); + return FALSE; + } + + syscall_index = (syscall_index & 0xFFF); + + // + // store an entry for the syscall in our list of syscalls + // + + entry_len = sizeof(SYSCALL_ENTRY) + name_len + 1; + entry = Mem_AllocEx(Driver_Pool, entry_len, TRUE); + if (!entry) { + Syscall_MaxIndex32 = 0; + return FALSE; + } + + entry->syscall_index = (USHORT)syscall_index; + entry->param_count = (USHORT)param_count; + entry->ntdll_offset = proc_offset; + entry->ntos_func = ntos_addr; + entry->handler1_func = NULL; + entry->handler2_func = NULL; + entry->handler3_func_support_procmon = NULL; + entry->name_len = (USHORT)name_len; + memcpy(entry->name, name, name_len); + entry->name[name_len] = '\0'; + + List_Insert_After(&Syscall_List32, NULL, entry); + + if (syscall_index > Syscall_MaxIndex32) + Syscall_MaxIndex32 = syscall_index; + + // + // process next ZwXxx export + // + +next_ntxxx: + + proc_offset = Dll_GetNextProc(dll, NULL, &name, &proc_index); + + } + + //DbgPrint("Found %d win32 SysCalls\n", Syscall_MaxIndex32); + + // + // report an error if we did not find a reasonable number of services + // + + if (Syscall_MaxIndex32 < 100) { + Log_Msg1(MSG_1113, L"100"); + Syscall_MaxIndex32 = 0; + return FALSE; + } + + if (Syscall_MaxIndex32 >= 2000) { + Log_Msg1(MSG_1113, L"2000"); + Syscall_MaxIndex32 = 0; + return FALSE; + } + + Mem_Free(table_copy, ShadowTable->Limit * sizeof(long)); + + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Syscall_Init_Table32 +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Syscall_Init_Table32(void) +{ + SYSCALL_ENTRY *entry; + ULONG len, i; + + // + // build the table which maps syscall index numbers to entries + // + + len = sizeof(SYSCALL_ENTRY *) * (Syscall_MaxIndex32 + 1); + Syscall_Table32 = Mem_AllocEx(Driver_Pool, len, TRUE); + if (! Syscall_Table32) + return FALSE; + + for (i = 0; i <= Syscall_MaxIndex32; ++i) { + + entry = List_Head(&Syscall_List32); + while (entry) { + if (entry->syscall_index == i) + break; + entry = List_Next(entry); + } + + Syscall_Table32[i] = entry; + } + + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Syscall_Api_Invoke32 +//--------------------------------------------------------------------------- + +extern unsigned int g_TrapFrameOffset; + +_FX NTSTATUS Syscall_Api_Invoke32(PROCESS* proc, ULONG64* parms) +{ + ULONG_PTR *user_args; + SYSCALL_ENTRY *entry; + ULONG syscall_index; + NTSTATUS status; +#ifdef _WIN64 + volatile ULONG_PTR ret = 0; + volatile ULONG_PTR UserStack = 0; + + volatile PETHREAD pThread = PsGetCurrentThread(); + volatile PKTRAP_FRAME pTrapFrame = NULL; +#endif + + // + // caller must be sandboxed and service index must be known + // + + if (! proc) + return STATUS_NOT_IMPLEMENTED; + + syscall_index = (ULONG)parms[1]; + + syscall_index = (syscall_index & 0xFFF); + + //DbgPrint("[syscall] request for service %d / %08X\n", syscall_index, syscall_index); + + if (Syscall_Table32 && (syscall_index <= Syscall_MaxIndex32)) + entry = Syscall_Table32[syscall_index]; + else + entry = NULL; + + if (! entry) + return STATUS_INVALID_SYSTEM_SERVICE; + + //DbgPrint("[syscall] request %s\n", entry->name); + + // DbgPrint("[syscall] request p=%06d t=%06d - BEGIN %s\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), entry->name); + +// Thread_SetThreadToken(proc); // may set proc->terminated + +// if (proc->terminated) { +// +// Process_TerminateProcess(proc); +// return STATUS_PROCESS_IS_TERMINATING; +// } + + + // + // on first win32k.sys call we must convert this thread to a GUI thread + // + + // todo: call KiConvertToGuiThread() or PsConvertToGuiThread() + + // + // if we have a handler for this service, invoke it + // + + user_args = (ULONG_PTR *)parms[2]; + + __try { + + BOOLEAN traced = FALSE; + const ULONG args_len = entry->param_count * sizeof(ULONG_PTR); +#ifdef _WIN64 + ProbeForRead(user_args, args_len, sizeof(ULONG_PTR)); + + // default - support procmon stack if handler3_func_support_procmon is null. + if (!entry->handler3_func_support_procmon + || entry->handler3_func_support_procmon(proc, entry, user_args) + ) + { + if (g_TrapFrameOffset) { + + pTrapFrame = (PKTRAP_FRAME) *(ULONG_PTR*)((UCHAR*)pThread + g_TrapFrameOffset); + if (pTrapFrame) { + ret = pTrapFrame->Rip; + UserStack = pTrapFrame->Rsp; + pTrapFrame->Rsp = pTrapFrame->Rbp; //*pRbp; + pTrapFrame->Rip = pTrapFrame->Rbx; //*pRbx; + } + } + else + { + pTrapFrame = NULL; + } + } + else + { + pTrapFrame = NULL; + } + +#else ! _WIN64 + ProbeForRead(user_args, args_len, sizeof(UCHAR)); +#endif _WIN64 + + if (entry->handler1_func) { + + status = entry->handler1_func(proc, entry, user_args); + + } else { + + if (MmIsAddressValid(entry->ntos_func)) { + + //DbgPrint(" SysCall32 %d -> %p\r\n", syscall_index, entry->ntos_func); + status = Syscall_Invoke(entry, user_args); + + } else { + + status = STATUS_INVALID_ADDRESS; + + } + } + + if (!traced && ((proc->call_trace & TRACE_ALLOW) || ((status != STATUS_SUCCESS) && (proc->call_trace & TRACE_DENY)))) + { + WCHAR trace_str[128]; + RtlStringCbPrintfW(trace_str, sizeof(trace_str), L"[syscall32] %.*S, status = 0x%X", //59 chars + entry->name + max(strlen(entry->name), 64), entry->name, + status); + const WCHAR* strings[2] = { trace_str, NULL }; + Session_MonitorPutEx(MONITOR_SYSCALL | MONITOR_TRACE, strings, NULL, PsGetCurrentProcessId(), PsGetCurrentThreadId()); + } + +#ifdef _WIN64 + if (g_TrapFrameOffset) { + if (pTrapFrame) { + pTrapFrame->Rip = ret; + pTrapFrame->Rsp = UserStack; + } + } +#endif + + } __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + + +// if (proc->terminated) { +// +// Process_TerminateProcess(proc); +// return STATUS_PROCESS_IS_TERMINATING; +// } + + // + // clear any thread impersonation set during the syscall, to restore + // use of the highly restricted primary token in this thread + // + +// Thread_ClearThreadToken(); + + /*if (! NT_SUCCESS(status)) { + DbgPrint("Process %06d Syscall %04X Status %08X\n", proc->pid, syscall_index, status); + }*/ + + return status; +} + + +//--------------------------------------------------------------------------- +// Syscall_Api_Query32 +//--------------------------------------------------------------------------- + + +_FX NTSTATUS Syscall_Api_Query32(PROCESS *proc, ULONG64 *parms) +{ + ULONG buf_len; + ULONG *user_buf; + ULONG *ptr; + SYSCALL_ENTRY *entry; + + // + // allocate user mode space for syscall table + // + + buf_len = sizeof(ULONG) // size of buffer + + List_Count(&Syscall_List32) * sizeof(ULONG) * 2 + + sizeof(ULONG) * 2 // final terminator entry + ; + + user_buf = (ULONG *)parms[1]; + + ProbeForWrite(user_buf, buf_len, sizeof(ULONG)); + + // + // populate the buffer with syscall data. first we store + // the size of the buffer, and then we leave room for ULONG used + // by SbieSvc, and for the code for four ZwXxx stub functions + // + + ptr = user_buf; + *ptr = buf_len; + ++ptr; + + // + // store service index number and (only on 32-bit Windows) also + // the parameter count for each syscall into one ULONG. + // store corresponding offset within ntdll into the other ULONG + // + + entry = List_Head(&Syscall_List32); + while (entry) { + + ULONG syscall_index = (ULONG)entry->syscall_index; +#ifndef _WIN64 + ULONG param_count = (ULONG)entry->param_count; + syscall_index |= (param_count * 4) << 24; +#endif ! _WIN64 + + *ptr = syscall_index; + ++ptr; + *ptr = entry->ntdll_offset; + ++ptr; + + entry = List_Next(entry); + } + + // + // store a final zero terminator entry and return successfully + // + + *ptr = 0; + ++ptr; + *ptr = 0; + + return STATUS_SUCCESS; +} + diff --git a/Sandboxie/core/drv/thread_token.c b/Sandboxie/core/drv/thread_token.c index 6e7c0b3c..4a050984 100644 --- a/Sandboxie/core/drv/thread_token.c +++ b/Sandboxie/core/drv/thread_token.c @@ -1356,7 +1356,7 @@ _FX NTSTATUS Thread_CheckTokenForImpersonation( NTSTATUS status; // OriginalToken BEGIN - if (Conf_Get_Boolean(proc->box->name, L"OriginalToken", 0, FALSE)) + if (proc->bAppCompartment || Conf_Get_Boolean(proc->box->name, L"OriginalToken", 0, FALSE)) return STATUS_SUCCESS; // OriginalToken END // OpenToken BEGIN diff --git a/Sandboxie/core/drv/token.c b/Sandboxie/core/drv/token.c index 35c26963..92ef86dd 100644 --- a/Sandboxie/core/drv/token.c +++ b/Sandboxie/core/drv/token.c @@ -1796,7 +1796,7 @@ _FX BOOLEAN Token_ReplacePrimary(PROCESS *proc) BOOLEAN ok = FALSE; // OriginalToken BEGIN - if (Conf_Get_Boolean(proc->box->name, L"OriginalToken", 0, FALSE)) + if (proc->bAppCompartment || Conf_Get_Boolean(proc->box->name, L"OriginalToken", 0, FALSE)) return TRUE; // OriginalToken END diff --git a/Sandboxie/core/drv/util.c b/Sandboxie/core/drv/util.c index bdea7005..f109a05f 100644 --- a/Sandboxie/core/drv/util.c +++ b/Sandboxie/core/drv/util.c @@ -351,6 +351,9 @@ _FX NTSTATUS MyValidateCertificate(void) Driver_Certified = NT_SUCCESS(status); + //if (status == STATUS_ACCOUNT_EXPIRED) + // status = STATUS_SUCCESS; + return status; } diff --git a/Sandboxie/core/svc/DriverAssistInject.cpp b/Sandboxie/core/svc/DriverAssistInject.cpp index 62c610ff..b8a7b4fd 100644 --- a/Sandboxie/core/svc/DriverAssistInject.cpp +++ b/Sandboxie/core/svc/DriverAssistInject.cpp @@ -83,10 +83,10 @@ void DriverAssist::InjectLow(void *_msg) sbieLow.is_wow64 = msg->is_wow64; sbieLow.bHostInject = msg->bHostInject; // NoSysCallHooks BEGIN - sbieLow.bNoSysHooks = SbieApi_QueryConfBool(boxname, L"NoSysCallHooks", FALSE); + sbieLow.bNoSysHooks = SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(boxname, L"NoSysCallHooks", FALSE); // NoSysCallHooks END // NoSbieCons BEGIN - sbieLow.bNoConsole = SbieApi_QueryConfBool(boxname, L"NoSandboxieConsole", FALSE); + sbieLow.bNoConsole = SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(boxname, L"NoSandboxieConsole", FALSE); // NoSbieCons END errlvl = SbieDll_InjectLow(hProcess, sbieLow.init_flags, TRUE); @@ -98,7 +98,7 @@ void DriverAssist::InjectLow(void *_msg) // // NoSbieDesk BEGIN - if (!SbieApi_QueryConfBool(boxname, L"NoSandboxieDesktop", FALSE)) + if (!SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) && !SbieApi_QueryConfBool(boxname, L"NoSandboxieDesktop", FALSE)) // NoSbieDesk END if (!msg->bHostInject) { diff --git a/Sandboxie/core/svc/GuiServer.cpp b/Sandboxie/core/svc/GuiServer.cpp index f269adf4..7007da58 100644 --- a/Sandboxie/core/svc/GuiServer.cpp +++ b/Sandboxie/core/svc/GuiServer.cpp @@ -3632,7 +3632,8 @@ ULONG GuiServer::GetProcessPathList( const HANDLE xpid = (HANDLE)(ULONG_PTR)pid; ULONG len; - LONG status = SbieApi_QueryPathList(path_code, &len, NULL, xpid); + LONG status = SbieApi_QueryPathList(path_code, &len, NULL, xpid, FALSE); + //LONG status = SbieApi_QueryPathList(path_code, &len, NULL, xpid, TRUE); if (status != 0) return status; @@ -3646,7 +3647,8 @@ ULONG GuiServer::GetProcessPathList( LIST *list = (LIST *)Pool_Alloc(pool, sizeof(LIST)); if (path && list) - status = SbieApi_QueryPathList(path_code, NULL, path, xpid); + status = SbieApi_QueryPathList(path_code, NULL, path, xpid, FALSE); + //status = SbieApi_QueryPathList(path_code, NULL, path, xpid, TRUE); if (status != STATUS_SUCCESS) { Pool_Delete(pool); @@ -3655,7 +3657,11 @@ ULONG GuiServer::GetProcessPathList( List_Init(list); while (*path) { - PATTERN *pattern = Pattern_Create(pool, path, TRUE); + PATTERN *pattern = Pattern_Create(pool, path, TRUE, 0); + //while (*((ULONG*)path) != -1) { + // ULONG level = *((ULONG*)path); + // path += sizeof(ULONG)/sizeof(WCHAR); + // PATTERN *pattern = Pattern_Create(pool, path, TRUE, level); if (! pattern) { Pool_Delete(pool); return status; diff --git a/Sandboxie/core/svc/PipeServer.cpp b/Sandboxie/core/svc/PipeServer.cpp index 9d0b90cf..409d78a3 100644 --- a/Sandboxie/core/svc/PipeServer.cpp +++ b/Sandboxie/core/svc/PipeServer.cpp @@ -27,6 +27,7 @@ #include "core/dll/sbiedll.h" #include "common/defines.h" #include "common/my_version.h" +//#include // For access to GetModuleFileNameEx #include "sbieiniserver.h" //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/svc/ProcessServer.cpp b/Sandboxie/core/svc/ProcessServer.cpp index 10187fdf..fac9d68d 100644 --- a/Sandboxie/core/svc/ProcessServer.cpp +++ b/Sandboxie/core/svc/ProcessServer.cpp @@ -777,7 +777,7 @@ HANDLE ProcessServer::RunSandboxedGetToken( // OriginalToken BEGIN if (!ok) { - if (SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) { + if (SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) { HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PipeServer::GetCallerProcessId()); @@ -854,7 +854,7 @@ HANDLE ProcessServer::RunSandboxedGetToken( if (SbieApi_QueryConfBool(boxname, L"ExposeBoxedSystem", FALSE)) ok = RunSandboxedSetDacl(CallerProcessHandle, NewTokenHandle, GENERIC_ALL, TRUE); // OriginalToken BEGIN - else if (!SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) + else if (!SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) && !SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) // OriginalToken END ok = RunSandboxedSetDacl(CallerProcessHandle, NewTokenHandle, GENERIC_READ, FALSE); } diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj b/Sandboxie/core/svc/SboxSvc.vcxproj index 7ebbe85d..547f6136 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj +++ b/Sandboxie/core/svc/SboxSvc.vcxproj @@ -208,6 +208,12 @@ true + + true + true + true + true + NotUsing NotUsing diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj.filters b/Sandboxie/core/svc/SboxSvc.vcxproj.filters index e440dbf3..5bcd2ded 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj.filters +++ b/Sandboxie/core/svc/SboxSvc.vcxproj.filters @@ -72,6 +72,9 @@ common + + ComProxy + diff --git a/Sandboxie/core/svc/main.cpp b/Sandboxie/core/svc/main.cpp index b24b3900..5b85491f 100644 --- a/Sandboxie/core/svc/main.cpp +++ b/Sandboxie/core/svc/main.cpp @@ -487,6 +487,8 @@ finish: bool CheckDropRights(const WCHAR *BoxName) { + if (SbieApi_QueryConfBool(BoxName, L"NoSecurityIsolation", FALSE)) + return false; // if we are not swaping the token we can not drop admin rights so keep this consistent if (SbieApi_QueryConfBool(BoxName, L"DropAdminRights", FALSE)) return true; return false; diff --git a/Sandboxie/core/svc/serviceserver2.cpp b/Sandboxie/core/svc/serviceserver2.cpp index 64c60dd8..aa899f01 100644 --- a/Sandboxie/core/svc/serviceserver2.cpp +++ b/Sandboxie/core/svc/serviceserver2.cpp @@ -134,7 +134,7 @@ bool ServiceServer::CanAccessSCM(HANDLE idProcess) HANDLE hToken = NULL; // OriginalToken BEGIN - if (SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) { + if (SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)(UINT_PTR)idProcess); if (hProcess != NULL) { OpenProcessToken(hProcess, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken); @@ -392,7 +392,7 @@ ULONG ServiceServer::RunHandler2( if (SbieApi_QueryConfBool(boxname, L"ExposeBoxedSystem", FALSE)) ok = ProcessServer::RunSandboxedSetDacl(hProcess, hNewToken, GENERIC_ALL, TRUE, idProcess); // OriginalToken BEGIN - else if (!SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) + else if (!SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) && !SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) // OriginalToken END ok = ProcessServer::RunSandboxedSetDacl(hProcess, hNewToken, GENERIC_READ, FALSE); diff --git a/Sandboxie/core/svc/terminalserver.cpp b/Sandboxie/core/svc/terminalserver.cpp index 10dcec0a..0fc009bd 100644 --- a/Sandboxie/core/svc/terminalserver.cpp +++ b/Sandboxie/core/svc/terminalserver.cpp @@ -589,3 +589,4 @@ MSG_HEADER *TerminalServer::GetUserToken(MSG_HEADER *msg) } + diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp index e07ad01e..cf0194a8 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp +++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp @@ -37,6 +37,7 @@ typedef long NTSTATUS; #include "..\..\Sandboxie\core\svc\msgids.h" #include "..\..\Sandboxie\core\svc\ProcessWire.h" +#include "..\..\Sandboxie\core\svc\GuiWire.h" #include "..\..\Sandboxie\core\svc\sbieiniwire.h" #include "..\..\Sandboxie\core\svc\QueueWire.h" #include "..\..\Sandboxie\core\svc\InteractiveWire.h" @@ -288,7 +289,7 @@ SB_STATUS CSbieAPI::Connect(bool withQueue) //m->lastRecordNum = 0; // Note: this lib is not using all functions hence it can be compatible with multiple driver ABI revisions - QStringList CompatVersions = QStringList () << "5.53.0"; + QStringList CompatVersions = QStringList () << "5.55.0"; QString CurVersion = GetVersion(); if (!CompatVersions.contains(CurVersion)) { @@ -2056,8 +2057,16 @@ QString CSbieAPI::GetFeatureStr() QStringList str; if (flags & SBIE_FEATURE_FLAG_WFP) str.append("WFP"); + if (flags & SBIE_FEATURE_FLAG_OB_CALLBACKS) + str.append("ObCB"); if (flags & SBIE_FEATURE_FLAG_SBIE_LOGIN) str.append("SbL"); + if (flags & SBIE_FEATURE_FLAG_PRIVACY_MODE) + str.append("PMod"); + if (flags & SBIE_FEATURE_FLAG_COMPARTMENTS) + str.append("AppC"); + if (flags & SBIE_FEATURE_FLAG_WIN32K_HOOK) + str.append("W32k"); return str.join(","); } diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.h b/SandboxiePlus/QSbieAPI/SbieAPI.h index 13bb4a39..9314bf91 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.h +++ b/SandboxiePlus/QSbieAPI/SbieAPI.h @@ -103,6 +103,16 @@ public: virtual SB_STATUS LockConfig(const QString& NewPassword); virtual void ClearPassword(); + enum EFeatureFlags + { + eSbieFeatureWFP = 0x00000001, + eSbieFeatureObCB = 0x00000002, + eSbieFeaturePMod = 0x00000004, + eSbieFeatureAppC = 0x00000008, + eSbieFeatureSbiL = 0x00000010, + eSbieFeatureCert = 0x80000000 + }; + virtual quint32 GetFeatureFlags(); virtual QString GetFeatureStr(); diff --git a/SandboxiePlus/SandMan/Forms/NewBoxWindow.ui b/SandboxiePlus/SandMan/Forms/NewBoxWindow.ui index af9f7879..4a9eeb91 100644 --- a/SandboxiePlus/SandMan/Forms/NewBoxWindow.ui +++ b/SandboxiePlus/SandMan/Forms/NewBoxWindow.ui @@ -6,8 +6,8 @@ 0 0 - 333 - 263 + 500 + 300 @@ -18,14 +18,14 @@ - 0 - 0 + 500 + 300 - 500 - 263 + 750 + 600 @@ -34,64 +34,31 @@ - - + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + - Select restriction/isolation template: + Sandbox Name: - - + + - Initial sandbox configuration: + Box Type Preset: - - - - 32 - - + + - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Copy options from an existing box: - - - - + Qt::Vertical @@ -104,54 +71,42 @@ - - + + - Sandbox Name: + A sandbox isolates your host system from processes running within the box, it prevents them from making permanent changes to other programs and data in your computer. The level of isolation impacts your security as well as the compatibility with applications, hence there will be a different level of isolation depending on the selected Box Type. Sandboxie can also protect your personal data from being accessed by processes running under its supervision. + + + true - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + 32 - - - - Qt::Horizontal + + + + Box info - - QSizePolicy::Fixed + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - 40 - 20 - + + true - + - - - - Qt::Horizontal + + + + - - QSizePolicy::Fixed - - - - 40 - 20 - - - + @@ -159,10 +114,6 @@ txtName - radTemplate - cmbTemplates - radCopy - cmbBoxes diff --git a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui index b9c260c4..7fb0dab7 100644 --- a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui +++ b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui @@ -45,7 +45,7 @@ QTabWidget::North - 0 + 8 @@ -64,15 +64,106 @@ - - + + + + + 75 + true + true + + - Drop rights from Administrators and Power Users groups + Appearance - - + + + + + + + + + + + + + + + 75 + true + true + + + + General Configuration + + + + + + + + + + Box Type Preset: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Sandbox Indicator in title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + px Width + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Sandboxed window border: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Box info + + + Qt::AutoText + + + true + + + + + + + + + @@ -87,36 +178,28 @@ - - + + - + Show this box in the 'run in box' selection prompt - - - - Sandbox Indicator in title: + + + + Qt::Horizontal - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 40 + 20 + - + - - - - - 75 - true - true - - - - (Recommended) - - + + @@ -138,40 +221,19 @@ - - - - 75 - true - true - - + - CAUTION: When running under the built in administrator, processes can not drop administrative privileges. + <b>More Box Types</b> are exclusively available to <u>project supporters</u>, the Privacy Enhanced boxes <b><font color='red'>protect user data from illicit access</font></b> by the sandboxed programs.<br />If you are not yet a supporter, then please consider <a href="https://sandboxie-plus.com/go.php?to=sbie-get-cert">supporting the project</a>, to receive a <a href="https://sandboxie-plus.com/go.php?to=sbie-cert">supporter certificate</a>.<br />You can test the other box types by creating new sandboxes of those types, however processes in these will be auto terminated after 5 minutes. + + + Qt::RichText true - - - - - 75 - true - true - - - - Protect the system from sandboxed processes - - - Elevation restrictions - - - - + Qt::Vertical @@ -184,104 +246,6 @@ - - - - Show this box in the 'run in box' selection prompt - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 75 - true - true - - - - Appearance - - - - - - - Make applications think they are running elevated (allows to run installers safely) - - - - - - - - - - px Width - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 75 - true - true - - - - Security note: Elevated applications running under the supervision of Sandboxie, with an admin or system token, have more opportunities to bypass isolation and modify the system outside the sandbox. - - - true - - - - - - - Sandboxed window border: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Allow MSIServer to run with a sandboxed system token and apply other exceptions if required - - - - - - - Note: Msi Installer Exemptions should not be required, but if you encounter issues installing a msi package which you trust, this option may help the installation complete successfully. You can also try disabling drop admin rights. - - - true - - - @@ -444,6 +408,155 @@ + + + Admin Rights + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 75 + true + true + + + + (Recommended) + + + + + + + + 75 + true + true + + + + Protect the system from sandboxed processes + + + Elevation restrictions + + + + + + + + 75 + true + true + + + + CAUTION: When running under the built in administrator, processes can not drop administrative privileges. + + + true + + + + + + + Make applications think they are running elevated (allows to run installers safely) + + + + + + + Note: Msi Installer Exemptions should not be required, but if you encounter issues installing a msi package which you trust, this option may help the installation complete successfully. You can also try disabling drop admin rights. + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 20 + 20 + + + + + + + + + 75 + true + true + + + + Security note: Elevated applications running under the supervision of Sandboxie, with an admin or system token, have more opportunities to bypass isolation and modify the system outside the sandbox. + + + true + + + + + + + Drop rights from Administrators and Power Users groups + + + + + + + Allow MSIServer to run with a sandboxed system token and apply other exceptions if required + + + + + + + Access Restrictions @@ -454,7 +567,7 @@ - Open Windows Credentials Store + Open Windows Credentials Store (user mode) @@ -605,7 +718,7 @@ - Prevent change to network and firewall parameters + Prevent change to network and firewall parameters (user mode) @@ -1255,7 +1368,7 @@ If leader processes are defined, all others are treated as lingering processes.< - Network Restrictions + Network Firewall Rules @@ -1414,200 +1527,318 @@ If leader processes are defined, all others are treated as lingering processes.< - - - - - - 0 - 0 - + + + 0 + + + + Resource Access Rules + + + + 3 - - - 0 - 23 - + + 6 - - Add File/Folder + + 3 - - - - - - - 0 - 0 - + + 0 - - - 0 - 23 - + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + Add Wnd Class + + + + + + + Configure which processes can access what resources. Double click on an entry to edit it. +'Open' File and Key access only applies to program binaries located outside the sandbox. +You can use 'Open for All' instead to make it apply to all programs, or change this behaviour in the Policies tab. + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + Add COM Object + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + Add Reg Key + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + Add IPC Path + + + + + + + true + + + + Type + + + + + Program + + + + + Access + + + + + Path + + + + + + + + Show Templates + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + Add File/Folder + + + + + + + + + + Resource Access Policies + + + + 9 - - Add Wnd Class + + 9 - - - - - - Move Down + + 9 - - - - - - Qt::Vertical + + 9 - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - Add IPC Path - - - - - - - Show Templates - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - Add Reg Key - - - - - - - true - - - - Type - - - - - Program - - - - - Access - - - - - Path - - - - - - - - Remove - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - Add COM Object - - - - - - - Move Up - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Configure which processes can access what resources. Double click on an entry to edit it. -'Direct' File and Key access only applies to program binaries located outside the sandbox. -For files access you can use 'Direct All' instead to make it apply to all programs. - - - - - - - Apply Close...=!<program>,... directives also to all binaries located in the sandboxed. - - - - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + The rule specificity is a measure to how well a given rule matches a particular path, simply put the specificity is the length of characters from the begin of the path up to and including the last matching non-wildcard sub string. A rule which matches only file types like "*.tmp" would those have the highest specificity as it would always match the entire file path. +The process match level has a higher priority than the specificity, it describes how a rule applies to a given process, rules applying by process name, or group, have the strongest match level, followed by the match by negation (i.e. rules applying to all processes but the given one, or group), the lowest match levels have global matches, i.e. rules that apply to any process. + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Priorize rules based on their Specificity and Process Match Level + + + + + + + Privacy Mode, block file and registry access to all locations except the generic system ones + + + + + + + + 75 + true + true + + + + Access Mode + + + + + + + When the Privacy Mode is enabled, sandboxed processes will be only able to read C:\Windows\*, C:\Program Files\*, and parts of the HKLM registry, all other locations will need explicit access to be readable and/or writable. In this mode, Rule Specificity is always enabled. + + + true + + + + + + + + 75 + true + true + + + + Rule Policies + + + + + + + Apply Close...=!<program>,... rules also to all binaries located in the sandboxed. + + + + + + + Apply File and Key Open directives only to binaries located outside the sandbox. + + + + + + + + @@ -1760,7 +1991,56 @@ For files access you can use 'Direct All' instead to make it apply to all progra + + + + Don't alter window class names created by sandboxed programs + + + + + + + Start the sandboxed RpcSs as a SYSTEM process (not recommended) + + + + + + + Limit access to the emulated service control manager to privileged processes + + + + + + Do not start sandboxed services using a system token (recommended) + + + + + + + + 75 + true + true + + + + Compatibility + + + + + + + Allow use of nested job objects (experimental, works on Windows 8 and later) + + + + Qt::Vertical @@ -1773,17 +2053,103 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - + + - Don't alter window class names created by sandboxed programs + Open access to COM infrastructure (not recommended) - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + - Do not start sandboxed services using a system token (recommended) + Force usage of custom dummy Manifest files (legacy behaviour) + + + + + + + Add sandboxed processes to job objects (recommended) + + + + + + + + 75 + true + true + + + + Protect the sandbox integrity itself + + + COM isolation + + + + + + + Emulate sandboxed window station for all processes + + + + + + + Drop critical privileges from processes running with a SYSTEM token + + + + + + + + 75 + true + true + + + + (Security Critical) + + + + + + + Protect sandboxed SYSTEM processes from unprivileged processes + + + + + + + + 75 + true + true + + + + (Security Critical) @@ -1804,61 +2170,6 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - Force usage of custom dummy Manifest files (legacy behaviour) - - - - - - - Limit access to the emulated service control manager to privileged processes - - - - - - - - 75 - true - true - - - - Compatibility - - - - - - - Emulate sandboxed window station for all processes - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Allow use of nested job objects (experimental, works on Windows 8 and later) - - - @@ -1870,28 +2181,61 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - + + - Allow sandboxed programs to manage Hardware/Devices + Security Isolation through the usage of a heavily restricted process token is Sandboxie's primary means of enforcing sandbox restrictions, when this is disabled the box is operated in the application compartment mode, i.e. it’s no longer providing reliable security, just simple application compartmentalization. + + + true - - - - Open access to Windows Security Account Manager - - - - + Open access to Windows Local Security Authority - + + + + Allow sandboxed programs to manage Hardware/Devices + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Disable Security Isolation (experimental) + + + + + + + Various advanced isolation features can break compatibility with some applications. If you are using this sandbox <b>NOT for Security</b> but for simple application portability, by changing these options you can restore compatibility by sacrificing some security. + + + true + + + + Qt::Horizontal @@ -1904,7 +2248,58 @@ For files access you can use 'Direct All' instead to make it apply to all progra - + + + + Open access to Windows Security Account Manager + + + + + + + + 75 + true + true + + + + Protect the sandbox integrity itself + + + Security Isolation & Filtering + + + + + + + Disable Security Filtering (not recommended) + + + + + + + Security Filtering used by Sandboxie to enforce filesystem and registry access restrictions, as well as to restrict process access. + + + true + + + + + + + The below options can be used safely when you don't grant admin rights. + + + true + + + + @@ -1921,29 +2316,6 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Various advanced isolation features can break compatibility, with some applications, if you are using this sandbox <b>NOT for Security</b> but for simple application portability by changing these options you can restore compatibility by sacrificing some security.<br>These options can be used securely when you don't grant any of the sandboxed process admin rights. - - - true - - - @@ -2336,8 +2708,8 @@ instead of "*". 0 0 - 98 - 28 + 63 + 16 @@ -2711,8 +3083,6 @@ Please note that this values are currently user specific and saved globally for btnAddIPC btnAddWnd btnAddCOM - btnMoveUp - btnMoveDown chkShowAccessTmpl btnDelAccess chkAutoRecovery @@ -2725,7 +3095,6 @@ Please note that this values are currently user specific and saved globally for tabsAdvanced chkPreferExternalManifest chkNoWindowRename - chkRestrictServices lstAutoExec btnAddAutoExec btnDelAutoExec diff --git a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui index 68edff4b..75041fbe 100644 --- a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui +++ b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui @@ -315,7 +315,28 @@ - + + + + Portable root folder + + + + + + + + 75 + true + true + + + + Sandbox default + + + + Qt::Vertical @@ -328,127 +349,6 @@ - - - - - - - Sandbox <a href="sbie://docs/ipcrootpath">ipc root</a>: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - Sandbox <a href="sbie://docs/filerootpath">file system root</a>: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - Portable root folder - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - 23 - 16777215 - - - - ... - - - - - - - Sandbox <a href="sbie://docs/keyrootpath">registry root</a>: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - Use Windows Filtering Platform to restrict network access (experimental) - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Separate user folders - - - @@ -463,17 +363,124 @@ - - - - - 75 - true - true - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Sandbox <a href="sbie://docs/keyrootpath">registry root</a>: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + Activate Kernel Mode Object Filtering (experimental) + + + + + + + + 23 + 16777215 + - Sandbox default + ... + + + + + + + Use Windows Filtering Platform to restrict network access (experimental) + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Sandbox <a href="sbie://docs/ipcrootpath">ipc root</a>: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + + + + Separate user folders + + + + + + + Sandbox <a href="sbie://docs/filerootpath">file system root</a>: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true diff --git a/SandboxiePlus/SandMan/Models/SbieModel.cpp b/SandboxiePlus/SandMan/Models/SbieModel.cpp index 9d82a9a7..b2f6fc2c 100644 --- a/SandboxiePlus/SandMan/Models/SbieModel.cpp +++ b/SandboxiePlus/SandMan/Models/SbieModel.cpp @@ -128,7 +128,7 @@ QList CSbieModel::Sync(const QMap& BoxList, cons New[pNode->Path].append(pNode); Added.append(ID); - pNode->Icon = theGUI->GetBoxIcon(false); + pNode->Icon = theGUI->GetBoxIcon(CSandBoxPlus::eDefault, false); pNode->IsBold = true; pNode->Values[eName].Raw = Group; @@ -203,7 +203,7 @@ QList CSbieModel::Sync(const QMap& BoxList, cons pNode->inUse = inUse; pNode->boxType = boxType; //pNode->Icon = pNode->inUse ? m_BoxInUse : m_BoxEmpty; - pNode->Icon = theGUI->GetBoxIcon(inUse, boxType); + pNode->Icon = theGUI->GetBoxIcon(boxType, inUse); Changed = 1; // set change for first column } diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-empty.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-empty.png index 5a0d03af..6cb88c59 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-empty.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-empty.png differ diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-full.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-full.png index e3a27335..0fea5cc3 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-full.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-b-full.png differ diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-empty.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-empty.png index d23c6b75..1da9f210 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-empty.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-empty.png differ diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-full.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-full.png index 2a60113a..133d8278 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-full.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-c-full.png differ diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-empty.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-empty.png index 9b229cdf..d457977f 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-empty.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-empty.png differ diff --git a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-full.png b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-full.png index f5321110..a9538854 100644 Binary files a/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-full.png and b/SandboxiePlus/SandMan/Resources/Boxes/sandbox-r-full.png differ diff --git a/SandboxiePlus/SandMan/SandMan.cpp b/SandboxiePlus/SandMan/SandMan.cpp index 5d3b2684..6013a31f 100644 --- a/SandboxiePlus/SandMan/SandMan.cpp +++ b/SandboxiePlus/SandMan/SandMan.cpp @@ -494,7 +494,7 @@ void CSandMan::CreateToolBar() m_pToolBar->addSeparator(); m_pToolBar->addWidget(new QLabel(" ")); - QLabel* pSupportLbl = new QLabel(tr("Support Sandboxie-Plus on Patreon")); + QLabel* pSupportLbl = new QLabel("Support Sandboxie-Plus on Patreon"); pSupportLbl->setTextInteractionFlags(Qt::TextBrowserInteraction); connect(pSupportLbl, SIGNAL(linkActivated(const QString&)), this, SLOT(OnHelp())); m_pToolBar->addWidget(pSupportLbl); @@ -565,17 +565,46 @@ void CSandMan::closeEvent(QCloseEvent *e) QApplication::quit(); } -QIcon CSandMan::GetBoxIcon(bool inUse, int boxType) +QIcon CSandMan::GetBoxIcon(int boxType, bool inUse) { EBoxColors color = eYellow; switch (boxType) { - case CSandBoxPlus::eHardened: color = eOrang; break; - //case CSandBoxPlus::eHasLogApi: color = eRed; break; - case CSandBoxPlus::eInsecure: color = eMagenta; break; + case CSandBoxPlus::eHardenedPlus: color = eRed; break; + case CSandBoxPlus::eHardened: color = eOrang; break; + case CSandBoxPlus::eDefaultPlus: color = eBlue; break; + case CSandBoxPlus::eDefault: color = eYellow; break; + case CSandBoxPlus::eAppBoxPlus: color = eCyan; break; + case CSandBoxPlus::eAppBox: color = eGreen; break; + case CSandBoxPlus::eInsecure: color = eMagenta; break; } return inUse ? m_BoxIcons[color].second : m_BoxIcons[color].first; } +QString CSandMan::GetBoxDescription(int boxType) +{ + QString Info; + + switch (boxType) { + case CSandBoxPlus::eHardenedPlus: + case CSandBoxPlus::eHardened: + Info = tr("This box provides enhanced security isolation, it is suitable to test untrusted software."); + break; + case CSandBoxPlus::eDefaultPlus: + case CSandBoxPlus::eDefault: + Info = tr("This box provides standard isolation, it is suitable to run your software to enhance security."); + break; + case CSandBoxPlus::eAppBoxPlus: + case CSandBoxPlus::eAppBox: + Info = tr("This box does not enforce isolation, it is intended to be used as an application compartment for software virtualization only."); + break; + } + + if(boxType == CSandBoxPlus::eHardenedPlus || boxType == CSandBoxPlus::eDefaultPlus || boxType == CSandBoxPlus::eAppBoxPlus) + Info.append(tr("\n\nThis box prevents access to all user data locations, except explicitly granted in the Resource Access options.")); + + return Info; +} + bool CSandMan::IsFullyPortable() { QString SbiePath = theAPI->GetSbiePath(); @@ -945,6 +974,10 @@ void CSandMan::OnStatusChanged() g_FeatureFlags = theAPI->GetFeatureFlags(); + // if teh certificate is valid but the driver does not report it being active it means its expired + if (!g_Certificate.isEmpty() && (g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { + OnLogMessage(tr("The supporter certificate is expired")); + } SB_STATUS Status = theAPI->ReloadBoxes(); @@ -1024,7 +1057,7 @@ void CSandMan::SetupHotKeys() m_pHotkeyManager->unregisterAllHotkeys(); if (theConf->GetBool("Options/EnablePanicKey", false)) - m_pHotkeyManager->registerHotkey(theConf->GetString("Options/PanicKeySequence", "Shift+Pause"), HK_PANIC); + m_pHotkeyManager->registerHotkey(theConf->GetString("Options/PanicKeySequence", "Ctrl+Alt+Cancel"), HK_PANIC); } void CSandMan::OnHotKey(size_t id) @@ -1066,6 +1099,30 @@ void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, qui m_MissingTemplates.append(MsgData[2]); } + if ((MsgCode & 0xFFFF) == 6004) // certificat error + { + static bool bCertWarning = false; + if (!bCertWarning) { + bCertWarning = true; + + QMessageBox msgBox; + msgBox.setTextFormat(Qt::RichText); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setWindowTitle("Sandboxie-Plus"); + msgBox.setText( tr("The program %1 started in box %2 will be terminated in 5 minutes because the box was configured to use features exclusively available to project supporters.
" + "Become a project supporter, and receive a supporter certificate").arg(MsgData[2]).arg(MsgData[1])); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + /*msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + if (msgBox.exec() == QDialogButtonBox::Yes) { + OpenUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert")); + }*/ + + //bCertWarning = false; + } + // return; + } + QString Message = MsgCode != 0 ? theAPI->GetSbieMsgStr(MsgCode, m_LanguageId) : (MsgData.size() > 0 ? MsgData[0] : QString()); for (int i = 1; i < MsgData.size(); i++) @@ -1086,6 +1143,32 @@ void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, qui m_pPopUpWindow->AddLogMessage(Message, MsgCode, MsgData, ProcessId); } +bool CSandMan::CheckCertificate() +{ + if (!g_Certificate.isEmpty()) + return true; + + //if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { + // OnLogMessage(tr("The supporter certificate is expired")); + // return false; + //} + + QMessageBox msgBox; + msgBox.setTextFormat(Qt::RichText); + msgBox.setIcon(QMessageBox::Information); + msgBox.setWindowTitle("Sandboxie-Plus"); + msgBox.setText(tr("The selected feature set is only available to project supporters. Processes started in a box with this feature set enabled without a supporter certificate will be terminated after 5 minutes.
" + "Become a project supporter, and receive a supporter certificate")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + /*msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + if (msgBox.exec() == QDialogButtonBox::Yes) { + OpenUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert")); + }*/ + + return false; +} + void CSandMan::OnQueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data) { m_pPopUpWindow->AddUserPrompt(RequestId, Data, ClientPid); @@ -1809,7 +1892,7 @@ void CSandMan::OnSysTray(QSystemTrayIcon::ActivationReason Reason) bAdded = true; } - pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBox->GetActiveProcessCount() != 0, pBoxEx->GetType())); + pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBoxEx->GetType(), pBox->GetActiveProcessCount() != 0)); } foreach(QTreeWidgetItem* pItem, OldBoxes) @@ -1936,7 +2019,10 @@ void CSandMan::CheckForUpdates(bool bManual) Query.addQueryItem("version", QString::number(VERSION_MJR) + "." + QString::number(VERSION_MIN) + "." + QString::number(VERSION_REV) + "." + QString::number(VERSION_UPD)); Query.addQueryItem("system", "windows-" + QSysInfo::kernelVersion() + "-" + QSysInfo::currentCpuArchitecture()); Query.addQueryItem("language", QString::number(m_LanguageId)); - QString UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey"); + + QString UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("updatekey"); + if (UpdateKey.isEmpty()) + UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey"); if (!UpdateKey.isEmpty()) Query.addQueryItem("update_key", UpdateKey); Query.addQueryItem("auto", bManual ? "0" : "1"); @@ -2169,16 +2255,26 @@ void CSandMan::OnAbout() "

Version %1

" "

Copyright (c) 2020-2021 by DavidXanatos

" ).arg(GetVersion()); + + QString CertInfo; + if (!g_Certificate.isEmpty()) { + CertInfo = tr("This copy of Sandboxie+ is certified for: %1").arg(GetArguments(g_Certificate, L'\n', L':').value("name")); + } else { + CertInfo = tr("Sandboxie+ is free for personal and non-commercial use."); + } + QString AboutText = tr( - "

Sandboxie-Plus is an open source continuation of Sandboxie.

" - "

" - "

Visit sandboxie-plus.com for more information.

" - "

" - "

" - "

" - "

Icons from icons8.com

" - "

" - ); + "Sandboxie-Plus is an open source continuation of Sandboxie." + "Visit sandboxie-plus.com for more information.
" + "
" + "%3
" + "
" + "Driver version: %1
" + "Features: %2
" + "
" + "Icons from icons8.com" + ).arg(theAPI->GetVersion()).arg(theAPI->GetFeatureStr()).arg(CertInfo); + QMessageBox *msgBox = new QMessageBox(this); msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->setWindowTitle(tr("About Sandboxie-Plus")); @@ -2301,14 +2397,6 @@ QT_TRANSLATE_NOOP("QPlatformTheme", "&Yes"), QT_TRANSLATE_NOOP("QPlatformTheme", "&No"), }; -// Make sure that CSandBox strings won't be marked as vanished in all .ts files, even after running lupdate - -static const char* CSandBox_strings[] = { -QT_TRANSLATE_NOOP("CSandBox", "Waiting for folder: %1"), -QT_TRANSLATE_NOOP("CSandBox", "Deleting folder: %1"), -QT_TRANSLATE_NOOP("CSandBox", "Merging folders: %1 >> %2"), -QT_TRANSLATE_NOOP("CSandBox", "Finishing Snapshot Merge..."), -}; ////////////////////////////////////////////////////////////////////////////////////////// // WinSpy based window finder diff --git a/SandboxiePlus/SandMan/SandMan.h b/SandboxiePlus/SandMan/SandMan.h index a9891431..425fa9c5 100644 --- a/SandboxiePlus/SandMan/SandMan.h +++ b/SandboxiePlus/SandMan/SandMan.h @@ -52,7 +52,7 @@ public: void RunSandboxed(const QStringList& Commands, const QString& BoxName); - QIcon GetBoxIcon(bool inUse, int boxType = 0); + QIcon GetBoxIcon(int boxType, bool inUse = false); QString GetBoxDescription(int boxType); bool CheckCertificate(); diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.cpp b/SandboxiePlus/SandMan/SbiePlusAPI.cpp index 177bd198..2f6e10f4 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.cpp +++ b/SandboxiePlus/SandMan/SbiePlusAPI.cpp @@ -86,7 +86,9 @@ CSandBoxPlus::CSandBoxPlus(const QString& BoxName, class CSbieAPI* pAPI) : CSand m_bDropRights = false; - m_bSecurityRestricted = false; + m_bSecurityEnhanced = false; + m_bPrivacyEnhanced = false; + m_bApplicationCompartment = false; m_iUnsecureDebugging = 0; m_SuspendRecovery = false; @@ -142,7 +144,9 @@ void CSandBoxPlus::UpdateDetails() //GetBool("SandboxieLogon", false) - m_bSecurityRestricted = m_iUnsecureDebugging == 0 && (GetBool("DropAdminRights", false)); + m_bSecurityEnhanced = m_iUnsecureDebugging == 0 && (GetBool("DropAdminRights", false)); + m_bApplicationCompartment = GetBool("NoSecurityIsolation", false); + m_bPrivacyEnhanced = (m_iUnsecureDebugging != 1 || m_bApplicationCompartment) && (GetBool("UsePrivacyMode", false)); // app compartments are inhenrently insecure CSandBox::UpdateDetails(); } @@ -154,37 +158,6 @@ void CSandBoxPlus::CloseBox() m_SuspendRecovery = false; } -QString CSandBoxPlus::GetStatusStr() const -{ - if (!m_IsEnabled) - return tr("Disabled"); - - QStringList Status; - - if (IsEmpty()) - Status.append(tr("Empty")); - - if (m_iUnsecureDebugging == 1) - Status.append(tr("NOT SECURE (Debug Config)")); - else if (m_iUnsecureDebugging == 2) - Status.append(tr("Reduced Isolation")); - else if(m_bSecurityRestricted) - Status.append(tr("Enhanced Isolation")); - - if (m_bLogApiFound) - Status.append(tr("API Log")); - if (m_bINetBlocked) - Status.append(tr("No INet")); - if (m_bSharesAllowed) - Status.append(tr("Net Share")); - if (m_bDropRights) - Status.append(tr("No Admin")); - - if (Status.isEmpty()) - return tr("Normal"); - return Status.join(", "); -} - bool CSandBoxPlus::CheckUnsecureConfig() const { if (GetBool("OriginalToken", false)) return true; @@ -195,10 +168,68 @@ bool CSandBoxPlus::CheckUnsecureConfig() const if(GetBool("UnfilteredToken", false)) return true; if (GetBool("DisableFileFilter", false)) return true; if (GetBool("DisableKeyFilter", false)) return true; + if (GetBool("DisableObjectFilter", false)) return true; + if (GetBool("StripSystemPrivileges", false)) return true; return false; } +QString CSandBoxPlus::GetStatusStr() const +{ + if (!m_IsEnabled) + return tr("Disabled"); + + QStringList Status; + + if (IsEmpty()) + Status.append(tr("Empty")); + + if (m_bApplicationCompartment) + Status.append(tr("Application Compartment")); + else if (m_iUnsecureDebugging == 1) + Status.append(tr("NOT SECURE")); + else if (m_iUnsecureDebugging == 2) + Status.append(tr("Reduced Isolation")); + else if(m_bSecurityEnhanced) + Status.append(tr("Enhanced Isolation")); + + if(m_bPrivacyEnhanced) + Status.append(tr("Privacy Enhanced")); + + if (m_bLogApiFound) + Status.append(tr("API Log")); + if (m_bINetBlocked) + Status.append(tr("No INet")); + if (m_bSharesAllowed) + Status.append(tr("Net Share")); + if (m_bDropRights && !m_bSecurityEnhanced) + Status.append(tr("No Admin")); + + if (Status.isEmpty()) + return tr("Normal"); + return Status.join(", "); +} + +CSandBoxPlus::EBoxTypes CSandBoxPlus::GetType() const +{ + if (m_bApplicationCompartment && m_bPrivacyEnhanced) + return eAppBoxPlus; + if (m_bApplicationCompartment) + return eAppBox; + + if (m_iUnsecureDebugging != 0) + return eInsecure; + + if (m_bSecurityEnhanced && m_bPrivacyEnhanced) + return eHardenedPlus; + if (m_bSecurityEnhanced) + return eHardened; + + if (m_bPrivacyEnhanced) + return eDefaultPlus; + return eDefault; +} + void CSandBoxPlus::SetLogApi(bool bEnable) { if (bEnable) @@ -389,17 +420,6 @@ int CSandBoxPlus::IsLeaderProgram(const QString& ProgName) return FindInStrList(Programs, ProgName) != Programs.end() ? 1 : 0; } -CSandBoxPlus::EBoxTypes CSandBoxPlus::GetType() const -{ - //if (m_bLogApiFound) - // return eHasLogApi; - if (m_iUnsecureDebugging != 0) - return eInsecure; - if (m_bSecurityRestricted) - return eHardened; - return eDefault; -} - /////////////////////////////////////////////////////////////////////////////// // CSbieProcess // diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.h b/SandboxiePlus/SandMan/SbiePlusAPI.h index b6057a00..ca661cce 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.h +++ b/SandboxiePlus/SandMan/SbiePlusAPI.h @@ -54,7 +54,6 @@ public: virtual void SetDropRights(bool bEnable); virtual bool IsDropRights() const { return m_bDropRights; } - virtual bool IsSecurityRestricted() const { return m_bSecurityRestricted; } virtual bool IsUnsecureDebugging() const { return m_iUnsecureDebugging != 0; } virtual void BlockProgram(const QString& ProgName); @@ -74,12 +73,15 @@ public: enum EBoxTypes { - eDefault = 0, + eHardenedPlus, eHardened, - //eHasLogApi, + eDefaultPlus, + eDefault, + eAppBoxPlus, + eAppBox, eInsecure, - eUnknown = -1 + eUnknown }; EBoxTypes GetType() const; @@ -99,12 +101,15 @@ protected: bool m_bSharesAllowed; bool m_bDropRights; - bool m_bSecurityRestricted; + bool m_bSecurityEnhanced; + bool m_bPrivacyEnhanced; + bool m_bApplicationCompartment; int m_iUnsecureDebugging; bool m_SuspendRecovery; QSet m_RecentPrograms; + }; /////////////////////////////////////////////////////////////////////////////// diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp index 2827d2e9..098ed94a 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.cpp +++ b/SandboxiePlus/SandMan/Views/SbieView.cpp @@ -126,6 +126,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) m_pMenuPresetsShares = m_pMenuPresets->addAction(tr("Allow Network Shares"), this, SLOT(OnSandBoxAction())); m_pMenuPresetsShares->setCheckable(true); + m_pMenuDuplicate = m_pMenu->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuRename = m_pMenu->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction())); m_iMoveTo = m_pMenu->actions().count(); m_pMenuMoveTo = m_pMenu->addMenu(CSandMan::GetIcon("Group"), tr("Move Box/Group")); @@ -356,6 +357,7 @@ void CSbieView::UpdateMenu() UpdateRunMenu(pBox); m_pMenuMkLink->setEnabled(iSandBoxeCount == 1); + m_pMenuDuplicate->setEnabled(iSandBoxeCount == 1); m_pMenuRename->setEnabled(iSandBoxeCount == 1); m_pMenuRecover->setEnabled(iSandBoxeCount == 1); @@ -875,6 +877,43 @@ void CSbieView::OnSandBoxAction(QAction* Action) pSnapshotsWindow->show(); } } + else if (Action == m_pMenuDuplicate) + { + QString OldValue = SandBoxes.first()->GetName().replace("_", " "); + QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new name for the duplicated Sandbox."), QLineEdit::Normal, tr("%1 Copy").arg(OldValue)); + if (Value.isEmpty() || Value == OldValue) + return; + + QString Name = Value.replace(" ", "_"); + SB_STATUS Status = theAPI->CreateBox(Name, false); + + if (!Status.IsError()) + { + CSandBoxPtr pBox = theAPI->GetBoxByName(Value); + + QList> Settings; + CSandBoxPtr pSrcBox = theAPI->GetBoxByName(SandBoxes.first()->GetName()); + qint32 status = 0; + if (!pSrcBox.isNull()) Settings = pSrcBox->GetIniSection(&status); + if (Settings.isEmpty()) + Status = SB_ERR(SB_FailedCopyConf, QVariantList() << SandBoxes.first()->GetName() << (quint32)status); + else + { + for (QList>::iterator I = Settings.begin(); I != Settings.end(); ++I) + { + Status = theAPI->SbieIniSet(Name, I->first, I->second, CSbieAPI::eIniInsert, false); + if (Status.IsError()) + break; + } + } + + theAPI->CommitIniChanges(); + theAPI->ReloadConfig(); + theAPI->ReloadBoxes(); + } + + Results.append(Status); + } else if (Action == m_pMenuRename) { QString OldValue = SandBoxes.first()->GetName().replace("_", " "); diff --git a/SandboxiePlus/SandMan/Views/SbieView.h b/SandboxiePlus/SandMan/Views/SbieView.h index be68eed6..8b2297be 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.h +++ b/SandboxiePlus/SandMan/Views/SbieView.h @@ -116,6 +116,7 @@ private: QAction* m_pMenuRecover; QAction* m_pMenuCleanUp; QAction* m_pMenuRemove; + QAction* m_pMenuDuplicate; QAction* m_pMenuMoveUp; //QAction* m_pMenuMoveBy; QAction* m_pMenuMoveDown; diff --git a/SandboxiePlus/SandMan/Views/TraceView.cpp b/SandboxiePlus/SandMan/Views/TraceView.cpp index 393cc675..77bfd547 100644 --- a/SandboxiePlus/SandMan/Views/TraceView.cpp +++ b/SandboxiePlus/SandMan/Views/TraceView.cpp @@ -171,7 +171,7 @@ int CTraceView__Filter(const CTraceEntryPtr& pEntry, void* params) if (This->m_FilterExp.isValid()) { if (!pEntry->GetMessage().contains(This->m_FilterExp) - //&& !pEntry->GetTypeStr().contains(This->m_FilterExp) + && !pEntry->GetTypeStr().contains(This->m_FilterExp) //&& !pEntry->GetStautsStr().contains(This->m_FilterExp) && !pEntry->GetProcessName().contains(This->m_FilterExp)) Ret = This->m_bHighLight ? 1 : 0; diff --git a/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp b/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp index a0fdd446..5c3179ec 100644 --- a/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp @@ -35,19 +35,16 @@ CNewBoxWindow::CNewBoxWindow(QWidget *parent) break; } - ui.cmbTemplates->addItem(tr("Hardened")); - ui.cmbTemplates->addItem(tr("Default")); - ui.cmbTemplates->setCurrentIndex(eDefault); - ui.cmbTemplates->addItem(tr("Legacy Sandboxie Behaviour")); - // leniant - // open + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eHardenedPlus), tr("Hardened Sandbox with Data Protection"), (int)CSandBoxPlus::eHardenedPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eHardened), tr("Security Hardened Sandbox"), (int)CSandBoxPlus::eHardened); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eDefaultPlus), tr("Sandbox with Data Protection"), (int)CSandBoxPlus::eDefaultPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eDefault), tr("Standard Isolation Sandbox (Default)"), (int)CSandBoxPlus::eDefault); + //ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eInsecure), tr("UNSECURE Configuration (please change)"), (int)CSandBoxPlus::eInsecure); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eAppBoxPlus), tr("Application Compartment with Data Protection"), (int)CSandBoxPlus::eAppBoxPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eAppBox), tr("Application Compartment (NO Isolation)"), (int)CSandBoxPlus::eAppBox); - foreach(const CSandBoxPtr& pBox, Boxes) - ui.cmbBoxes->addItem(pBox->GetName()); - - connect(ui.radTemplate, SIGNAL(toggled(bool)), this, SLOT(OnPreset())); - connect(ui.radCopy, SIGNAL(toggled(bool)), this, SLOT(OnPreset())); - ui.radTemplate->setChecked(true); + connect(ui.cmbBoxType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnBoxTypChanged())); + ui.cmbBoxType->setCurrentIndex(3); // default ui.txtName->setFocus(); @@ -59,10 +56,14 @@ CNewBoxWindow::~CNewBoxWindow() //theConf->SetBlob("NewBoxWindow/Window_Geometry", saveGeometry()); } -void CNewBoxWindow::OnPreset() +void CNewBoxWindow::OnBoxTypChanged() { - ui.cmbTemplates->setEnabled(ui.radTemplate->isChecked()); - ui.cmbBoxes->setEnabled(ui.radCopy->isChecked()); + int BoxType = ui.cmbBoxType->currentData().toInt(); + + ui.lblBoxInfo->setText(theGUI->GetBoxDescription(BoxType)); + + if(BoxType != CSandBoxPlus::eDefault && BoxType != CSandBoxPlus::eHardened) + theGUI->CheckCertificate(); } void CNewBoxWindow::CreateBox() @@ -70,50 +71,36 @@ void CNewBoxWindow::CreateBox() m_Name = ui.txtName->text(); m_Name.replace(" ", "_"); - bool bCopy = ui.radCopy->isChecked(); + int BoxType = ui.cmbBoxType->currentData().toInt(); - SB_STATUS Status = theAPI->CreateBox(m_Name, !bCopy); + SB_STATUS Status = theAPI->CreateBox(m_Name, true); if (!Status.IsError()) { CSandBoxPtr pBox = theAPI->GetBoxByName(m_Name); - if (bCopy) + switch (BoxType) { - QList> Settings; - CSandBoxPtr pSrcBox = theAPI->GetBoxByName(ui.cmbBoxes->currentText()); - qint32 status = 0; - if(!pSrcBox.isNull()) Settings = pSrcBox->GetIniSection(&status); - if (Settings.isEmpty()) - Status = SB_ERR(SB_FailedCopyConf, QVariantList() << ui.cmbBoxes->currentText() << (quint32)status); - else - { - for (QList>::iterator I = Settings.begin(); I != Settings.end(); ++I) - { - Status = theAPI->SbieIniSet(m_Name, I->first, I->second, CSbieAPI::eIniInsert); - if (Status.IsError()) - break; - } - } - - theAPI->ReloadConfig(); - theAPI->ReloadBoxes(); - } - else switch (ui.cmbTemplates->currentIndex()) - { - case eHardened: - pBox.objectCast()->SetBool("DropAdminRights", true); - //pBox.objectCast()->SetBool("FakeAdminRights", true); // Note: making the app think it has admin rights has no security downsides, but it can help with compatibility - pBox.objectCast()->SetBool("ClosePrintSpooler", true); + case CSandBoxPlus::eHardenedPlus: + case CSandBoxPlus::eHardened: + //pBox->SetBool("NoSecurityIsolation", false); + pBox->SetBool("DropAdminRights", true); + //pBox->SetBool("MsiInstallerExemptions", false); + pBox->SetBool("UsePrivacyMode", BoxType == CSandBoxPlus::eHardenedPlus); break; - case eLegacy: - pBox.objectCast()->SetBool("UnrestrictedSCM", true); - //pBox.objectCast()->SetBool("ExposeBoxedSystem", true); - //pBox.objectCast()->SetBool("RunServicesAsSystem", true); // legacy behaviour, but there should be no normal use cases which require this - pBox.objectCast()->SetBool("OpenPrintSpooler", true); - pBox.objectCast()->InsertText("Template", "OpenSmartCard"); - default: - pBox.objectCast()->InsertText("Template", "OpenBluetooth"); // most Unity games needs that, besides most modern games are Unity based + case CSandBoxPlus::eDefaultPlus: + case CSandBoxPlus::eDefault: + //pBox->SetBool("NoSecurityIsolation", false); + //pBox->SetBool("DropAdminRights", false); + //pBox->SetBool("MsiInstallerExemptions", false); + //pBox->SetBool("RunServicesAsSystem", false); + pBox->SetBool("UsePrivacyMode", BoxType == CSandBoxPlus::eDefaultPlus); + break; + case CSandBoxPlus::eAppBoxPlus: + case CSandBoxPlus::eAppBox: + pBox->SetBool("NoSecurityIsolation", true); + //pBox->SetBool("RunServicesAsSystem", true); + pBox->SetBool("UsePrivacyMode", BoxType == CSandBoxPlus::eAppBoxPlus); break; } } diff --git a/SandboxiePlus/SandMan/Windows/NewBoxWindow.h b/SandboxiePlus/SandMan/Windows/NewBoxWindow.h index a7b9db4f..d72351b1 100644 --- a/SandboxiePlus/SandMan/Windows/NewBoxWindow.h +++ b/SandboxiePlus/SandMan/Windows/NewBoxWindow.h @@ -17,17 +17,7 @@ public: private slots: void CreateBox(); - void OnPreset(); - -protected: - enum ETemplates - { - eHardened = 0, - eDefault, - eLegacy, - eLenient, - eOpen - }; + void OnBoxTypChanged(); private: Ui::NewBoxWindow ui; diff --git a/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp b/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp index 8c9c0dd5..69999eb5 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsAccess.cpp @@ -11,6 +11,13 @@ void COptionsWindow::CreateAccess() { + // Resource Access + connect(ui.chkPrivacy, SIGNAL(clicked(bool)), this, SLOT(OnAccessChanged())); + connect(ui.chkUseSpecificity, SIGNAL(clicked(bool)), this, SLOT(OnAccessChanged())); + connect(ui.chkCloseForBox, SIGNAL(clicked(bool)), this, SLOT(OnAccessChanged())); + connect(ui.chkNoOpenForBox, SIGNAL(clicked(bool)), this, SLOT(OnAccessChanged())); + // + connect(ui.btnAddFile, SIGNAL(clicked(bool)), this, SLOT(OnAddFile())); QMenu* pFileBtnMenu = new QMenu(ui.btnAddFile); pFileBtnMenu->addAction(tr("Browse for File"), this, SLOT(OnBrowseFile())); @@ -21,9 +28,6 @@ void COptionsWindow::CreateAccess() connect(ui.btnAddIPC, SIGNAL(clicked(bool)), this, SLOT(OnAddIPC())); connect(ui.btnAddWnd, SIGNAL(clicked(bool)), this, SLOT(OnAddWnd())); connect(ui.btnAddCOM, SIGNAL(clicked(bool)), this, SLOT(OnAddCOM())); - // todo: add priority by order - ui.btnMoveUp->setVisible(false); - ui.btnMoveDown->setVisible(false); connect(ui.chkShowAccessTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowAccessTmpl())); connect(ui.btnDelAccess, SIGNAL(clicked(bool)), this, SLOT(OnDelAccess())); @@ -32,6 +36,36 @@ void COptionsWindow::CreateAccess() connect(ui.treeAccess, SIGNAL(itemSelectionChanged()), this, SLOT(OnAccessSelectionChanged())); } +void COptionsWindow::OnAccessChanged() +{ + if (ui.chkPrivacy->isChecked() || ui.chkUseSpecificity->isChecked()) + theGUI->CheckCertificate(); + + UpdateAccessPolicy(); + + m_AccessChanged = true; + OnOptChanged(); +} + +void COptionsWindow::UpdateAccessPolicy() +{ + if (ui.chkPrivacy->isChecked()) { + ui.chkUseSpecificity->setEnabled(false); + ui.chkUseSpecificity->setChecked(true); + + ui.chkCloseForBox->setEnabled(false); + ui.chkCloseForBox->setChecked(false); + ui.chkNoOpenForBox->setEnabled(false); + ui.chkNoOpenForBox->setChecked(false); + } + else { + ui.chkUseSpecificity->setEnabled(true); + + ui.chkCloseForBox->setEnabled(true); + ui.chkNoOpenForBox->setEnabled(true); + } +} + QTreeWidgetItem* COptionsWindow::GetAccessEntry(EAccessType Type, const QString& Program, EAccessMode Mode, const QString& Path) { for (int i = 0; i < ui.treeAccess->topLevelItemCount(); i++) @@ -51,6 +85,7 @@ void COptionsWindow::SetAccessEntry(EAccessType Type, const QString& Program, EA if (GetAccessEntry(Type, Program, Mode, Path) != NULL) return; // already set m_AccessChanged = true; + OnOptChanged(); AddAccessEntry(Type, Mode, Program, Path); } @@ -60,6 +95,7 @@ void COptionsWindow::DelAccessEntry(EAccessType Type, const QString& Program, EA { delete pItem; m_AccessChanged = true; + OnOptChanged(); } } @@ -67,17 +103,21 @@ QString COptionsWindow::AccessTypeToName(EAccessEntry Type) { switch (Type) { + case eNormalFilePath: return "NormalFilePath"; case eOpenFilePath: return "OpenFilePath"; case eOpenPipePath: return "OpenPipePath"; case eClosedFilePath: return "ClosedFilePath"; case eReadFilePath: return "ReadFilePath"; case eWriteFilePath: return "WriteFilePath"; + case eNormalKeyPath: return "NormalKeyPath"; case eOpenKeyPath: return "OpenKeyPath"; + case eOpenConfPath: return "OpenConfPath"; case eClosedKeyPath: return "ClosedKeyPath"; case eReadKeyPath: return "ReadKeyPath"; case eWriteKeyPath: return "WriteKeyPath"; + case eNormalIpcPath: return "NormalIpcPath"; case eOpenIpcPath: return "OpenIpcPath"; case eClosedIpcPath: return "ClosedIpcPath"; @@ -92,7 +132,10 @@ QString COptionsWindow::AccessTypeToName(EAccessEntry Type) void COptionsWindow::LoadAccessList() { + ui.chkPrivacy->setChecked(m_pBox->GetBool("UsePrivacyMode", false)); + ui.chkUseSpecificity->setChecked(m_pBox->GetBool("UseRuleSpecificity", false)); ui.chkCloseForBox->setChecked(m_pBox->GetBool("AlwaysCloseForBoxed", true)); + ui.chkNoOpenForBox->setChecked(m_pBox->GetBool("DontOpenForBoxed", true)); ui.treeAccess->clear(); @@ -104,6 +147,8 @@ void COptionsWindow::LoadAccessList() LoadAccessListTmpl(); + UpdateAccessPolicy(); + m_AccessChanged = false; } @@ -141,23 +186,27 @@ void COptionsWindow::ParseAndAddAccessEntry(EAccessEntry EntryType, const QStrin EAccessMode Mode; switch (EntryType) { - case eOpenFilePath: Type = eFile; Mode = eDirect; break; - case eOpenPipePath: Type = eFile; Mode = eDirectAll; break; + case eNormalFilePath: Type = eFile; Mode = eNormal; break; + case eOpenFilePath: Type = eFile; Mode = eOpen; break; + case eOpenPipePath: Type = eFile; Mode = eOpen4All; break; case eClosedFilePath: Type = eFile; Mode = eClosed; break; case eReadFilePath: Type = eFile; Mode = eReadOnly; break; case eWriteFilePath: Type = eFile; Mode = eWriteOnly; break; - case eOpenKeyPath: Type = eKey; Mode = eDirect; break; + case eNormalKeyPath: Type = eKey; Mode = eNormal; break; + case eOpenKeyPath: Type = eKey; Mode = eOpen; break; + case eOpenConfPath: Type = eKey; Mode = eOpen4All;break; case eClosedKeyPath: Type = eKey; Mode = eClosed; break; case eReadKeyPath: Type = eKey; Mode = eReadOnly; break; case eWriteKeyPath: Type = eKey; Mode = eWriteOnly; break; - case eOpenIpcPath: Type = eIPC; Mode = eDirect; break; + case eNormalIpcPath: Type = eIPC; Mode = eNormal; break; + case eOpenIpcPath: Type = eIPC; Mode = eOpen; break; case eClosedIpcPath: Type = eIPC; Mode = eClosed; break; - case eOpenWinClass: Type = eWnd; Mode = eDirect; break; + case eOpenWinClass: Type = eWnd; Mode = eOpen; break; - case eOpenCOM: Type = eCOM; Mode = eDirect; break; + case eOpenCOM: Type = eCOM; Mode = eOpen; break; case eClosedCOM: Type = eCOM; Mode = eClosed; break; case eClosedCOM_RT: Type = eCOM; Mode = eClosedRT; break; @@ -184,12 +233,13 @@ QString COptionsWindow::GetAccessModeStr(EAccessMode Mode) { switch (Mode) { - case eDirect: return tr("Direct"); - case eDirectAll: return tr("Direct All"); + case eNormal: return tr("Normal"); + case eOpen: return tr("Open"); + case eOpen4All: return tr("Open for All"); case eClosed: return tr("Closed"); case eClosedRT: return tr("Closed RT"); case eReadOnly: return tr("Read Only"); - case eWriteOnly: return tr("Hidden"); + case eWriteOnly: return tr("Boxed Only"); } return tr("Unknown"); } @@ -213,9 +263,10 @@ void COptionsWindow::OnBrowseFile() if (Value.isEmpty()) return; - AddAccessEntry(eFile, eDirect, "", Value); + AddAccessEntry(eFile, eOpen, "", Value); m_AccessChanged = true; + OnOptChanged(); } void COptionsWindow::OnBrowseFolder() @@ -224,9 +275,10 @@ void COptionsWindow::OnBrowseFolder() if (Value.isEmpty()) return; - AddAccessEntry(eFile, eDirect, "", Value); + AddAccessEntry(eFile, eOpen, "", Value); m_AccessChanged = true; + OnOptChanged(); } void COptionsWindow::AddAccessEntry(EAccessType Type, EAccessMode Mode, QString Program, const QString& Path, const QString& Template) @@ -265,8 +317,9 @@ QString COptionsWindow::MakeAccessStr(EAccessType Type, EAccessMode Mode) case eFile: switch (Mode) { - case eDirect: return "OpenFilePath"; - case eDirectAll: return "OpenPipePath"; + case eNormal: return "NormalFilePath"; + case eOpen: return "OpenFilePath"; + case eOpen4All: return "OpenPipePath"; case eClosed: return "ClosedFilePath"; case eReadOnly: return "ReadFilePath"; case eWriteOnly: return "WriteFilePath"; @@ -275,7 +328,9 @@ QString COptionsWindow::MakeAccessStr(EAccessType Type, EAccessMode Mode) case eKey: switch (Mode) { - case eDirect: return "OpenKeyPath"; + case eNormal: return "NormalKeyPath"; + case eOpen: return "OpenKeyPath"; + case eOpen4All: return "OpenConfPath"; case eClosed: return "ClosedKeyPath"; case eReadOnly: return "ReadKeyPath"; case eWriteOnly: return "WriteKeyPath"; @@ -284,20 +339,21 @@ QString COptionsWindow::MakeAccessStr(EAccessType Type, EAccessMode Mode) case eIPC: switch (Mode) { - case eDirect: return "OpenIpcPath"; + case eNormal: return "NormalIpcPath"; + case eOpen: return "OpenIpcPath"; case eClosed: return "ClosedIpcPath"; } break; case eWnd: switch (Mode) { - case eDirect: return "OpenWinClass"; + case eOpen: return "OpenWinClass"; } break; case eCOM: switch (Mode) { - case eDirect: return "OpenClsid"; + case eOpen: return "OpenClsid"; case eClosed: return "ClosedClsid"; case eClosedRT: return "ClosedRT"; } @@ -350,7 +406,7 @@ void COptionsWindow::CloseAccessEdit(QTreeWidgetItem* pItem, bool bSave) bool isGUID = pPath->text().length() == 38 && pPath->text().left(1) == "{" && pPath->text().right(1) == "}"; switch (pMode->currentData().toInt()) { - case eDirect: + case eOpen: case eClosed: if (!isGUID) { QMessageBox::critical(this, "SandboxiePlus", tr("COM objects must be specified by their GUID, like: {00000000-0000-0000-0000-000000000000}")); @@ -374,6 +430,7 @@ void COptionsWindow::CloseAccessEdit(QTreeWidgetItem* pItem, bool bSave) pItem->setData(3, Qt::UserRole, pPath->text()); m_AccessChanged = true; + OnOptChanged(); } ui.treeAccess->setItemWidget(pItem, 1, NULL); @@ -385,11 +442,11 @@ QList COptionsWindow::GetAccessModes(EAccessType Ty { switch (Type) { - case eFile: return QList() << eDirect << eDirectAll << eClosed << eReadOnly << eWriteOnly; - case eKey: return QList() << eDirect << eClosed << eReadOnly << eWriteOnly; - case eIPC: return QList() << eDirect << eClosed; - case eWnd: return QList() << eDirect; - case eCOM: return QList() << eDirect << eClosed << eClosedRT; + case eFile: return QList() << eNormal << eOpen << eOpen4All << eClosed << eReadOnly << eWriteOnly; + case eKey: return QList() << eNormal << eOpen << eOpen4All << eClosed << eReadOnly << eWriteOnly; + case eIPC: return QList() << eNormal << eOpen << eClosed; + case eWnd: return QList() << eOpen; + case eCOM: return QList() << eOpen << eClosed << eClosedRT; } return QList(); } @@ -424,9 +481,9 @@ void COptionsWindow::OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Colum QComboBox* pCombo = new QComboBox(pProgram); pCombo->addItem(tr("All Programs"), ""); - for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { - QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); - pCombo->addItem(tr("Group: %1").arg(pItem->text(0)), pItem->data(0, Qt::UserRole).toString()); + foreach(const QString Group, GetCurrentGroups()){ + QString GroupName = Group.mid(1, Group.length() - 2); + pCombo->addItem(tr("Group: %1").arg(Group), GroupName); } foreach(const QString & Name, m_Programs) @@ -469,18 +526,23 @@ void COptionsWindow::OnDelAccess() { DeleteAccessEntry(ui.treeAccess->currentItem()); m_AccessChanged = true; + OnOptChanged(); } void COptionsWindow::SaveAccessList() { + WriteAdvancedCheck(ui.chkPrivacy, "UsePrivacyMode", "y", ""); + WriteAdvancedCheck(ui.chkUseSpecificity, "UseRuleSpecificity", "y", ""); WriteAdvancedCheck(ui.chkCloseForBox, "AlwaysCloseForBoxed", "", "n"); + WriteAdvancedCheck(ui.chkNoOpenForBox, "DontOpenForBoxed", "", "n"); CloseAccessEdit(true); - QStringList Keys = QStringList() << "OpenFilePath" << "OpenPipePath" << "ClosedFilePath" << "ReadFilePath" << "WriteFilePath" - << "OpenKeyPath" << "ClosedKeyPath" << "ReadKeyPath" << "WriteKeyPath" - << "OpenIpcPath" << "ClosedIpcPath" << "OpenWinClass" << "OpenClsid" << "ClosedClsid" << "ClosedRT"; + QStringList Keys = QStringList() + << "NormalFilePath" << "OpenFilePath" << "OpenPipePath" << "ClosedFilePath" << "ReadFilePath" << "WriteFilePath" + << "NormalKeyPath" << "OpenKeyPath" << "OpenConfPath" << "ClosedKeyPath" << "ReadKeyPath" << "WriteKeyPath" + << "NormalIpcPath"<< "OpenIpcPath" << "ClosedIpcPath" << "OpenWinClass" << "OpenClsid" << "ClosedClsid" << "ClosedRT"; QMap> AccessMap; for (int i = 0; i < ui.treeAccess->topLevelItemCount(); i++) diff --git a/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp b/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp index 837860be..4bf5af46 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp @@ -15,9 +15,17 @@ void COptionsWindow::CreateAdvanced() connect(ui.chkNestedJobs, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkUseSbieWndStation, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + connect(ui.chkAddToJob, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkProtectSCM, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkRestrictServices, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); - //connect(ui.chkProtectSystem, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + connect(ui.chkElevateRpcss, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + connect(ui.chkProtectSystem, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + connect(ui.chkDropPrivileges, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + + connect(ui.chkOpenCOM, SIGNAL(clicked(bool)), this, SLOT(OnOpenCOM())); + + connect(ui.chkNoSecurityIsolation, SIGNAL(clicked(bool)), this, SLOT(OnIsolationChanged())); + connect(ui.chkNoSecurityFiltering, SIGNAL(clicked(bool)), this, SLOT(OnIsolationChanged())); connect(ui.chkOpenDevCMApi, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); //connect(ui.chkOpenLsaSSPI, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); @@ -58,10 +66,15 @@ void COptionsWindow::LoadAdvanced() ui.chkNestedJobs->setChecked(m_pBox->GetBool("AllowBoxedJobs", false)); ui.chkUseSbieWndStation->setChecked(m_pBox->GetBool("UseSbieWndStation", false)); + ui.chkAddToJob->setChecked(!m_pBox->GetBool("NoAddProcessToJob", false)); ui.chkProtectSCM->setChecked(!m_pBox->GetBool("UnrestrictedSCM", false)); ui.chkRestrictServices->setChecked(!m_pBox->GetBool("RunServicesAsSystem", false)); - //ui.chkProtectSystem->setChecked(!m_pBox->GetBool("ExposeBoxedSystem", false)); + ui.chkElevateRpcss->setChecked(m_pBox->GetBool("RunRpcssAsSystem", false)); + ui.chkProtectSystem->setChecked(!m_pBox->GetBool("ExposeBoxedSystem", false)); + ui.chkDropPrivileges->setChecked(m_pBox->GetBool("StripSystemPrivileges", true)); + ui.chkNoSecurityIsolation->setChecked(m_pBox->GetBool("NoSecurityIsolation", false)); + ui.chkNoSecurityFiltering->setChecked(m_pBox->GetBool("NoSecurityFiltering", false)); ui.chkOpenDevCMApi->setChecked(m_pBox->GetBool("OpenDevCMApi", false)); //ui.chkOpenLsaSSPI->setChecked(!m_pBox->GetBool("BlockPassword", true)); // OpenLsaSSPI @@ -102,6 +115,11 @@ void COptionsWindow::LoadAdvanced() ui.lstUsers->addItems(Users.mid(1)); ui.chkMonitorAdminOnly->setChecked(m_pBox->GetBool("MonitorAdminOnly", false)); + UpdateBoxIsolation(); + + ui.chkOpenCredentials->setEnabled(!ui.chkOpenProtectedStorage->isChecked()); + if (!ui.chkOpenCredentials->isEnabled()) ui.chkOpenCredentials->setChecked(true); + m_AdvancedChanged = false; } @@ -110,10 +128,16 @@ void COptionsWindow::SaveAdvanced() WriteAdvancedCheck(ui.chkPreferExternalManifest, "PreferExternalManifest", "y", ""); WriteAdvancedCheck(ui.chkUseSbieWndStation, "UseSbieWndStation", "y", ""); + WriteAdvancedCheck(ui.chkAddToJob, "NoAddProcessToJob", "", "y"); WriteAdvancedCheck(ui.chkProtectSCM, "UnrestrictedSCM", "", "y"); WriteAdvancedCheck(ui.chkNestedJobs, "AllowBoxedJobs", "y", ""); WriteAdvancedCheck(ui.chkRestrictServices, "RunServicesAsSystem", "", "y"); - //WriteAdvancedCheck(ui.chkProtectSystem, "ExposeBoxedSystem", "", "y"); + WriteAdvancedCheck(ui.chkElevateRpcss, "RunRpcssAsSystem", "y", ""); + WriteAdvancedCheck(ui.chkProtectSystem, "ExposeBoxedSystem", "", "y"); + WriteAdvancedCheck(ui.chkDropPrivileges, "StripSystemPrivileges", "", "n"); + + WriteAdvancedCheck(ui.chkNoSecurityIsolation, "NoSecurityIsolation", "y", ""); + WriteAdvancedCheck(ui.chkNoSecurityFiltering, "NoSecurityFiltering", "y", ""); WriteAdvancedCheck(ui.chkOpenDevCMApi, "OpenDevCMApi", "y", ""); //WriteAdvancedCheck(ui.chkOpenLsaSSPI, "BlockPassword", "n", ""); // OpenLsaSSPI @@ -158,21 +182,68 @@ void COptionsWindow::SaveAdvanced() m_AdvancedChanged = false; } -void COptionsWindow::OnAdvancedChanged() +void COptionsWindow::OnIsolationChanged() { - ui.chkOpenCredentials->setEnabled(!ui.chkOpenProtectedStorage->isChecked()); - if (!ui.chkOpenCredentials->isEnabled()) ui.chkOpenCredentials->setChecked(true); + if (ui.chkPrivacy->isChecked() || ui.chkUseSpecificity->isChecked()) + theGUI->CheckCertificate(); + + UpdateBoxIsolation(); m_AdvancedChanged = true; + OnOptChanged(); +} + +void COptionsWindow::UpdateBoxIsolation() +{ + ui.chkNoSecurityFiltering->setEnabled(ui.chkNoSecurityIsolation->isChecked()); + + ui.chkAddToJob->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + + ui.chkOpenDevCMApi->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + ui.chkOpenSamEndpoint->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + ui.chkOpenLsaEndpoint->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + + + ui.chkRawDiskRead->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); // without isolation only user mode + ui.chkRawDiskNotify->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + + ui.chkDropRights->setEnabled(!ui.chkNoSecurityIsolation->isChecked() && !theAPI->IsRunningAsAdmin()); + + ui.chkBlockNetShare->setEnabled(!ui.chkNoSecurityFiltering->isChecked()); + + ui.chkBlockSpooler->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); + ui.chkOpenSpooler->setEnabled(!ui.chkBlockSpooler->isChecked() && !ui.chkNoSecurityIsolation->isChecked()); + ui.chkPrintToFile->setEnabled(!ui.chkBlockSpooler->isChecked() && !ui.chkNoSecurityFiltering->isChecked()); + + ui.chkCloseClipBoard->setEnabled(!ui.chkNoSecurityIsolation->isChecked()); +} + +void COptionsWindow::OnAdvancedChanged() +{ + m_AdvancedChanged = true; + OnOptChanged(); +} + +void COptionsWindow::OnOpenCOM() +{ + if (ui.chkOpenCOM->isChecked()) { + SetAccessEntry(eIPC, "", eOpen, "\\RPC Control\\epmapper"); + SetAccessEntry(eIPC, "", eOpen, "*\\BaseNamedObjects*\\__ComCatalogCache__"); + } + else { + DelAccessEntry(eIPC, "", eOpen, "\\RPC Control\\epmapper"); + DelAccessEntry(eIPC, "", eOpen, "*\\BaseNamedObjects*\\__ComCatalogCache__"); + } } void COptionsWindow::OnNoWindowRename() { if (ui.chkNoWindowRename->isChecked()) - SetAccessEntry(eWnd, "", eDirect, "#"); + SetAccessEntry(eWnd, "", eOpen, "#"); else - DelAccessEntry(eWnd, "", eDirect, "#"); + DelAccessEntry(eWnd, "", eOpen, "#"); m_AdvancedChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddAutoExec() @@ -184,6 +255,7 @@ void COptionsWindow::OnAddAutoExec() ui.lstAutoExec->addItem(Process); m_AdvancedChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelAutoExec() @@ -192,6 +264,7 @@ void COptionsWindow::OnDelAutoExec() delete pItem; m_AdvancedChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddProcess() @@ -203,6 +276,7 @@ void COptionsWindow::OnAddProcess() ui.lstProcesses->addItem(Process); m_AdvancedChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelProcess() @@ -211,6 +285,7 @@ void COptionsWindow::OnDelProcess() delete pItem; m_AdvancedChanged = true; + OnOptChanged(); } #include @@ -281,6 +356,7 @@ void COptionsWindow::OnAddUser() ui.lstUsers->addItems(Users); m_AdvancedChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelUser() @@ -326,6 +402,7 @@ void COptionsWindow::OnDebugChanged() { QCheckBox* pCheck = qobject_cast(sender()); m_DebugOptions[pCheck].Changed = true; + OnOptChanged(); } void COptionsWindow::LoadDebug() diff --git a/SandboxiePlus/SandMan/Windows/OptionsForce.cpp b/SandboxiePlus/SandMan/Windows/OptionsForce.cpp index a6da670c..cbfc2bfd 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsForce.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsForce.cpp @@ -91,6 +91,7 @@ void COptionsWindow::OnForceProg() return; AddForcedEntry(Value, 1); m_ForcedChanged = true; + OnOptChanged(); } void COptionsWindow::OnForceDir() @@ -100,10 +101,12 @@ void COptionsWindow::OnForceDir() return; AddForcedEntry(Value, 2); m_ForcedChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelForce() { DeleteAccessEntry(ui.treeForced->currentItem()); m_ForcedChanged = true; + OnOptChanged(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp index 5ab451f7..394b4b15 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp @@ -18,6 +18,40 @@ void COptionsWindow::CreateGeneral() ui.cmbBoxBorder->addItem(tr("Show only when title is in focus"), "ttl"); ui.cmbBoxBorder->addItem(tr("Always show"), "on"); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eHardenedPlus), tr("Hardened Sandbox with Data Protection"), (int)CSandBoxPlus::eHardenedPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eHardened), tr("Security Hardened Sandbox"), (int)CSandBoxPlus::eHardened); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eDefaultPlus), tr("Sandbox with Data Protection"), (int)CSandBoxPlus::eDefaultPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eDefault), tr("Standard Isolation Sandbox (Default)"), (int)CSandBoxPlus::eDefault); + //ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eInsecure), tr("UNSECURE Configuration (please change)"), (int)CSandBoxPlus::eInsecure); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eAppBoxPlus), tr("Application Compartment with Data Protection"), (int)CSandBoxPlus::eAppBoxPlus); + ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eAppBox), tr("Application Compartment (NO Isolation)"), (int)CSandBoxPlus::eAppBox); + + ui.lblSupportCert->setVisible(false); + if (g_Certificate.isEmpty()) + { + ui.lblSupportCert->setVisible(true); + connect(ui.lblSupportCert, SIGNAL(linkActivated(const QString&)), theGUI, SLOT(OpenUrl(const QString&))); + + for (int i = 0; i < ui.cmbBoxType->count(); i++) + { + int BoxType = ui.cmbBoxType->itemData(i, Qt::UserRole).toInt(); + bool disabled = BoxType != CSandBoxPlus::eDefault && BoxType != CSandBoxPlus::eHardened; + + QStandardItemModel* model = qobject_cast(ui.cmbBoxType->model()); + QStandardItem* item = model->item(i); + item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled : item->flags() | Qt::ItemIsEnabled); + } + } + + + m_HoldBoxType = false; + + connect(ui.cmbBoxType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnBoxTypChanged())); + connect(ui.chkDropRights, SIGNAL(clicked(bool)), this, SLOT(UpdateBoxType())); + connect(ui.chkPrivacy, SIGNAL(clicked(bool)), this, SLOT(UpdateBoxType())); + connect(ui.chkNoSecurityIsolation, SIGNAL(clicked(bool)), this, SLOT(UpdateBoxType())); + connect(ui.chkNoSecurityFiltering, SIGNAL(clicked(bool)), this, SLOT(UpdateBoxType())); + connect(ui.cmbBoxIndicator, SIGNAL(currentIndexChanged(int)), this, SLOT(OnGeneralChanged())); connect(ui.cmbBoxBorder, SIGNAL(currentIndexChanged(int)), this, SLOT(OnGeneralChanged())); connect(ui.btnBorderColor, SIGNAL(clicked(bool)), this, SLOT(OnPickColor())); @@ -63,7 +97,6 @@ void COptionsWindow::CreateGeneral() pAutoBtnMenu->addAction(tr("Browse for Program"), this, SLOT(OnAddAutoExe())); ui.btnAddAutoExe->setPopupMode(QToolButton::MenuButtonPopup); ui.btnAddAutoExe->setMenu(pAutoBtnMenu); - connect(ui.btnAddAutoExe, SIGNAL(clicked(bool)), this, SLOT(OnAddAutoExe())); connect(ui.btnAddAutoSvc, SIGNAL(clicked(bool)), this, SLOT(OnDelAutoSvc())); connect(ui.btnDelAuto, SIGNAL(clicked(bool)), this, SLOT(OnDelAuto())); } @@ -91,19 +124,16 @@ void COptionsWindow::LoadGeneral() ui.chkBlockSpooler->setChecked(m_pBox->GetBool("ClosePrintSpooler", false)); ui.chkOpenSpooler->setChecked(m_pBox->GetBool("OpenPrintSpooler", false)); - ui.chkOpenSpooler->setEnabled(!ui.chkBlockSpooler->isChecked()); ui.chkPrintToFile->setChecked(m_pBox->GetBool("AllowSpoolerPrintToFile", false)); - ui.chkPrintToFile->setEnabled(!ui.chkBlockSpooler->isChecked()); ui.chkOpenProtectedStorage->setChecked(m_pBox->GetBool("OpenProtectedStorage", false)); - ui.chkOpenCredentials->setEnabled(!ui.chkOpenProtectedStorage->isChecked()); ui.chkOpenCredentials->setChecked(!ui.chkOpenCredentials->isEnabled() || m_pBox->GetBool("OpenCredentials", false)); ui.chkCloseClipBoard->setChecked(!m_pBox->GetBool("OpenClipboard", true)); //ui.chkOpenSmartCard->setChecked(m_pBox->GetBool("OpenSmartCard", true)); //ui.chkOpenBluetooth->setChecked(m_pBox->GetBool("OpenBluetooth", false)); ui.treeAutoStart->clear(); - foreach(const QString & Value, m_pBox->GetTextList("StartProgram", m_Template)) + foreach(const QString & Value, m_pBox->GetTextList("StartCommand", m_Template)) AddAutoRunItem(Value, 0); foreach(const QString & Value, m_pBox->GetTextList("StartService", m_Template)) AddAutoRunItem(Value, 1); @@ -173,7 +203,7 @@ void COptionsWindow::SaveGeneral() else StartProgram.append(pItem->text(1)); } - WriteTextList("StartProgram", StartProgram); + WriteTextList("StartCommand", StartProgram); WriteTextList("StartService", StartService); QStringList RunCommands; @@ -199,8 +229,6 @@ void COptionsWindow::SaveGeneral() void COptionsWindow::OnGeneralChanged() { - m_GeneralChanged = true; - ui.lblCopyLimit->setEnabled(ui.chkCopyLimit->isChecked()); ui.txtCopyLimit->setEnabled(ui.chkCopyLimit->isChecked()); ui.lblCopyLimit->setText(tr("kilobytes (%1)").arg(FormatSize(ui.txtCopyLimit->text().toULongLong() * 1024))); @@ -209,16 +237,23 @@ void COptionsWindow::OnGeneralChanged() ui.chkAutoEmpty->setEnabled(!ui.chkProtectBox->isChecked()); - ui.chkOpenSpooler->setEnabled(!ui.chkBlockSpooler->isChecked()); - ui.chkPrintToFile->setEnabled(!ui.chkBlockSpooler->isChecked()); + ui.chkOpenSpooler->setEnabled(!ui.chkBlockSpooler->isChecked() && !ui.chkNoSecurityIsolation->isChecked()); + ui.chkPrintToFile->setEnabled(!ui.chkBlockSpooler->isChecked() && !ui.chkNoSecurityFiltering->isChecked()); + + ui.chkOpenCredentials->setEnabled(!ui.chkOpenProtectedStorage->isChecked()); + if (!ui.chkOpenCredentials->isEnabled()) ui.chkOpenCredentials->setChecked(true); + + m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::OnPickColor() { - QColor color = QColorDialog::getColor(m_BorderColor, this, tr("Select color")); + QColor color = QColorDialog::getColor(m_BorderColor, this, "Select color"); if (!color.isValid()) return; m_GeneralChanged = true; + OnOptChanged(); m_BorderColor = color; ui.btnBorderColor->setStyleSheet("background-color: " + m_BorderColor.name()); } @@ -231,6 +266,7 @@ void COptionsWindow::OnAddAutoCmd() AddAutoRunItem(Value, 0); m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddAutoExe() @@ -241,6 +277,7 @@ void COptionsWindow::OnAddAutoExe() AddAutoRunItem(Value, 0); m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelAutoSvc() @@ -251,6 +288,7 @@ void COptionsWindow::OnDelAutoSvc() AddAutoRunItem(Value, 1); m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::AddAutoRunItem(const QString& Value, int Type) @@ -271,6 +309,7 @@ void COptionsWindow::OnDelAuto() delete pItem; m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::OnBrowsePath() @@ -285,6 +324,7 @@ void COptionsWindow::OnBrowsePath() AddRunItem(Name, Value); m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddCommand() @@ -299,6 +339,7 @@ void COptionsWindow::OnAddCommand() AddRunItem(Name, Value); m_GeneralChanged = true; + OnOptChanged(); } void COptionsWindow::AddRunItem(const QString& Name, const QString& Command) @@ -318,4 +359,73 @@ void COptionsWindow::OnDelCommand() delete pItem; m_GeneralChanged = true; + OnOptChanged(); +} + +void COptionsWindow::UpdateBoxType() +{ + bool bPrivacyMode = ui.chkPrivacy->isChecked(); + bool bNoAdmin = ui.chkDropRights->isChecked(); + bool bAppBox = ui.chkNoSecurityIsolation->isChecked(); + + int BoxType; + if (bAppBox) + BoxType = bPrivacyMode ? (int)CSandBoxPlus::eAppBoxPlus : (int)CSandBoxPlus::eAppBox; + else if (bNoAdmin) + BoxType = bPrivacyMode ? (int)CSandBoxPlus::eHardenedPlus : (int)CSandBoxPlus::eHardened; + else + BoxType = bPrivacyMode ? (int)CSandBoxPlus::eDefaultPlus : (int)CSandBoxPlus::eDefault; + + ui.lblBoxInfo->setText(theGUI->GetBoxDescription(BoxType)); + + if (m_HoldBoxType) + return; + + m_HoldBoxType = true; + ui.cmbBoxType->setCurrentIndex(ui.cmbBoxType->findData(BoxType)); + m_HoldBoxType = false; +} + +void COptionsWindow::OnBoxTypChanged() +{ + if (m_HoldBoxType) + return; + + int BoxType = ui.cmbBoxType->currentData().toInt(); + + switch (BoxType) { + case CSandBoxPlus::eHardenedPlus: + case CSandBoxPlus::eHardened: + ui.chkNoSecurityIsolation->setChecked(false); + ui.chkNoSecurityFiltering->setChecked(false); + ui.chkDropRights->setChecked(true); + ui.chkMsiExemptions->setChecked(false); + //ui.chkRestrictServices->setChecked(true); + ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eHardenedPlus); + break; + case CSandBoxPlus::eDefaultPlus: + case CSandBoxPlus::eDefault: + ui.chkNoSecurityIsolation->setChecked(false); + ui.chkNoSecurityFiltering->setChecked(false); + ui.chkDropRights->setChecked(false); + ui.chkMsiExemptions->setChecked(false); + //ui.chkRestrictServices->setChecked(true); + ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eDefaultPlus); + break; + case CSandBoxPlus::eAppBoxPlus: + case CSandBoxPlus::eAppBox: + ui.chkNoSecurityIsolation->setChecked(true); + //ui.chkRestrictServices->setChecked(false); + ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eAppBoxPlus); + break; + } + + m_GeneralChanged = true; + m_AccessChanged = true; + m_AdvancedChanged = true; + + m_HoldBoxType = true; + UpdateBoxType(); + m_HoldBoxType = false; + OnOptChanged(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp b/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp index 5d815104..c6abb63c 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsGrouping.cpp @@ -11,7 +11,6 @@ void COptionsWindow::LoadGroups() { - m_TemplateGroups.clear(); ui.treeGroups->clear(); QStringList ProcessGroups = m_pBox->GetTextList("ProcessGroup", m_Template); @@ -51,7 +50,6 @@ void COptionsWindow::LoadGroupsTmpl(bool bUpdate) { foreach(const QString& Group, m_pBox->GetTextListTmpl("ProcessGroup", Template)) { - m_TemplateGroups.insert(Group); QStringList Entries = Group.split(","); QString GroupName = Entries.takeFirst(); @@ -90,6 +88,31 @@ void COptionsWindow::LoadGroupsTmpl(bool bUpdate) } } +QStringList COptionsWindow::GetCurrentGroups() +{ + QStringList Groups; + + for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) + { + QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); + QString GroupName = pItem->data(0, Qt::UserRole).toString(); + Groups.append(GroupName); + } + + foreach(const QString& Template, m_pBox->GetTemplates()) + { + foreach(const QString& Group, m_pBox->GetTextListTmpl("ProcessGroup", Template)) + { + QStringList Entries = Group.split(","); + QString GroupName = Entries.takeFirst(); + if (!Groups.contains(GroupName)) + Groups.append(GroupName); + } + } + + return Groups; +} + void COptionsWindow::SaveGroups() { QStringList ProcessGroups; @@ -103,8 +126,6 @@ void COptionsWindow::SaveGroups() for (int j = 0; j < pItem->childCount(); j++) Programs.append(pItem->child(j)->data(0, Qt::UserRole).toString()); QString Group = GroupName + "," + Programs.join(","); - if (m_TemplateGroups.contains(Group)) - continue; // don't save unchanged groups to local config ProcessGroups.append(Group); } @@ -131,6 +152,7 @@ void COptionsWindow::OnAddGroup() ui.treeGroups->addTopLevelItem(pItem); m_GroupsChanged = true; + OnOptChanged(); } void COptionsWindow::AddProgToGroup(QTreeWidget* pTree, const QString& Groupe) @@ -172,6 +194,7 @@ void COptionsWindow::AddProgToGroup(const QString& Value, const QString& Groupe) pGroupItem->addChild(pProgItem); m_GroupsChanged = true; + OnOptChanged(); } void COptionsWindow::DelProgFromGroup(QTreeWidget* pTree, const QString& Groupe) @@ -196,6 +219,7 @@ void COptionsWindow::DelProgFromGroup(QTreeWidget* pTree, const QString& Groupe) { delete pProgItem; m_GroupsChanged = true; + OnOptChanged(); break; } } @@ -214,6 +238,7 @@ void COptionsWindow::AddProgramToGroup(const QString& Program, const QString& Gr pItem->addChild(pSubItem); m_GroupsChanged = true; + OnOptChanged(); } void COptionsWindow::DelProgramFromGroup(const QString& Program, const QString& Group) @@ -229,6 +254,7 @@ void COptionsWindow::DelProgramFromGroup(const QString& Program, const QString& } m_GroupsChanged = true; + OnOptChanged(); } QTreeWidgetItem* COptionsWindow::FindGroupByName(const QString& Group, bool bAdd) @@ -280,6 +306,7 @@ void COptionsWindow::OnAddProg() pItem->addChild(pSubItem); m_GroupsChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelProg() @@ -296,6 +323,7 @@ void COptionsWindow::OnDelProg() delete pItem; m_GroupsChanged = true; + OnOptChanged(); } void COptionsWindow::CopyGroupToList(const QString& Groupe, QTreeWidget* pTree) diff --git a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp index da75c7a2..9861c39a 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp @@ -240,6 +240,7 @@ void COptionsWindow::OnBlockINet() DelAccessEntry(eFile, "!", eClosed, "InternetAccessDevices"); m_INetBlockChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddINetProg() @@ -262,6 +263,7 @@ void COptionsWindow::OnAddINetProg() AddProgramToGroup(Value, INetModeToGroup(Mode)); //m_INetBlockChanged = true; + //OnOptChanged(); } void COptionsWindow::OnDelINetProg() @@ -277,6 +279,7 @@ void COptionsWindow::OnDelINetProg() delete pItem; //m_INetBlockChanged = true; + //OnOptChanged(); } bool COptionsWindow::FindEntryInSettingList(const QString& Name, const QString& Value) @@ -560,6 +563,7 @@ void COptionsWindow::CloseNetFwEdit(QTreeWidgetItem* pItem, bool bSave) pItem->setData(4, Qt::UserRole, pProt->currentData()); m_NetFwRulesChanged = true; + OnOptChanged(); } for (int i = 0; i < 5; i++) @@ -579,6 +583,7 @@ void COptionsWindow::OnAddNetFwRule() ui.treeNetFw->addTopLevelItem(pItem); m_NetFwRulesChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelNetFwRule() @@ -589,8 +594,8 @@ void COptionsWindow::OnDelNetFwRule() delete pItem; - m_NetFwRulesChanged = true; + OnOptChanged(); } void COptionsWindow__SetRowColor(QTreeWidgetItem* pItem, bool bMatch, bool bConflict = false, bool bBlock = false, bool bActive = false) diff --git a/SandboxiePlus/SandMan/Windows/OptionsRecovery.cpp b/SandboxiePlus/SandMan/Windows/OptionsRecovery.cpp index 05c58be6..988d43b7 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsRecovery.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsRecovery.cpp @@ -97,6 +97,7 @@ void COptionsWindow::OnAddRecFolder() AddRecoveryEntry(Value, 1); m_RecoveryChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddRecIgnore() @@ -107,6 +108,7 @@ void COptionsWindow::OnAddRecIgnore() AddRecoveryEntry(Value, 2); m_RecoveryChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddRecIgnoreExt() @@ -117,6 +119,7 @@ void COptionsWindow::OnAddRecIgnoreExt() AddRecoveryEntry(Value, 2); m_RecoveryChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelRecEntry() @@ -132,4 +135,5 @@ void COptionsWindow::OnDelRecEntry() delete pItem; m_RecoveryChanged = true; + OnOptChanged(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsStart.cpp b/SandboxiePlus/SandMan/Windows/OptionsStart.cpp index 7aef0ce4..0c9fb785 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsStart.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsStart.cpp @@ -41,16 +41,19 @@ void COptionsWindow::OnRestrictStart() ui.chkStartBlockMsg->setEnabled(!ui.radStartAll->isChecked()); //m_StartChanged = true; + //OnOptChanged(); } void COptionsWindow::OnAddStartProg() { AddProgToGroup(ui.treeStart, ""); //m_StartChanged = true; + //OnOptChanged(); } void COptionsWindow::OnDelStartProg() { DelProgFromGroup(ui.treeStart, ""); //m_StartChanged = true; + //OnOptChanged(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsStop.cpp b/SandboxiePlus/SandMan/Windows/OptionsStop.cpp index bc15e7de..123f9770 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsStop.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsStop.cpp @@ -91,6 +91,7 @@ void COptionsWindow::OnAddLingering() return; AddStopEntry(Value, 1); m_StopChanged = true; + OnOptChanged(); } void COptionsWindow::OnAddLeader() @@ -100,10 +101,12 @@ void COptionsWindow::OnAddLeader() return; AddStopEntry(Value, 2); m_StopChanged = true; + OnOptChanged(); } void COptionsWindow::OnDelStopProg() { DeleteAccessEntry(ui.treeStop->currentItem()); m_StopChanged = true; + OnOptChanged(); } diff --git a/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp b/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp index 75561d83..be598a26 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp @@ -85,6 +85,7 @@ void COptionsWindow::OnScreenReaders() else m_BoxTemplates.removeAll("ScreenReader"); m_TemplatesChanged = true; + OnOptChanged(); } QString COptionsWindow::GetCategoryName(const QString& Category) @@ -154,12 +155,14 @@ void COptionsWindow::OnTemplateClicked(QTreeWidgetItem* pItem, int Column) if (!m_BoxTemplates.contains(Name)) { m_BoxTemplates.append(Name); m_TemplatesChanged = true; + OnOptChanged(); } } else if (pItem->checkState(1) == Qt::Unchecked) { if (m_BoxTemplates.contains(Name)) { m_BoxTemplates.removeAll(Name); m_TemplatesChanged = true; + OnOptChanged(); } } } @@ -254,6 +257,7 @@ void COptionsWindow::OnFolderChanged() { //CPathEdit* pEdit = (CPathEdit*)sender(); m_FoldersChanged = true; + OnOptChanged(); } void COptionsWindow::ShowFolders() diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp index 398a298a..2e5f43d0 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp @@ -17,6 +17,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri m_Template = pBox->GetName().left(9).compare("Template_", Qt::CaseInsensitive) == 0; bool ReadOnly = /*pBox->GetAPI()->IsConfigLocked() ||*/ (m_Template && pBox->GetName().mid(9, 6).compare("Local_", Qt::CaseInsensitive) != 0); + m_HoldChange = false; + QSharedPointer pBoxPlus = m_pBox.objectCast(); if (!pBoxPlus.isNull()) m_Programs = pBoxPlus->GetRecentPrograms(); @@ -120,10 +122,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri CreateAccess(); - // Resource Access - connect(ui.chkCloseForBox, SIGNAL(clicked(bool)), this, SLOT(OnAccessChanged())); - // - // Recovery connect(ui.chkAutoRecovery, SIGNAL(clicked(bool)), this, SLOT(OnRecoveryChanged())); connect(ui.btnAddRecovery, SIGNAL(clicked(bool)), this, SLOT(OnAddRecFolder())); @@ -152,6 +150,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.btnEditIni, SIGNAL(clicked(bool)), this, SLOT(OnEditIni())); connect(ui.btnSaveIni, SIGNAL(clicked(bool)), this, SLOT(OnSaveIni())); connect(ui.btnCancelEdit, SIGNAL(clicked(bool)), this, SLOT(OnCancelEdit())); + connect(ui.txtIniSection, SIGNAL(textChanged()), this, SLOT(OnOptChanged())); + // connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked(bool)), this, SLOT(ok())); @@ -162,7 +162,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri { ui.btnEditIni->setEnabled(false); ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); } if (theAPI->IsRunningAsAdmin()) @@ -175,6 +174,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri LoadConfig(); + ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); + ui.treeAccess->viewport()->installEventFilter(this); ui.treeINet->viewport()->installEventFilter(this); ui.treeNetFw->viewport()->installEventFilter(this); @@ -206,6 +207,12 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri if (!Columns.isEmpty()) ui.treeTemplates->header()->restoreState(Columns); } +void COptionsWindow::OnOptChanged() { + if (m_HoldChange) + return; + ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true); +} + COptionsWindow::~COptionsWindow() { theConf->SetBlob("OptionsWindow/Window_Geometry",saveGeometry()); @@ -309,6 +316,7 @@ void COptionsWindow::LoadConfig() LoadTemplates(); + UpdateBoxType(); } void COptionsWindow::WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, const QString& Value) @@ -328,6 +336,9 @@ void COptionsWindow::WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, //if (pCheck->checkState() == Qt::PartiallyChecked) // return; + if (!pCheck->isEnabled()) + return; + SB_STATUS Status; if (pCheck->checkState() == Qt::Checked) { @@ -435,6 +446,8 @@ void COptionsWindow::apply() UpdateCurrentTab(); emit OptionsChanged(); + + ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); } void COptionsWindow::ok() @@ -485,9 +498,9 @@ QString COptionsWindow::SelectProgram(bool bOrGroup) if (bOrGroup) { - for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { - QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); - progDialog.addItem(tr("Group: %1").arg(pItem->text(0)), pItem->data(0, Qt::UserRole).toString()); + foreach(const QString Group, GetCurrentGroups()){ + QString GroupName = Group.mid(1, Group.length() - 2); + progDialog.addItem(tr("Group: %1").arg(Group), GroupName); } } @@ -548,7 +561,9 @@ void COptionsWindow::UpdateCurrentTab() } else if (ui.tabs->currentWidget() == ui.tabAdvanced) { - if (GetAccessEntry(eWnd, "", eDirect, "*") != NULL) + ui.chkOpenCOM->setChecked(GetAccessEntry(eIPC, "", eOpen, "\\RPC Control\\epmapper") != NULL); + + if (GetAccessEntry(eWnd, "", eOpen, "*") != NULL) { ui.chkNoWindowRename->setEnabled(false); ui.chkNoWindowRename->setChecked(true); @@ -556,7 +571,7 @@ void COptionsWindow::UpdateCurrentTab() else { ui.chkNoWindowRename->setEnabled(true); - ui.chkNoWindowRename->setChecked(GetAccessEntry(eWnd, "", eDirect, "#") != NULL); + ui.chkNoWindowRename->setChecked(GetAccessEntry(eWnd, "", eOpen, "#") != NULL); } } } @@ -609,7 +624,9 @@ void COptionsWindow::LoadIniSection() else Section = m_pBox->GetAPI()->SbieIniGetEx(m_pBox->GetName(), ""); + m_HoldChange = true; ui.txtIniSection->setPlainText(Section); + m_HoldChange = false; } void COptionsWindow::SaveIniSection() diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.h b/SandboxiePlus/SandMan/Windows/OptionsWindow.h index bd43c6d1..54237ab0 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.h +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.h @@ -27,8 +27,13 @@ private slots: //void OnWithTemplates(); + void OnOptChanged(); + void OnPickColor(); + void OnBoxTypChanged(); + void UpdateBoxType(); + void OnBrowsePath(); void OnAddCommand(); void OnDelCommand(); @@ -59,13 +64,13 @@ private slots: // net void OnINetItemDoubleClicked(QTreeWidgetItem* pItem, int Column); - void OnINetSelectionChanged() { CloseINetEdit(); } + void OnINetSelectionChanged() { CloseINetEdit(); OnOptChanged();} void OnBlockINet(); void OnAddINetProg(); void OnDelINetProg(); void OnNetFwItemDoubleClicked(QTreeWidgetItem* pItem, int Column); - void OnNetFwSelectionChanged() { CloseNetFwEdit(); } + void OnNetFwSelectionChanged() { CloseNetFwEdit(); OnOptChanged();} void OnAddNetFwRule(); void OnDelNetFwRule(); @@ -78,15 +83,15 @@ private slots: // access //void OnAccessItemClicked(QTreeWidgetItem* pItem, int Column); void OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Column); - void OnAccessSelectionChanged() { CloseAccessEdit(); } + void OnAccessSelectionChanged() { CloseAccessEdit(); OnOptChanged();} - void OnAddFile() { AddAccessEntry(eFile, eDirect, "", ""); m_AccessChanged = true; } + void OnAddFile() { AddAccessEntry(eFile, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } void OnBrowseFile(); void OnBrowseFolder(); - void OnAddKey() { AddAccessEntry(eKey, eDirect, "", ""); m_AccessChanged = true; } - void OnAddIPC() { AddAccessEntry(eIPC, eDirect, "", ""); m_AccessChanged = true; } - void OnAddWnd() { AddAccessEntry(eWnd, eDirect, "", ""); m_AccessChanged = true; } - void OnAddCOM() { AddAccessEntry(eCOM, eDirect, "", ""); m_AccessChanged = true; } + void OnAddKey() { AddAccessEntry(eKey, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } + void OnAddIPC() { AddAccessEntry(eIPC, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } + void OnAddWnd() { AddAccessEntry(eWnd, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } + void OnAddCOM() { AddAccessEntry(eCOM, eOpen, "", ""); m_AccessChanged = true; OnOptChanged(); } void OnDelAccess(); void OnShowAccessTmpl() { LoadAccessListTmpl(true); } // @@ -119,12 +124,14 @@ private slots: void OnTab(); void OnGeneralChanged(); - void OnStartChanged() { m_StartChanged = true; } - //void OnRestrictionChanged() { m_RestrictionChanged = true; } - void OnINetBlockChanged() { m_INetBlockChanged = true; } - void OnRecoveryChanged() { m_RecoveryChanged = true; } - void OnAccessChanged() { m_AccessChanged = true; } + void OnStartChanged() { m_StartChanged = true; OnOptChanged(); } + //void OnRestrictionChanged() { m_RestrictionChanged = true; OnOptChanged(); } + void OnINetBlockChanged() { m_INetBlockChanged = true; OnOptChanged(); } + void OnRecoveryChanged() { m_RecoveryChanged = true; OnOptChanged(); } + void OnAccessChanged(); void OnAdvancedChanged(); + void OnOpenCOM(); + void OnIsolationChanged(); void OnDebugChanged(); void SetIniEdit(bool bEnable); @@ -155,17 +162,21 @@ protected: enum EAccessEntry { + eNormalFilePath, eOpenFilePath, eOpenPipePath, eClosedFilePath, eReadFilePath, eWriteFilePath, + eNormalKeyPath, eOpenKeyPath, + eOpenConfPath, eClosedKeyPath, eReadKeyPath, eWriteKeyPath, + eNormalIpcPath, eOpenIpcPath, eClosedIpcPath, @@ -189,8 +200,9 @@ protected: enum EAccessMode { - eDirect, - eDirectAll, + eNormal, + eOpen, + eOpen4All, eClosed, eClosedRT, eReadOnly, @@ -227,6 +239,7 @@ protected: void LoadGroups(); void LoadGroupsTmpl(bool bUpdate = false); void SaveGroups(); + QStringList GetCurrentGroups(); void LoadForced(); void LoadForcedTmpl(bool bUpdate = false); @@ -283,6 +296,8 @@ protected: void CloseAccessEdit(bool bSave = true); void CloseAccessEdit(QTreeWidgetItem* pItem, bool bSave = true); + + void UpdateAccessPolicy(); // void LoadRecoveryList(); @@ -293,6 +308,7 @@ protected: void CreateAdvanced(); void LoadAdvanced(); void SaveAdvanced(); + void UpdateBoxIsolation(); void CreateDebug(); void LoadDebug(); @@ -311,9 +327,13 @@ protected: QString GetCategoryName(const QString& Category); + bool m_HoldChange; + bool m_ConfigDirty; QColor m_BorderColor; + bool m_HoldBoxType; + bool m_GeneralChanged; bool m_GroupsChanged; bool m_ForcedChanged; @@ -333,8 +353,6 @@ protected: bool m_Template; - QSet m_TemplateGroups; - QMultiMap> m_AllTemplates; QStringList m_GlobalTemplates; QStringList m_BoxTemplates; diff --git a/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp index 004de9cc..4eda963c 100644 --- a/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp @@ -119,7 +119,7 @@ CSelectBoxWindow::CSelectBoxWindow(const QStringList& Commands, const QString& B QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setText(0, pBox->GetName().replace("_", " ")); pItem->setData(0, Qt::UserRole, pBox->GetName()); - pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBox->GetActiveProcessCount() > 0, pBoxEx->GetType())); + pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBoxEx->GetType(), pBox->GetActiveProcessCount())); if (pParent) pParent->addChild(pItem); else diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp index 264d6c05..5b686cc0 100644 --- a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp @@ -121,6 +121,7 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) m_FeaturesChanged = false; connect(ui.chkWFP, SIGNAL(stateChanged(int)), this, SLOT(OnFeaturesChanged())); + connect(ui.chkObjCb, SIGNAL(stateChanged(int)), this, SLOT(OnFeaturesChanged())); m_WarnProgsChanged = false; @@ -217,7 +218,7 @@ void CSettingsWindow::LoadSettings() ui.chkNotifyRecovery->setChecked(!theConf->GetBool("Options/InstantRecovery", true)); ui.chkPanic->setChecked(theConf->GetBool("Options/EnablePanicKey", false)); - ui.keyPanic->setKeySequence(QKeySequence(theConf->GetString("Options/PanicKeySequence", "Shift+Pause"))); + ui.keyPanic->setKeySequence(QKeySequence(theConf->GetString("Options/PanicKeySequence", "Ctrl+Alt+Cancel"))); ui.chkWatchConfig->setChecked(theConf->GetBool("Options/WatchIni", true)); @@ -238,6 +239,7 @@ void CSettingsWindow::LoadSettings() ui.ipcRoot->setText(theAPI->GetGlobalSettings()->GetText("IpcRootPath", IpcRootPath_Default)); ui.chkWFP->setChecked(theAPI->GetGlobalSettings()->GetBool("NetworkEnableWFP", false)); + ui.chkObjCb->setChecked(theAPI->GetGlobalSettings()->GetBool("EnableObjectFiltering", false)); ui.chkAdminOnly->setChecked(theAPI->GetGlobalSettings()->GetBool("EditAdminOnly", false)); ui.chkPassRequired->setChecked(!theAPI->GetGlobalSettings()->GetText("EditPassword", "").isEmpty()); @@ -260,6 +262,7 @@ void CSettingsWindow::LoadSettings() ui.fileRoot->setEnabled(false); ui.chkSeparateUserFolders->setEnabled(false); ui.chkWFP->setEnabled(false); + ui.chkObjCb->setEnabled(false); ui.regRoot->setEnabled(false); ui.ipcRoot->setEnabled(false); ui.chkAdminOnly->setEnabled(false); @@ -291,7 +294,13 @@ void CSettingsWindow::LoadSettings() QPalette palette = QApplication::palette(); if (theGUI->m_DarkTheme) palette.setColor(QPalette::Text, Qt::black); - palette.setColor(QPalette::Base, QColor(192, 255, 192)); + if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { + palette.setColor(QPalette::Base, QColor(255, 255, 192)); + ui.lblCertExp->setVisible(true); + } + else { + palette.setColor(QPalette::Base, QColor(192, 255, 192)); + } ui.txtCertificate->setPalette(palette); } @@ -361,6 +370,7 @@ void CSettingsWindow::SaveSettings() theAPI->GetGlobalSettings()->SetBool("NetworkEnableWFP", ui.chkWFP->isChecked()); + theAPI->GetGlobalSettings()->SetBool("EnableObjectFiltering", ui.chkObjCb->isChecked()); if (m_FeaturesChanged) { m_FeaturesChanged = false; @@ -464,6 +474,8 @@ void CSettingsWindow::SaveSettings() if (theGUI->m_DarkTheme) palette.setColor(QPalette::Text, Qt::black); + ui.lblCertExp->setVisible(false); + if (Certificate.isEmpty()) { palette.setColor(QPalette::Base, Qt::white); @@ -472,9 +484,17 @@ void CSettingsWindow::SaveSettings() { g_FeatureFlags = theAPI->GetFeatureFlags(); - QMessageBox::information(this, "Sandboxie-Plus", tr("Thank you for supporting the development of Sandboxie-Plus.")); + if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { + QMessageBox::information(this, "Sandboxie-Plus", tr("This certificate is unfortunately expired.")); - palette.setColor(QPalette::Base, QColor(192, 255, 192)); + palette.setColor(QPalette::Base, QColor(255, 255, 192)); + ui.lblCertExp->setVisible(true); + } + else { + QMessageBox::information(this, "Sandboxie-Plus", tr("Thank you for supporting the development of Sandboxie-Plus.")); + + palette.setColor(QPalette::Base, QColor(192, 255, 192)); + } } else { diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h index 5383f1e0..1eecbbe1 100644 --- a/SandboxiePlus/version.h +++ b/SandboxiePlus/version.h @@ -1,9 +1,9 @@ #pragma once -#define VERSION_MJR 0 -#define VERSION_MIN 9 -#define VERSION_REV 8 -#define VERSION_UPD 4 +#define VERSION_MJR 1 +#define VERSION_MIN 0 +#define VERSION_REV 0 +#define VERSION_UPD 0 #ifndef STR #define STR2(X) #X