diff --git a/CHANGELOG.md b/CHANGELOG.md index 59467001..06d5d026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,24 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.9.1 / 5.51.1] - 2021-07-?? + +### Added +- added tray icon indicating no connection to the driver if it happens +- added option to customize the tray icon +- added "DllSkipHook=some.dll" option to disable instalation of hooks into selected dll's + +### Changed +- reworked NtClose handling for better performance and extendibility + +### Fixed +- fixed issue with fake admin and some nsi installers +- fixed more issued with FileDispositionInformation behavioure, which resulted in bogus file deletion handling +- fixed issue with checking WFP status -## [0.9.0 / 5.51.0] - 2021-07-?? +## [0.9.0 / 5.51.0] - 2021-07-29 ### Added - added support for Windows Filtering Platform (WFP) to be used instead of the device-based network blocking scheme @@ -13,7 +27,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). -- to use WFP for a specified sandbox, add 'AllowNetworkAccess=n' to said box -- you can exempt certain processes from blocking by using 'AllowNetworkAccess=program.exe,y' -- you can also enable this policy globally by adding 'AllowNetworkAccess=n' to the global section --- in this case you can exempt entire boxes by adding 'AllowNetworkAccess=n' to said boxes +-- in this case you can exempt entire boxes by adding 'AllowNetworkAccess=y' to said boxes -- specifying 'AllowNetworkAccess=program.exe,n' will block the access only for the named process -- Note: WFP is less absolute than the old approach, using WFP will filter only TCP/UDP communication -- restricted boxed processes will still be able to resolve domain names using the system service @@ -24,7 +38,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). -- Note: this filter applies only to outgoing connections/traffic, for incoming traffic either the WFP mode or a third-party firewall is needed -- like the old user mode based mechanism, malicious applications can bypass it by unhooking certain functions -- hence it's recommended to use the kernel mode WFP-based mechanism when reliable isolation is required --- Note: the main reason this mechanism was added in user mode is to allow for easier debugging - added new trace option "NetFwTrace=*" to trace the actions of the firewall components -- please note that the driver only trace logs the kernel debug output, use DbgView.exe to log - API_QUERY_PROCESS_INFO can now be used to get the impersonation token of a sandboxed thread @@ -46,6 +59,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - added missing hook for ConnectEx function + + ## [0.8.9 / 5.50.9] - 2021-07-28 HotFix 2 ### Fixed diff --git a/Sandboxie/common/map.c b/Sandboxie/common/map.c index 18fe6b6d..50d88a8f 100644 --- a/Sandboxie/common/map.c +++ b/Sandboxie/common/map.c @@ -162,8 +162,11 @@ static map_node_t* map_new_node(map_base_t* m, const void* _key, void* vdata, si memcpy(node->key, key, ksize); node->next = NULL; if (vsize) { - node->value = vsize ? node->key + voffset : NULL; - memcpy(node->value, vdata, vsize); + node->value = node->key + voffset; + if (vdata) + memcpy(node->value, vdata, vsize); + else + memset(node->value, 0, vsize); } else node->value = vdata; @@ -171,7 +174,7 @@ static map_node_t* map_new_node(map_base_t* m, const void* _key, void* vdata, si } -BOOLEAN map_insert(map_base_t* m, const void* key, void* vdata, size_t vsize) +void* map_insert(map_base_t* m, const void* key, void* vdata, size_t vsize) { // create a new node and fill inn all the blanks map_node_t* node = map_new_node(m, key, vdata, vsize); @@ -192,10 +195,10 @@ BOOLEAN map_insert(map_base_t* m, const void* key, void* vdata, size_t vsize) map_add_node(m, node); m->nnodes++; - return TRUE; + return node->value; fail: if (node) m->func_free(m->mem_pool, node); - return FALSE; + return NULL; } @@ -247,7 +250,7 @@ void* map_remove(map_base_t* m, const void* key) m->func_free(m->mem_pool, node); m->nnodes--; } - return value; + return value; // WARNING: this valus is only pointer when the map was storring an externaly allocated value!!! } diff --git a/Sandboxie/common/map.h b/Sandboxie/common/map.h index 17576d35..7b03a1df 100644 --- a/Sandboxie/common/map.h +++ b/Sandboxie/common/map.h @@ -48,7 +48,7 @@ BOOLEAN map_wcsimatch(const void* key1, const void* key2); void map_init(map_base_t *m, void* pool); BOOLEAN map_resize(map_base_t* m, int nbuckets); -BOOLEAN map_insert(map_base_t *m, const void* key, void* vdata, size_t vsize); +void* map_insert(map_base_t *m, const void* key, void* vdata, size_t vsize); void* map_get(map_base_t *m, const void* key); void* map_remove(map_base_t *m, const void* key); void map_deinit(map_base_t *m); diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h index 77aca7e4..5f85794a 100644 --- a/Sandboxie/common/my_version.h +++ b/Sandboxie/common/my_version.h @@ -21,8 +21,8 @@ #ifndef _MY_VERSION_H #define _MY_VERSION_H -#define MY_VERSION_BINARY 5,51,0 -#define MY_VERSION_STRING "5.51.0" +#define MY_VERSION_BINARY 5,51,1 +#define MY_VERSION_STRING "5.51.1" #define MY_VERSION_COMPAT "5.51.0" // this refers to the driver ABI compatibility // These #defines are used by either Resource Compiler, or by NSIC installer diff --git a/Sandboxie/common/ntproto.h b/Sandboxie/common/ntproto.h index 81c1cf0a..19dcc5e3 100644 --- a/Sandboxie/common/ntproto.h +++ b/Sandboxie/common/ntproto.h @@ -667,6 +667,21 @@ typedef NTSTATUS (*P_NtAccessCheckByTypeResultList) ( PNTSTATUS AccessStatus ); +typedef NTSTATUS(WINAPI *P_NtAccessCheckByType) ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID PrincipalSelfSid, + HANDLE ClientToken, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE_LIST ObjectTypeList, + ULONG ObjectTypeListLength, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + PULONG PrivilegeSetLength, + PACCESS_MASK GrantedAccess, + PNTSTATUS AccessStatus); + +typedef BOOL(*P_RtlEqualSid) (void * sid1, void * sid2); + typedef NTSTATUS (*P_NtQuerySystemInformation)( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, diff --git a/Sandboxie/common/win32_ntddk.h b/Sandboxie/common/win32_ntddk.h index 4a10bd48..d679f9a9 100644 --- a/Sandboxie/common/win32_ntddk.h +++ b/Sandboxie/common/win32_ntddk.h @@ -554,9 +554,25 @@ typedef struct _FILE_SHORT_NAME_INFORMATION { // FileDispositionInformation typedef struct _FILE_DISPOSITION_INFORMATION { - BOOLEAN DeleteFile; + BOOLEAN DeleteFileOnClose; } FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; +// // FileDispositionInformationEx +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1) +#define FILE_DISPOSITION_DO_NOT_DELETE 0x00000000 +#define FILE_DISPOSITION_DELETE 0x00000001 +#define FILE_DISPOSITION_POSIX_SEMANTICS 0x00000002 +#define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x00000004 +#define FILE_DISPOSITION_ON_CLOSE 0x00000008 +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS5) +#define FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE 0x00000010 +#endif + +typedef struct _FILE_DISPOSITION_INFORMATION_EX { + ULONG Flags; +} FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX; +#endif + // FilePositionInformation typedef struct _FILE_POSITION_INFORMATION { LARGE_INTEGER CurrentByteOffset; diff --git a/Sandboxie/core/dll/config.c b/Sandboxie/core/dll/config.c index 9576b3e0..5482bd0d 100644 --- a/Sandboxie/core/dll/config.c +++ b/Sandboxie/core/dll/config.c @@ -514,7 +514,7 @@ BOOLEAN SbieDll_MatchImage(const WCHAR* pat_str, const WCHAR* test_str, const WC //--------------------------------------------------------------------------- -SBIEDLL_EXPORT BOOLEAN SbieDll_GetStringForStringList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, WCHAR* value, ULONG value_size) +BOOLEAN SbieDll_GetStringForStringList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, WCHAR* value, ULONG value_size) { WCHAR buf[CONF_LINE_LEN]; ULONG index = 0; @@ -568,7 +568,7 @@ BOOLEAN SbieDll_CheckStringInList(const WCHAR* string, const WCHAR* boxname, con //--------------------------------------------------------------------------- -/*SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found) +/*BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found) { WCHAR buf[32]; if (SbieDll_GetStringForStringList(string, boxname, setting, buf, sizeof(buf))) diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h index 20b7b77f..2a46985c 100644 --- a/Sandboxie/core/dll/dll.h +++ b/Sandboxie/core/dll/dll.h @@ -463,6 +463,9 @@ BOOLEAN File_IsBlockedNetParam(const WCHAR *BoxName); void File_GetSetDeviceMap(WCHAR *DeviceMap96); +typedef void(*P_CloseHandler)(HANDLE handle); +BOOLEAN File_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler); +BOOLEAN File_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler); //--------------------------------------------------------------------------- // Functions (key) @@ -591,6 +594,7 @@ BOOLEAN Taskbar_SHCore_Init(HMODULE hmodule); // Functions (init for DllMain) //--------------------------------------------------------------------------- +BOOLEAN File_InitHandles(void); BOOLEAN Key_Init(void); diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c index 9d0977e1..47c2e506 100644 --- a/Sandboxie/core/dll/dllmain.c +++ b/Sandboxie/core/dll/dllmain.c @@ -320,6 +320,9 @@ _FX void Dll_InitInjected(void) if (ok) Dll_FixWow64Syscall(); + if (ok) + ok = File_InitHandles(); + if (ok) ok = Obj_Init(); diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c index e2c269d1..0642dd7c 100644 --- a/Sandboxie/core/dll/file.c +++ b/Sandboxie/core/dll/file.c @@ -3036,7 +3036,7 @@ ReparseLoop: //} // MSIServer without system - if (status == STATUS_ACCESS_DENIED && Dll_ImageType == DLL_IMAGE_MSI_INSTALLER && Scm_MsiServer_Systemless + if (status == STATUS_ACCESS_DENIED && Dll_ImageType == DLL_IMAGE_MSI_INSTALLER //&& Scm_MsiServer_Systemless && ObjectAttributes->ObjectName->Buffer && ObjectAttributes->ObjectName->Length >= 34 && _wcsicmp(ObjectAttributes->ObjectName->Buffer + (ObjectAttributes->ObjectName->Length / sizeof(WCHAR)) - 11, L"\\Config.Msi") == 0 ) { @@ -3448,8 +3448,7 @@ ReparseLoop: // or was deleted, then record it for recovery // - IsRecover = - File_RecordRecover(*FileHandle, TruePath); + IsRecover = File_RecordRecover(*FileHandle, TruePath); } } @@ -5886,70 +5885,33 @@ _FX NTSTATUS File_SetDisposition( THREAD_DATA *TlsData = Dll_GetTlsData(&LastError); UNICODE_STRING uni; - WCHAR *DosPath; NTSTATUS status; ULONG mp_flags; + ULONG FileFlags; // // check if the specified path is an open or closed path // - RtlInitUnicodeString(&uni, L""); - mp_flags = 0; - DosPath = NULL; + FileFlags = 0; Dll_PushTlsNameBuffer(TlsData); __try { WCHAR *TruePath, *CopyPath; - ULONG FileFlags; + RtlInitUnicodeString(&uni, L""); status = File_GetName( FileHandle, &uni, &TruePath, &CopyPath, &FileFlags); - // - // fix-me: this is broken, instead of deleting files on close it deletes them instantly - // possible workarounds use __sys_NtSetInformationFile for files that reside only in the sandbox - // or implement proper deletion on handle close in File_NtCloseImpl - // - if (NT_SUCCESS(status)) { mp_flags = File_MatchPath(TruePath, &FileFlags); if (PATH_IS_CLOSED(mp_flags)) status = STATUS_ACCESS_DENIED; - - else if (PATH_NOT_OPEN(mp_flags)) { - - status = File_DeleteDirectory(CopyPath, TRUE); - - if (status != STATUS_DIRECTORY_NOT_EMPTY) - status = STATUS_SUCCESS; - - if (NT_SUCCESS(status) && Dll_ChromeSandbox) { - - // - // if this is a Chrome sandbox process, we have - // to pass a DOS path to NtDeleteFile rather - // than a file handle - // - - ULONG len = wcslen(TruePath); - DosPath = Dll_AllocTemp((len + 8) * sizeof(WCHAR)); - wmemcpy(DosPath, TruePath, len + 1); - if (SbieDll_TranslateNtToDosPath(DosPath)) { - len = wcslen(DosPath); - wmemmove(DosPath + 4, DosPath, len + 1); - wmemcpy(DosPath, File_BQQB, 4); - } else { - Dll_Free(DosPath); - DosPath = NULL; - } - } - } } } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -5961,33 +5923,49 @@ _FX NTSTATUS File_SetDisposition( // // handle the request appropriately // - - if (PATH_IS_OPEN(mp_flags)) { + + if (PATH_IS_OPEN(mp_flags) || (FileFlags & FGN_IS_BOXED_PATH) != 0) { status = __sys_NtSetInformationFile( FileHandle, IoStatusBlock, - FileInformation, Length, FileInformationClass); // FileDispositionInformation + FileInformation, Length, FileInformationClass); } else if (NT_SUCCESS(status)) { - OBJECT_ATTRIBUTES objattrs; - - InitializeObjectAttributes( - &objattrs, &uni, OBJ_CASE_INSENSITIVE, FileHandle, NULL); - - if (DosPath) { - objattrs.RootDirectory = NULL; - RtlInitUnicodeString(&uni, DosPath); - } - - status = File_NtDeleteFileImpl(&objattrs); - IoStatusBlock->Status = 0; IoStatusBlock->Information = 8; } - if (DosPath) - Dll_Free(DosPath); + if (NT_SUCCESS(status) && !PATH_IS_OPEN(mp_flags)) { + + BOOLEAN DeleteOnClose; + + if (FileInformationClass == FileDispositionInformation) { + + DeleteOnClose = ((FILE_DISPOSITION_INFORMATION*)FileInformation)->DeleteFileOnClose; + + } else if (FileInformationClass == FileDispositionInformationEx) { // Win 10 RS1 and later + + ULONG Flags = ((FILE_DISPOSITION_INFORMATION_EX*)FileInformation)->Flags; + + if ((Flags & FILE_DISPOSITION_DELETE) != 0) + DeleteOnClose = TRUE; + else if((Flags & FILE_DISPOSITION_ON_CLOSE) != 0) // FILE_DISPOSITION_ON_CLOSE with no FILE_DISPOSITION_DELETE means clear flag + DeleteOnClose = FALSE; + } + + + EnterCriticalSection(&File_HandleOnClose_CritSec); + + FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle); + if (!on_close) { + on_close = map_insert(&File_HandleOnClose, FileHandle, NULL, sizeof(FILE_ON_CLOSE)); + } + + on_close->DeleteOnClose = DeleteOnClose; + + LeaveCriticalSection(&File_HandleOnClose_CritSec); + } SetLastError(LastError); return status; diff --git a/Sandboxie/core/dll/file_dir.c b/Sandboxie/core/dll/file_dir.c index 6e3cab04..6d99b335 100644 --- a/Sandboxie/core/dll/file_dir.c +++ b/Sandboxie/core/dll/file_dir.c @@ -22,7 +22,7 @@ #include "common/pool.h" - +#include "common/map.h" //--------------------------------------------------------------------------- // Structures and Types @@ -93,6 +93,14 @@ typedef struct _FILE_FS_DEVICE_INFORMATION { ULONG Characteristics; } FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; +#define MAX_CLOSE_HANDLERS 4 + +typedef struct _FILE_ON_CLOSE { + + BOOLEAN DeleteOnClose; + P_CloseHandler CloseHandlers[MAX_CLOSE_HANDLERS]; + +} FILE_ON_CLOSE; //--------------------------------------------------------------------------- // Functions @@ -208,6 +216,8 @@ static ULONG File_DoAutoRecover_4( NTSTATUS File_NtCloseImpl(HANDLE FileHandle); +VOID File_NtCloseDir(HANDLE FileHandle); + //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- @@ -216,7 +226,6 @@ NTSTATUS File_NtCloseImpl(HANDLE FileHandle); static LIST File_RecoverFolders; static LIST File_RecoverIgnores; -static HANDLE *File_RecHandles = NULL; static LIST File_RecPaths; static CRITICAL_SECTION File_RecHandles_CritSec; @@ -227,6 +236,9 @@ static WCHAR *File_CurDir_LastOutput = NULL; static LIST File_DirHandles; static CRITICAL_SECTION File_DirHandles_CritSec; +static HASH_MAP File_HandleOnClose; +static CRITICAL_SECTION File_HandleOnClose_CritSec; + static BOOLEAN File_MsoDllLoaded = FALSE; @@ -501,6 +513,7 @@ _FX NTSTATUS File_Merge( } else { + File_UnRegisterCloseHandler(merge->handle, File_NtCloseDir); List_Remove(&File_DirHandles, merge); File_MergeFree(merge); } @@ -554,6 +567,7 @@ _FX NTSTATUS File_Merge( } List_Insert_After(&File_DirHandles, NULL, merge); + File_RegisterCloseHandler(merge->handle, File_NtCloseDir); } // @@ -1904,6 +1918,73 @@ _FX NTSTATUS File_NtClose(HANDLE FileHandle) } +//--------------------------------------------------------------------------- +// File_RegisterCloseHandler +//--------------------------------------------------------------------------- + + +_FX BOOLEAN File_RegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler) +{ + if (!FileHandle || FileHandle == (HANDLE)-1) + return FALSE; + + ULONG i; + + EnterCriticalSection(&File_HandleOnClose_CritSec); + + FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle); + if (!on_close) { + on_close = map_insert(&File_HandleOnClose, FileHandle, NULL, sizeof(FILE_ON_CLOSE)); + } + + for (i = 0; i < MAX_CLOSE_HANDLERS; i++) { + if (on_close->CloseHandlers[i] == CloseHandler) + break; // already registered + if (on_close->CloseHandlers[i] == NULL) { + on_close->CloseHandlers[i] = CloseHandler; // set to empty slot + break; + } + } + + LeaveCriticalSection(&File_HandleOnClose_CritSec); + + if (i == MAX_CLOSE_HANDLERS) { + SbieApi_Log(2301, L"No free CloseHandlers slot available"); + return FALSE; + } + + return TRUE; +} + + +//--------------------------------------------------------------------------- +// File_UnRegisterCloseHandler +//--------------------------------------------------------------------------- + + +_FX BOOLEAN File_UnRegisterCloseHandler(HANDLE FileHandle, P_CloseHandler CloseHandler) +{ + ULONG i = MAX_CLOSE_HANDLERS; + + EnterCriticalSection(&File_HandleOnClose_CritSec); + + FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, FileHandle); + if (on_close) { + + for (i = 0; i < MAX_CLOSE_HANDLERS; i++) { + if (on_close->CloseHandlers[i] == CloseHandler) { + on_close->CloseHandlers[i] = NULL; // clear slot + break; + } + } + } + + LeaveCriticalSection(&File_HandleOnClose_CritSec); + + return i != MAX_CLOSE_HANDLERS; +} + + //--------------------------------------------------------------------------- // File_NtCloseImpl //--------------------------------------------------------------------------- @@ -1915,8 +1996,12 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle) THREAD_DATA *TlsData = Dll_GetTlsData(&LastError); NTSTATUS status; - ULONG type; - FILE_MERGE *merge; + ULONG i; + BOOLEAN HasCloseHandlers = FALSE; + P_CloseHandler CloseHandlers[MAX_CLOSE_HANDLERS]; + BOOLEAN DeleteOnClose = FALSE; + UNICODE_STRING uni; + WCHAR *DeletePath = NULL; P_NtClose pSysNtClose = __sys_NtClose; @@ -1949,47 +2034,136 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle) } // - // determine the type of handle we are closing. - // if we are closing a key handle, call Key_NtClose + // check the handle map and execute the close handlers if there is are any + // and prepare the DeleteOnClose if its set // - type = Obj_GetObjectType(FileHandle); + EnterCriticalSection(&File_HandleOnClose_CritSec); - if (type == OBJ_TYPE_KEY) { + FILE_ON_CLOSE* on_close = (FILE_ON_CLOSE*)map_get(&File_HandleOnClose, FileHandle); + if (on_close) { - Key_NtClose(FileHandle); + HasCloseHandlers = TRUE; + memcpy(CloseHandlers, on_close->CloseHandlers, sizeof(CloseHandlers)); + DeleteOnClose = on_close->DeleteOnClose; + } + + map_remove(&File_HandleOnClose, FileHandle); + + LeaveCriticalSection(&File_HandleOnClose_CritSec); + + // + // execute close handlers + // + + if (HasCloseHandlers) { + + for (i = 0; i < MAX_CLOSE_HANDLERS; i++) { + if(CloseHandlers[i] != NULL) + CloseHandlers[i](FileHandle); + } } // - // special handling for scm_msi.c + // preapre delete disposition if set // - if (TlsData->scm_last_own_token == FileHandle) - TlsData->scm_last_own_token = NULL; + if (DeleteOnClose) { - // - // if not closing a file handle, stop here - // + Dll_PushTlsNameBuffer(TlsData); - if (type != OBJ_TYPE_FILE) { + __try { - TlsData->file_NtClose_lock = FALSE; + WCHAR *TruePath, *CopyPath; + ULONG FileFlags; - SetLastError(LastError); + RtlInitUnicodeString(&uni, L""); + status = File_GetName( + FileHandle, &uni, &TruePath, &CopyPath, &FileFlags); - return pSysNtClose ? pSysNtClose(FileHandle) : NtClose(FileHandle); + status = File_DeleteDirectory(CopyPath, TRUE); + + if (status != STATUS_DIRECTORY_NOT_EMPTY) + status = STATUS_SUCCESS; + + if (NT_SUCCESS(status)) { + + ULONG len = wcslen(TruePath); + DeletePath = Dll_AllocTemp((len + 8) * sizeof(WCHAR)); + wmemcpy(DeletePath, TruePath, len + 1); + + if (Dll_ChromeSandbox) { + + // + // if this is a Chrome sandbox process, we have + // to pass a DOS path to NtDeleteFile rather + // than a file handle + // + + if (SbieDll_TranslateNtToDosPath(DeletePath)) { + len = wcslen(DeletePath); + wmemmove(DeletePath + 4, DeletePath, len + 1); + wmemcpy(DeletePath, File_BQQB, 4); + } + } + } + + } __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + + Dll_PopTlsNameBuffer(TlsData); } // - // close for a real handle + // close the handle // + status = pSysNtClose ? pSysNtClose(FileHandle) : NtClose(FileHandle); + + // + // execute pending delete disposition + // + + if (DeletePath) { + + OBJECT_ATTRIBUTES objattrs; + RtlInitUnicodeString(&uni, DeletePath); + InitializeObjectAttributes( + &objattrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = File_NtDeleteFileImpl(&objattrs); + + Dll_Free(DeletePath); + } + + // + // finish + // + + TlsData->file_NtClose_lock = FALSE; + + SetLastError(LastError); + return status; +} + + +//--------------------------------------------------------------------------- +// File_NtCloseDir +//--------------------------------------------------------------------------- + + +_FX VOID File_NtCloseDir(HANDLE FileHandle) +{ + FILE_MERGE *merge; + EnterCriticalSection(&File_DirHandles_CritSec); merge = List_Head(&File_DirHandles); while (merge) { FILE_MERGE *next = List_Next(merge); if (merge->handle == FileHandle) { + File_UnRegisterCloseHandler(merge->handle, File_NtCloseDir); List_Remove(&File_DirHandles, merge); File_MergeFree(merge); } @@ -1997,19 +2171,6 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle) } LeaveCriticalSection(&File_DirHandles_CritSec); - - // - // close and recover file - // - - File_NotifyRecover(FileHandle); - - status = pSysNtClose ? pSysNtClose(FileHandle) : NtClose(FileHandle); - - TlsData->file_NtClose_lock = FALSE; - - SetLastError(LastError); - return status; } @@ -2348,10 +2509,6 @@ _FX void File_InitRecoverFolders(void) List_Init(&File_RecPaths); - File_RecHandles = Dll_Alloc(sizeof(HANDLE) * 128); - memzero(File_RecHandles, sizeof(HANDLE) * 128); - File_RecHandles[127] = (HANDLE)-1; - // // init list of recover folders // @@ -2580,36 +2737,35 @@ finish: _FX BOOLEAN File_RecordRecover(HANDLE FileHandle, const WCHAR *TruePath) { - ULONG i; + BOOLEAN IsRecoverable; - if (! File_RecHandles) - return FALSE; + IsRecoverable = File_IsRecoverable(TruePath); - if (! File_IsRecoverable(TruePath)) - return FALSE; + // + // in a Chrome sandbox process, handles are opened by the broker, + // so skip checking against the list of recorded file handles + // + + // Note: this does not seam to be required anymore + + //if ((! IsRecoverable) && Dll_ChromeSandbox) { + // + // FILE_ACCESS_INFORMATION info; + // + // status = __sys_NtQueryInformationFile( + // FileHandle, &IoStatusBlock, &info, + // sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation); + // + // if (NT_SUCCESS(status) && (info.AccessFlags & FILE_WRITE_DATA)) + // IsRecoverable = 2; //TRUE; // we still want to return false when called from File_NtCreateFileImpl + // else + // IsRecoverable = FALSE; + //} - EnterCriticalSection(&File_RecHandles_CritSec); + if (IsRecoverable != FALSE) + File_RegisterCloseHandler(FileHandle, File_NotifyRecover); - if (FileHandle) { - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) - if (File_RecHandles[i] == FileHandle) { - FileHandle = NULL; - break; - } - } - - if (FileHandle) { - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) - if (! File_RecHandles[i]) { - File_RecHandles[i] = FileHandle; - FileHandle = NULL; - break; - } - } - - LeaveCriticalSection(&File_RecHandles_CritSec); - - return TRUE; + return IsRecoverable == TRUE; } @@ -2624,9 +2780,6 @@ _FX void File_DuplicateRecover( ULONG i; BOOLEAN dup; - if (! File_RecHandles) - return; - // // called from NtDuplicateObject to duplicate the "recoverability" // of the old handle to the new handle. needed in particular for @@ -2635,32 +2788,20 @@ _FX void File_DuplicateRecover( dup = FALSE; - EnterCriticalSection(&File_RecHandles_CritSec); + EnterCriticalSection(&File_HandleOnClose_CritSec); - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) - if (File_RecHandles[i] == OldFileHandle) { - dup = TRUE; - break; + FILE_ON_CLOSE* on_close = map_get(&File_HandleOnClose, OldFileHandle); + if (on_close) { + for (i = 0; i < MAX_CLOSE_HANDLERS; i++) { + if(on_close->CloseHandlers[i] == File_NotifyRecover) + dup = TRUE; } - - if (dup && NewFileHandle) { - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) - if (File_RecHandles[i] == NewFileHandle) { - NewFileHandle = NULL; - break; - } } - if (dup && NewFileHandle) { - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) - if (! File_RecHandles[i]) { - File_RecHandles[i] = NewFileHandle; - NewFileHandle = NULL; - break; - } - } + LeaveCriticalSection(&File_HandleOnClose_CritSec); - LeaveCriticalSection(&File_RecHandles_CritSec); + if (dup && NewFileHandle) + File_RegisterCloseHandler(NewFileHandle, File_NotifyRecover); } @@ -2679,56 +2820,11 @@ _FX void File_NotifyRecover(HANDLE FileHandle) ULONG space[16]; } info; ULONG length; - ULONG i; ULONG FileFlags; UNICODE_STRING uni; WCHAR *TruePath, *CopyPath; IO_STATUS_BLOCK IoStatusBlock; - BOOLEAN IsRecoverable; - - // - // check input handle against list of recorded handles - // - - if (! File_RecHandles) - return; - - IsRecoverable = FALSE; - EnterCriticalSection(&File_RecHandles_CritSec); - - for (i = 0; File_RecHandles[i] != (HANDLE)-1; ++i) { - if (File_RecHandles[i] == FileHandle) - { - File_RecHandles[i] = NULL; - IsRecoverable = TRUE; - break; - } - } - - LeaveCriticalSection(&File_RecHandles_CritSec); - - // - // in a Chrome sandbox process, handles are opened by the broker, - // so skip checking against the list of recorded file handles - // - - if ((! IsRecoverable) && Dll_ChromeSandbox) { - - FILE_ACCESS_INFORMATION info; - - status = __sys_NtQueryInformationFile( - FileHandle, &IoStatusBlock, &info, - sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation); - - if (NT_SUCCESS(status) && (info.AccessFlags & FILE_WRITE_DATA)) - IsRecoverable = TRUE; - else - IsRecoverable = FALSE; - } - - if (! IsRecoverable) - return; - + // // send request to SbieCtrl (if recoverable file) // @@ -2750,8 +2846,7 @@ _FX void File_NotifyRecover(HANDLE FileHandle) // Immediate Recovery // - IsRecoverable = File_IsRecoverable(TruePath); - if (! IsRecoverable) + if (!File_IsRecoverable(TruePath)) break; status = __sys_NtQueryInformationFile( @@ -2768,42 +2863,39 @@ _FX void File_NotifyRecover(HANDLE FileHandle) // queue immediate recovery elements for later processing // - if (IsRecoverable) { + FILE_RECOVER_FOLDER *rec; + ULONG TruePath_len; - FILE_RECOVER_FOLDER *rec; - ULONG TruePath_len; + EnterCriticalSection(&File_RecHandles_CritSec); - EnterCriticalSection(&File_RecHandles_CritSec); + TruePath_len = wcslen(TruePath); - TruePath_len = wcslen(TruePath); - - rec = List_Head(&File_RecPaths); - while (rec) { - if (rec->path_len == TruePath_len) - if (_wcsicmp(rec->path, TruePath) == 0) - break; - rec = List_Next(rec); - } - - if (! rec) { - - length = sizeof(FILE_RECOVER_FOLDER) - + (TruePath_len + 1) * sizeof(WCHAR); - rec = Dll_Alloc(length); - - rec->ticks = GetTickCount(); - - wcscpy(rec->path, TruePath); - rec->path_len = TruePath_len; - - List_Insert_After(&File_RecPaths, NULL, rec); - } - - LeaveCriticalSection(&File_RecHandles_CritSec); - if (rec) - File_DoAutoRecover(TRUE); + rec = List_Head(&File_RecPaths); + while (rec) { + if (rec->path_len == TruePath_len) + if (_wcsicmp(rec->path, TruePath) == 0) + break; + rec = List_Next(rec); } + if (! rec) { + + length = sizeof(FILE_RECOVER_FOLDER) + + (TruePath_len + 1) * sizeof(WCHAR); + rec = Dll_Alloc(length); + + rec->ticks = GetTickCount(); + + wcscpy(rec->path, TruePath); + rec->path_len = TruePath_len; + + List_Insert_After(&File_RecPaths, NULL, rec); + } + + LeaveCriticalSection(&File_RecHandles_CritSec); + if (rec) + File_DoAutoRecover(TRUE); + } while (0); Dll_PopTlsNameBuffer(TlsData); diff --git a/Sandboxie/core/dll/file_init.c b/Sandboxie/core/dll/file_init.c index 8bedcc22..cdc0b8ad 100644 --- a/Sandboxie/core/dll/file_init.c +++ b/Sandboxie/core/dll/file_init.c @@ -122,6 +122,20 @@ static const WCHAR *File_DeviceMap_EnvVar = ENV_VAR_PFX L"DEVICE_MAP"; #undef ENV_VAR_PFX +//--------------------------------------------------------------------------- +// File_InitHandles +//--------------------------------------------------------------------------- + + +_FX BOOLEAN File_InitHandles(void) +{ + InitializeCriticalSection(&File_HandleOnClose_CritSec); + map_init(&File_HandleOnClose, Dll_Pool); + + return TRUE; +} + + //--------------------------------------------------------------------------- // File_Init //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/guiclass.c b/Sandboxie/core/dll/guiclass.c index a8980904..783a44ae 100644 --- a/Sandboxie/core/dll/guiclass.c +++ b/Sandboxie/core/dll/guiclass.c @@ -149,12 +149,12 @@ _FX BOOLEAN Gui_InitClass(void) Gui_BoxPrefixA[len - 1] = '\0'; // NoSbieDesk BEGIN - if (SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) { - - Gui_OpenAllWinClasses = TRUE; - Gui_RenameClasses = FALSE; - } - else + //if (SbieApi_QueryConfBool(NULL, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(NULL, L"NoSandboxieDesktop", FALSE)) { + // + // Gui_OpenAllWinClasses = TRUE; + // Gui_RenameClasses = FALSE; + //} + //else // NoSbieDesk END // diff --git a/Sandboxie/core/dll/includes.c b/Sandboxie/core/dll/includes.c index 1ae3ff08..ab80c662 100644 --- a/Sandboxie/core/dll/includes.c +++ b/Sandboxie/core/dll/includes.c @@ -34,6 +34,10 @@ extern const ULONG tzuk; #define POOL_TAG tzuk #include "common/pool.c" +/* Map */ + +#include "common/map.c" + /* Stream */ #include "common/stream.c" diff --git a/Sandboxie/core/dll/key_merge.c b/Sandboxie/core/dll/key_merge.c index cad7bda1..82e7606e 100644 --- a/Sandboxie/core/dll/key_merge.c +++ b/Sandboxie/core/dll/key_merge.c @@ -200,6 +200,7 @@ _FX NTSTATUS Key_Merge( // if we got here, we need to discard the stale entry // + File_UnRegisterCloseHandler(merge->handle, Key_NtClose); List_Remove(&Key_Handles, merge); Key_MergeFree(merge, TRUE); @@ -225,6 +226,7 @@ _FX NTSTATUS Key_Merge( memcpy(merge->name, TruePath, TruePath_len + sizeof(WCHAR)); List_Insert_Before(&Key_Handles, NULL, merge); + File_RegisterCloseHandler(merge->handle, Key_NtClose); } // diff --git a/Sandboxie/core/dll/ldr.c b/Sandboxie/core/dll/ldr.c index e708bc4e..632667d4 100644 --- a/Sandboxie/core/dll/ldr.c +++ b/Sandboxie/core/dll/ldr.c @@ -21,6 +21,7 @@ #include "dll.h" +#include "sbieapi.h" #include "core/drv/api_flags.h" //--------------------------------------------------------------------------- @@ -30,9 +31,6 @@ #define LDR_NUM_CALLBACKS 8 -#define LDR_TOKEN_PRIMARY -4 -#define LDR_TOKEN_IMPERSONATION -5 -#define LDR_TOKEN_EFFECTIVE -6 //--------------------------------------------------------------------------- // Structures and Types @@ -104,13 +102,12 @@ static NTSTATUS Ldr_NtLoadDriver(UNICODE_STRING *RegistryPath); static BOOL LdrCheckImmersive(); -static NTSTATUS Ldr_LdrRegisterDllNotification(ULONG Flags, void * NotificationFunction, PVOID Context, PVOID *Cookie); -static NTSTATUS Ldr_LdrUnregisterDllNotification(void * Cookie); +//static NTSTATUS Ldr_LdrRegisterDllNotification(ULONG Flags, void * NotificationFunction, PVOID Context, PVOID *Cookie); +//static NTSTATUS Ldr_LdrUnregisterDllNotification(void * Cookie); static void CALLBACK Ldr_LdrDllNotification(ULONG NotificationReason, PLDR_DLL_NOTIFICATION_DATA NotificationData, void * Context); -static BOOL Ldr_NtOpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle); -static BOOL Ldr_RtlEqualSid(void * sid1, void * sid2); +static void Ldr_LoadSkipList(); //--------------------------------------------------------------------------- @@ -152,27 +149,13 @@ typedef void(*P_LdrDllCallback)(const UCHAR *ImageName, HMODULE ImageBase); typedef void(*P_LdrDllCallbackW)(const WCHAR *ImageName, HMODULE ImageBase); typedef void(*P_Ldr_CallOneDllCallback)(const UCHAR *ImageNameA, ULONG_PTR ImageBase); -typedef NTSTATUS(WINAPI *P_NtAccessCheckByType) ( - PSECURITY_DESCRIPTOR SecurityDescriptor, - PSID PrincipalSelfSid, - HANDLE ClientToken, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE_LIST ObjectTypeList, - ULONG ObjectTypeListLength, - PGENERIC_MAPPING GenericMapping, - PPRIVILEGE_SET PrivilegeSet, - PULONG PrivilegeSetLength, - PACCESS_MASK GrantedAccess, - PNTSTATUS AccessStatus); - -typedef BOOL(*P_RtlEqualSid) (void * sid1, void * sid2); //--------------------------------------------------------------------------- static P_LdrRegisterDllNotification __sys_LdrRegisterDllNotification = NULL; static P_LdrUnregisterDllNotification __sys_LdrUnregisterDllNotification = NULL; -static P_NtTerminateProcess __sys_NtTerminateProcess = NULL; +static P_NtTerminateProcess __sys_NtTerminateProcess = NULL; static P_LdrLockLoaderLock __sys_LdrLockLoaderLock = NULL; static P_LdrUnlockLoaderLock __sys_LdrUnlockLoaderLock = NULL; @@ -187,20 +170,10 @@ static P_NtApphelpCacheControl __sys_NtApphelpCacheControl = NULL; static P_NtLoadDriver __sys_NtLoadDriver = NULL; -P_LdrGetDllHandleEx __sys_LdrGetDllHandleEx = NULL; +P_LdrGetDllHandleEx __sys_LdrGetDllHandleEx = NULL; static P_Ldr_CallOneDllCallback __my_Ldr_CallOneDllCallback = NULL; -static P_NtOpenThreadToken __sys_NtOpenThreadToken = NULL; - -P_RtlEqualSid __sys_RtlEqualSid = NULL; - -extern ULONG Dll_Windows; - -extern BOOLEAN Secure_Is_IE_NtQueryInformationToken; - -extern BOOLEAN Secure_FakeAdmin; - //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- @@ -275,68 +248,6 @@ static volatile BOOLEAN Ldr_LdrLoadDll_Invoked = FALSE; #include "ldr_init.c" -NTSTATUS Ldr_NtAccessCheckByType( - PSECURITY_DESCRIPTOR SecurityDescriptor, - PSID PrincipalSelfSid, - HANDLE ClientToken, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE_LIST ObjectTypeList, - ULONG ObjectTypeListLength, - PGENERIC_MAPPING GenericMapping, - PPRIVILEGE_SET PrivilegeSet, - PULONG PrivilegeSetLength, - PACCESS_MASK GrantedAccess, - PNTSTATUS AccessStatus -); - -NTSTATUS Ldr_NtAccessCheckByTypeResultList( - PSECURITY_DESCRIPTOR SecurityDescriptor, - PSID PrincipalSelfSid, - HANDLE ClientToken, - ACCESS_MASK DesiredAccess, - POBJECT_TYPE_LIST ObjectTypeList, - ULONG ObjectTypeListLength, - PGENERIC_MAPPING GenericMapping, - PPRIVILEGE_SET PrivilegeSet, - PULONG PrivilegeSetLength, - PACCESS_MASK GrantedAccess, - PNTSTATUS AccessStatus -); - -NTSTATUS Ldr_NtAccessCheck( - IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN HANDLE ClientToken, - IN ACCESS_MASK DesiredAccess, - IN PGENERIC_MAPPING GenericMapping OPTIONAL, - OUT PPRIVILEGE_SET RequiredPrivilegesBuffer, - IN OUT PULONG BufferLength, - OUT PACCESS_MASK GrantedAccess, - OUT PNTSTATUS AccessStatus); - -NTSTATUS Ldr_NtQuerySecurityAttributesToken( - IN HANDLE TokenHandle, - IN PUNICODE_STRING Attributes, - IN ULONG NumberOfAttributes, - OUT PVOID Buffer, - IN ULONG Length, - OUT PULONG ReturnLength); - -NTSTATUS Ldr_NtQueryInformationToken( - HANDLE TokenHandle, - TOKEN_INFORMATION_CLASS TokenInformationClass, - void *TokenInformation, - ULONG TokenInformationLength, - ULONG *ReturnLength); - -NTSTATUS Ldr_NtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus); - -static P_NtAccessCheckByType __sys_NtAccessCheckByType = NULL; -static P_NtAccessCheck __sys_NtAccessCheck = NULL; -static P_NtQuerySecurityAttributesToken __sys_NtQuerySecurityAttributesToken = NULL; -static P_NtQueryInformationToken __sys_NtQueryInformationToken = NULL; -static P_NtAccessCheckByTypeResultList __sys_NtAccessCheckByTypeResultList = NULL; - - NTSTATUS Ldr_NtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) { @@ -379,17 +290,17 @@ void CALLBACK Ldr_LdrDllNotification(ULONG NotificationReason, PLDR_DLL_NOTIFICA //--------------------------------------------------------------------------- -_FX NTSTATUS Ldr_LdrRegisterDllNotification(ULONG Flags, void * NotificationFunction, PVOID Context, PVOID *Cookie) -{ - NTSTATUS status = 0; - status = __sys_LdrRegisterDllNotification(0, ((void *)Ldr_LdrDllNotification), NULL, Cookie); - return status; -} - -_FX NTSTATUS Ldr_LdrUnregisterDllNotification(void * Cookie) -{ - return STATUS_SUCCESS; -} +//_FX NTSTATUS Ldr_LdrRegisterDllNotification(ULONG Flags, void * NotificationFunction, PVOID Context, PVOID *Cookie) +//{ +// NTSTATUS status = 0; +// status = __sys_LdrRegisterDllNotification(0, ((void *)Ldr_LdrDllNotification), NULL, Cookie); +// return status; +//} +// +//_FX NTSTATUS Ldr_LdrUnregisterDllNotification(void * Cookie) +//{ +// return STATUS_SUCCESS; +//} //--------------------------------------------------------------------------- // LdrCheckImmersive @@ -492,11 +403,14 @@ _FX BOOLEAN Ldr_Init() Ldr_Callbacks = Dll_Alloc(sizeof(ULONG_PTR) * LDR_NUM_CALLBACKS); memzero(Ldr_Callbacks, sizeof(ULONG_PTR) * LDR_NUM_CALLBACKS); - if (Dll_OsBuild >= 6000) { // Windows Vista + Ldr_LoadSkipList(); + + + if (Dll_OsBuild >= 6000) { // Windows Vista and later SbieDll_RegisterDllCallback(Ldr_MyDllCallbackA); __my_Ldr_CallOneDllCallback = Ldr_CallOneDllCallback; } - else { + else { // Windows XP SbieDll_RegisterDllCallback(Ldr_MyDllCallbackW); __my_Ldr_CallOneDllCallback = Ldr_CallOneDllCallbackXP; } @@ -505,26 +419,6 @@ _FX BOOLEAN Ldr_Init() // hook entrypoints // - void* RtlEqualSid = (P_RtlEqualSid)GetProcAddress(Dll_Ntdll, "RtlEqualSid"); - - SBIEDLL_HOOK(Ldr_, RtlEqualSid); - - if (Secure_FakeAdmin || Dll_OsBuild >= 9600) { - - void* NtAccessCheckByType = GetProcAddress(Dll_Ntdll, "NtAccessCheckByType"); - void* NtAccessCheck = GetProcAddress(Dll_Ntdll, "NtAccessCheck"); - void* NtQuerySecurityAttributesToken = GetProcAddress(Dll_Ntdll, "NtQuerySecurityAttributesToken"); - void* NtQueryInformationToken = GetProcAddress(Dll_Ntdll, "NtQueryInformationToken"); - void* NtAccessCheckByTypeResultList = GetProcAddress(Dll_Ntdll, "NtAccessCheckByTypeResultList"); - - - SBIEDLL_HOOK(Ldr_, NtQuerySecurityAttributesToken); - SBIEDLL_HOOK(Ldr_, NtAccessCheckByType); - SBIEDLL_HOOK(Ldr_, NtAccessCheck); - SBIEDLL_HOOK(Ldr_, NtAccessCheckByTypeResultList); - SBIEDLL_HOOK(Ldr_, NtQueryInformationToken); - } - if (Dll_OsBuild >= 9600) { // Windows 8.1 and later NTSTATUS rc = 0; @@ -546,16 +440,12 @@ _FX BOOLEAN Ldr_Init() SBIEDLL_HOOK(Ldr_, NtTerminateProcess); SBIEDLL_HOOK(Ldr_Win10_, LdrLoadDll); - SBIEDLL_HOOK(Ldr_, NtLoadDriver); - if (DLL_IMAGE_GOOGLE_CHROME == Dll_ImageType) { - SBIEDLL_HOOK(Ldr_, NtOpenThreadToken); - } } else { // Windows 8 and before SBIEDLL_HOOK(Ldr_, LdrLoadDll); SBIEDLL_HOOK(Ldr_, LdrUnloadDll); SBIEDLL_HOOK(Ldr_, LdrQueryImageFileExecutionOptions); - SBIEDLL_HOOK(Ldr_, NtLoadDriver); + if (Dll_OsBuild >= 8400) { P_LdrResolveDelayLoadedAPI LdrResolveDelayLoadedAPI = @@ -569,8 +459,10 @@ _FX BOOLEAN Ldr_Init() SBIEDLL_HOOK(Ldr_, LdrResolveDelayLoadedAPI); SBIEDLL_HOOK(Ldr_, NtApphelpCacheControl); } - } + SBIEDLL_HOOK(Ldr_, NtLoadDriver); + + // // set PEB.ReadImageFileExecOptions to non-zero to force ntdll to call // LdrQueryImageFileExecutionOptions so we can call Ldr_CallDllCallbacks @@ -1082,7 +974,7 @@ _FX void Ldr_MyDllCallbackA(const CHAR *ImageName, HMODULE ImageBase) DLL *dll = Ldr_Dlls; while (dll->nameA) { - if (_stricmp(ImageName, dll->nameA) == 0) { + if (_stricmp(ImageName, dll->nameA) == 0 && (dll->state & 2) == 0) { BOOLEAN ok = dll->init_func(ImageBase); if (!ok) SbieApi_Log(2318, dll->nameW); @@ -1102,7 +994,7 @@ _FX void Ldr_MyDllCallbackW(const WCHAR *ImageName, HMODULE ImageBase) DLL *dll = Ldr_Dlls; while (dll->nameW) { - if (_wcsicmp(ImageName, dll->nameW) == 0) { + if (_wcsicmp(ImageName, dll->nameW) == 0 && (dll->state & 2) == 0) { BOOLEAN ok = dll->init_func(ImageBase); if (!ok) SbieApi_Log(2318, dll->nameW); @@ -1125,7 +1017,7 @@ _FX void Ldr_MyDllCallbackNew(const WCHAR *ImageName, HMODULE ImageBase) while (dll->nameW) { BOOLEAN ok; - if (_wcsicmp(ImageName, dll->nameW) == 0) { + if (_wcsicmp(ImageName, dll->nameW) == 0 && (dll->state & 2) == 0) { if (ImageBase && !dll->state) { EnterCriticalSection(&Ldr_LoadedModules_CritSec); dll->state = 1; @@ -1377,221 +1269,30 @@ _FX NTSTATUS Ldr_NtLoadDriver(UNICODE_STRING *RegistryPath) return status; } + +//--------------------------------------------------------------------------- +// Ldr_LoadSkipList //--------------------------------------------------------------------------- -_FX void Ldr_TestToken(HANDLE token, PHANDLE hTokenReal) + +void Ldr_LoadSkipList() { - if (Dll_OsBuild < 9600) // this magic values are available only from windows 8.1 onwards - return; - - if ((LONG_PTR)token == LDR_TOKEN_PRIMARY) { - NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, hTokenReal); - } - else if ((LONG_PTR)token == LDR_TOKEN_IMPERSONATION) { - NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, hTokenReal); - } - else if ((LONG_PTR)token <= LDR_TOKEN_EFFECTIVE) { - NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, hTokenReal); - if (!hTokenReal) { - NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, hTokenReal); - } - } - return; -} - -_FX NTSTATUS Ldr_NtQueryInformationToken( - HANDLE TokenHandle, - TOKEN_INFORMATION_CLASS TokenInformationClass, - void *TokenInformation, - ULONG TokenInformationLength, - ULONG *ReturnLength) -{ - NTSTATUS status = 0; - THREAD_DATA *TlsData = NULL; - HANDLE hTokenReal = NULL; - BOOLEAN FakeAdmin = FALSE; - - Ldr_TestToken(TokenHandle, &hTokenReal); - - status = __sys_NtQueryInformationToken( - hTokenReal ? hTokenReal : TokenHandle, TokenInformationClass, - TokenInformation, TokenInformationLength, ReturnLength); - - if (hTokenReal) - { - NtClose(hTokenReal); - } - - // - // To make the process think we need to chage here a fe values - // we also ensure that tha token belongs to the current process - // - - if (Secure_FakeAdmin && (SbieApi_QueryProcessInfoEx(0, 'ippt', (LONG_PTR)hTokenReal))) - { - FakeAdmin = TRUE; - } - - // - // NtQueryInformationToken is hooked for Internet Explorer. - // - // if the check occurs during CreateProcess, then return the real - // information, so UAC elevation may occur for the new process. - // - // otherwise, this check is related to Protected Mode, so pretend - // we are running as Administrator - // - - TlsData = Dll_GetTlsData(NULL); - - if (Secure_Is_IE_NtQueryInformationToken && !TlsData->proc_create_process) - { - FakeAdmin = TRUE; - } - - if (NT_SUCCESS(status) && FakeAdmin) { - - if (TokenInformationClass == TokenElevation) { - - *(BOOLEAN *)TokenInformation = TRUE; - } - - else if (TokenInformationClass == TokenElevationType) { - - // - // on Vista, fake a return value for a full token - // - - *(ULONG *)TokenInformation = TokenElevationTypeFull; - } - - else if (TokenInformationClass == TokenIntegrityLevel) { - - // - // on Vista, fake a high integrity level - // - -#include "pshpack4.h" - - typedef struct { - - ULONG_PTR Pointer; - ULONG_PTR Sixty; - ULONG OneOhOne; - ULONG HighBitSet; - ULONG ThreeK; - - } TOKEN_INTEGRITY_LEVEL; - -#include "poppack.h" - - if (TokenInformationLength >= sizeof(TOKEN_INTEGRITY_LEVEL)) { - - TOKEN_INTEGRITY_LEVEL *Info = - (TOKEN_INTEGRITY_LEVEL *)TokenInformation; - - Info->Pointer = (ULONG_PTR)TokenInformation - + sizeof(ULONG_PTR) * 2; - Info->Sixty = 0x60; - Info->OneOhOne = 0x101; - Info->HighBitSet = 0x10000000; - Info->ThreeK = 0x3000; - - if (ReturnLength) - *ReturnLength = sizeof(TOKEN_INTEGRITY_LEVEL); + WCHAR buf[128]; + ULONG index = 0; + while (1) { // for each setting + NTSTATUS status = SbieApi_QueryConfAsIs(NULL, L"DllSkipHook", index, buf, sizeof(buf)); + ++index; + if (NT_SUCCESS(status)) { + DLL *dll = Ldr_Dlls; + while (dll->nameW) { // find dll entry + if (_wcsicmp(buf, dll->nameW) == 0) { + dll->state |= 2; + break; + } + ++dll; } } + else if (status != STATUS_BUFFER_TOO_SMALL) + break; } - - return status; -} - -_FX NTSTATUS Ldr_NtQuerySecurityAttributesToken(HANDLE TokenHandle, PUNICODE_STRING Attributes, ULONG NumberOfAttributes, PVOID Buffer, ULONG Length, PULONG ReturnLength) -{ - NTSTATUS status = 0; - HANDLE hTokenReal = NULL; - - Ldr_TestToken(TokenHandle, &hTokenReal); - - status = __sys_NtQuerySecurityAttributesToken(hTokenReal ? hTokenReal : TokenHandle, Attributes, NumberOfAttributes, Buffer, Length, ReturnLength); - - if (hTokenReal) { - NtClose(hTokenReal); - } - return status; -} - -NTSTATUS Ldr_NtAccessCheckByType(PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, ACCESS_MASK DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, ULONG ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, PULONG PrivilegeSetLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) -{ - NTSTATUS rc; - HANDLE hTokenReal = NULL; - - if (Dll_ImageType == DLL_IMAGE_SANDBOXIE_BITS || - Dll_ImageType == DLL_IMAGE_SANDBOXIE_WUAU || - Dll_ImageType == DLL_IMAGE_WUAUCLT) { - *GrantedAccess = 0xFFFFFFFF; - *AccessStatus = TRUE; - SetLastError(0); - return TRUE; - } - - Ldr_TestToken(ClientToken, &hTokenReal); - - rc = __sys_NtAccessCheckByType(SecurityDescriptor, PrincipalSelfSid, hTokenReal ? hTokenReal : ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus); - - if (hTokenReal) { - NtClose(hTokenReal); - } - - return rc; -} - - -_FX NTSTATUS Ldr_NtAccessCheck(PSECURITY_DESCRIPTOR SecurityDescriptor, HANDLE ClientToken, ACCESS_MASK DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET RequiredPrivilegesBuffer, PULONG BufferLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) -{ - NTSTATUS status = 0; - HANDLE hTokenReal = NULL; - - Ldr_TestToken(ClientToken, &hTokenReal); - - status = __sys_NtAccessCheck(SecurityDescriptor, hTokenReal ? hTokenReal : ClientToken, DesiredAccess, GenericMapping, RequiredPrivilegesBuffer, BufferLength, GrantedAccess, AccessStatus); - - if (hTokenReal) { - NtClose(hTokenReal); - } - return status; -} - -_FX NTSTATUS Ldr_NtAccessCheckByTypeResultList(PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, ACCESS_MASK DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, ULONG ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, PULONG PrivilegeSetLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) -{ - NTSTATUS status = 0; - HANDLE hTokenReal = NULL; - - Ldr_TestToken(ClientToken, &hTokenReal); - - status = __sys_NtAccessCheckByTypeResultList(SecurityDescriptor, PrincipalSelfSid, ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus); - - if (hTokenReal) { - NtClose(hTokenReal); - } - return status; -} - -BOOL Ldr_NtOpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle) -{ - BOOL rc; - - rc = __sys_NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle); - if (rc == STATUS_ACCESS_DENIED && OpenAsSelf) { - rc = __sys_NtOpenThreadToken(ThreadHandle, DesiredAccess, 0, TokenHandle); - } - return rc; -} - -BOOL Ldr_RtlEqualSid(void * sid1, void * sid2) -{ - if (!sid1 || !sid2) { - return FALSE; - } - return __sys_RtlEqualSid(sid1, sid2); -} +} \ No newline at end of file diff --git a/Sandboxie/core/dll/sbieapi.c b/Sandboxie/core/dll/sbieapi.c index 0d98c1a8..aaae497a 100644 --- a/Sandboxie/core/dll/sbieapi.c +++ b/Sandboxie/core/dll/sbieapi.c @@ -962,16 +962,18 @@ _FX LONG SbieApi_CheckInternetAccess( WCHAR MyDeviceName[34]; ULONG len; - len = wcslen(DeviceName32); - if (len > 32) - len = 32; - memzero(MyDeviceName, sizeof(MyDeviceName)); - wmemcpy(MyDeviceName, DeviceName32, len); + if (DeviceName32) { + len = wcslen(DeviceName32); + if (len > 32) + len = 32; + memzero(MyDeviceName, sizeof(MyDeviceName)); + wmemcpy(MyDeviceName, DeviceName32, len); + } memzero(parms, sizeof(parms)); args->func_code = API_CHECK_INTERNET_ACCESS; args->process_id.val64 = (ULONG64)(ULONG_PTR)ProcessId; - args->device_name.val64 = (ULONG64)(ULONG_PTR)MyDeviceName; + args->device_name.val64 = (ULONG64)(ULONG_PTR)(DeviceName32 ? MyDeviceName : NULL); args->issue_message.val64 = (ULONG64)(ULONG_PTR)IssueMessage; status = SbieApi_Ioctl(parms); diff --git a/Sandboxie/core/dll/sbiedll.h b/Sandboxie/core/dll/sbiedll.h index bd78deed..4288f150 100644 --- a/Sandboxie/core/dll/sbiedll.h +++ b/Sandboxie/core/dll/sbiedll.h @@ -216,9 +216,6 @@ SBIEDLL_EXPORT BOOLEAN SbieDll_GetSettingsForImageName_bool( SBIEDLL_EXPORT BOOLEAN SbieDll_GetBorderColor(const WCHAR* box_name, COLORREF* color, BOOL* title, int* width); - -//--------------------------------------------------------------------------- - SBIEDLL_EXPORT BOOLEAN SbieDll_IsReservedFileName(const WCHAR* name); //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/scm_msi.c b/Sandboxie/core/dll/scm_msi.c index 456da88a..165f52f6 100644 --- a/Sandboxie/core/dll/scm_msi.c +++ b/Sandboxie/core/dll/scm_msi.c @@ -191,6 +191,20 @@ _FX HANDLE Scm_CreateWaitableTimerW( } +//--------------------------------------------------------------------------- +// Scm_TokenCloseHandler +//--------------------------------------------------------------------------- + + +_FX VOID Scm_TokenCloseHandler(HANDLE Handle) +{ + THREAD_DATA *TlsData = Dll_GetTlsData(NULL); + + if (TlsData->scm_last_own_token == Handle) + TlsData->scm_last_own_token = NULL; +} + + //--------------------------------------------------------------------------- // Scm_OpenProcessToken //--------------------------------------------------------------------------- @@ -203,6 +217,8 @@ _FX BOOL Scm_OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE NTSTATUS status = __sys_OpenProcessToken(ProcessHandle, DesiredAccess, phTokenOut); if (NT_SUCCESS(status) && ProcessHandle == GetCurrentProcess()) { + + File_RegisterCloseHandler(*phTokenOut, Scm_TokenCloseHandler); TlsData->scm_last_own_token = *phTokenOut; } diff --git a/Sandboxie/core/dll/secure.c b/Sandboxie/core/dll/secure.c index 12efb0a0..2708f895 100644 --- a/Sandboxie/core/dll/secure.c +++ b/Sandboxie/core/dll/secure.c @@ -27,6 +27,16 @@ #include +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + + +#define LDR_TOKEN_PRIMARY -4 +#define LDR_TOKEN_IMPERSONATION -5 +#define LDR_TOKEN_EFFECTIVE -6 + + //--------------------------------------------------------------------------- // Functions //--------------------------------------------------------------------------- @@ -65,12 +75,66 @@ static NTSTATUS Secure_NtSetSecurityObject( SECURITY_INFORMATION SecurityInformation, SECURITY_DESCRIPTOR *SecurityDescriptor); -static NTSTATUS Secure_NtQueryInformationToken( +NTSTATUS Ldr_NtAccessCheckByType( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID PrincipalSelfSid, + HANDLE ClientToken, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE_LIST ObjectTypeList, + ULONG ObjectTypeListLength, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + PULONG PrivilegeSetLength, + PACCESS_MASK GrantedAccess, + PNTSTATUS AccessStatus +); + +NTSTATUS Ldr_NtAccessCheckByTypeResultList( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID PrincipalSelfSid, + HANDLE ClientToken, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE_LIST ObjectTypeList, + ULONG ObjectTypeListLength, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + PULONG PrivilegeSetLength, + PACCESS_MASK GrantedAccess, + PNTSTATUS AccessStatus +); + +NTSTATUS Ldr_NtAccessCheck( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping OPTIONAL, + OUT PPRIVILEGE_SET RequiredPrivilegesBuffer, + IN OUT PULONG BufferLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus); + +NTSTATUS Ldr_NtQuerySecurityAttributesToken( + IN HANDLE TokenHandle, + IN PUNICODE_STRING Attributes, + IN ULONG NumberOfAttributes, + OUT PVOID Buffer, + IN ULONG Length, + OUT PULONG ReturnLength); + +NTSTATUS Ldr_NtQueryInformationToken( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, void *TokenInformation, ULONG TokenInformationLength, ULONG *ReturnLength); + +static BOOL Ldr_NtOpenThreadToken( + HANDLE ThreadHandle, + DWORD DesiredAccess, + BOOL OpenAsSelf, + PHANDLE TokenHandle); + +static BOOL Ldr_RtlEqualSid(void * sid1, void * sid2); static NTSTATUS Secure_NtSetInformationToken( HANDLE TokenHandle, @@ -138,14 +202,19 @@ static P_NtOpenThread __sys_NtOpenThread = NULL; static P_NtDuplicateObject __sys_NtDuplicateObject = NULL; static P_NtQuerySecurityObject __sys_NtQuerySecurityObject = NULL; static P_NtSetSecurityObject __sys_NtSetSecurityObject = NULL; -static P_NtQueryInformationToken __sys_NtQueryInformationToken = NULL; +static P_NtAccessCheckByType __sys_NtAccessCheckByType = NULL; +static P_NtAccessCheck __sys_NtAccessCheck = NULL; +static P_NtQuerySecurityAttributesToken __sys_NtQuerySecurityAttributesToken = NULL; +static P_NtQueryInformationToken __sys_NtQueryInformationToken = NULL; +static P_NtAccessCheckByTypeResultList __sys_NtAccessCheckByTypeResultList = NULL; +static P_NtOpenThreadToken __sys_NtOpenThreadToken = NULL; + P_RtlEqualSid __sys_RtlEqualSid = NULL; static P_NtSetInformationToken __sys_NtSetInformationToken = NULL; static P_NtAdjustPrivilegesToken __sys_NtAdjustPrivilegesToken = NULL; static P_NtDuplicateToken __sys_NtDuplicateToken = NULL; static P_NtFilterToken __sys_NtFilterToken = NULL; static P_RtlQueryElevationFlags __sys_RtlQueryElevationFlags = NULL; static P_RtlCheckTokenMembershipEx __sys_RtlCheckTokenMembershipEx = NULL; -static P_NtQuerySecurityAttributesToken __sys_NtQuerySecurityAttributesToken = NULL; //--------------------------------------------------------------------------- @@ -303,8 +372,34 @@ _FX BOOLEAN Secure_Init(void) SBIEDLL_HOOK(Secure_, NtFilterToken); //NtFilterTokenEx is only present in windows 8 later windoses return STATUS_NOT_SUPPORTED } - if (Dll_Windows < 10) { - SBIEDLL_HOOK(Secure_, NtQueryInformationToken); + //if (Dll_Windows < 10) { + // SBIEDLL_HOOK(Secure_, NtQueryInformationToken); + //} + + void* RtlEqualSid = (P_RtlEqualSid)GetProcAddress(Dll_Ntdll, "RtlEqualSid"); + + SBIEDLL_HOOK(Ldr_, RtlEqualSid); + + if (Secure_FakeAdmin || Dll_OsBuild >= 9600) { + + void* NtAccessCheckByType = GetProcAddress(Dll_Ntdll, "NtAccessCheckByType"); + void* NtAccessCheck = GetProcAddress(Dll_Ntdll, "NtAccessCheck"); + void* NtQuerySecurityAttributesToken = GetProcAddress(Dll_Ntdll, "NtQuerySecurityAttributesToken"); + void* NtQueryInformationToken = GetProcAddress(Dll_Ntdll, "NtQueryInformationToken"); + void* NtAccessCheckByTypeResultList = GetProcAddress(Dll_Ntdll, "NtAccessCheckByTypeResultList"); + + + SBIEDLL_HOOK(Ldr_, NtQuerySecurityAttributesToken); + SBIEDLL_HOOK(Ldr_, NtAccessCheckByType); + SBIEDLL_HOOK(Ldr_, NtAccessCheck); + SBIEDLL_HOOK(Ldr_, NtAccessCheckByTypeResultList); + SBIEDLL_HOOK(Ldr_, NtQueryInformationToken); + } + + if (Dll_OsBuild >= 9600) { // Windows 8.1 and later + if (DLL_IMAGE_GOOGLE_CHROME == Dll_ImageType) { + SBIEDLL_HOOK(Ldr_, NtOpenThreadToken); + } } // @@ -787,7 +882,27 @@ _FX NTSTATUS Secure_NtSetSecurityObject( //--------------------------------------------------------------------------- -_FX NTSTATUS Secure_NtQueryInformationToken( +_FX void Ldr_TestToken(HANDLE token, PHANDLE hTokenReal) +{ + if (Dll_OsBuild < 9600) // this magic values are available only from windows 8.1 onwards + return; + + if ((LONG_PTR)token == LDR_TOKEN_PRIMARY) { + NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, hTokenReal); + } + else if ((LONG_PTR)token == LDR_TOKEN_IMPERSONATION) { + NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, hTokenReal); + } + else if ((LONG_PTR)token <= LDR_TOKEN_EFFECTIVE) { + NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, hTokenReal); + if (!hTokenReal) { + NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, hTokenReal); + } + } + return; +} + +_FX NTSTATUS Ldr_NtQueryInformationToken( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, void *TokenInformation, @@ -796,21 +911,32 @@ _FX NTSTATUS Secure_NtQueryInformationToken( { NTSTATUS status = 0; THREAD_DATA *TlsData = NULL; + HANDLE hTokenReal = NULL; + BOOLEAN FakeAdmin = FALSE; + Ldr_TestToken(TokenHandle, &hTokenReal); status = __sys_NtQueryInformationToken( - TokenHandle, TokenInformationClass, + hTokenReal ? hTokenReal : TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength); - if (!Secure_Is_IE_NtQueryInformationToken) + // + // To make the process think we need to chage here a few values + // we also ensure that tha token belongs to the current process + // + + if (Secure_FakeAdmin && (SbieApi_QueryProcessInfoEx(0, 'ippt', (LONG_PTR)(hTokenReal ? hTokenReal : TokenHandle)))) { - return status; + FakeAdmin = TRUE; } - TlsData = Dll_GetTlsData(NULL); + if (hTokenReal) + { + NtClose(hTokenReal); + } // - // NtQueryInformationToken is hooked only for Internet Explorer. + // NtQueryInformationToken is hooked for Internet Explorer. // // if the check occurs during CreateProcess, then return the real // information, so UAC elevation may occur for the new process. @@ -819,9 +945,21 @@ _FX NTSTATUS Secure_NtQueryInformationToken( // we are running as Administrator // - if (NT_SUCCESS(status) && (! TlsData->proc_create_process)) { + TlsData = Dll_GetTlsData(NULL); - if (TokenInformationClass == TokenElevationType) { + if (Secure_Is_IE_NtQueryInformationToken && !TlsData->proc_create_process) + { + FakeAdmin = TRUE; + } + + if (NT_SUCCESS(status) && FakeAdmin) { + + if (TokenInformationClass == TokenElevation) { + + *(BOOLEAN *)TokenInformation = TRUE; + } + + else if (TokenInformationClass == TokenElevationType) { // // on Vista, fake a return value for a full token @@ -830,7 +968,7 @@ _FX NTSTATUS Secure_NtQueryInformationToken( *(ULONG *)TokenInformation = TokenElevationTypeFull; } - if (TokenInformationClass == TokenIntegrityLevel) { + else if (TokenInformationClass == TokenIntegrityLevel) { // // on Vista, fake a high integrity level @@ -855,12 +993,12 @@ _FX NTSTATUS Secure_NtQueryInformationToken( TOKEN_INTEGRITY_LEVEL *Info = (TOKEN_INTEGRITY_LEVEL *)TokenInformation; - Info->Pointer = (ULONG_PTR)TokenInformation - + sizeof(ULONG_PTR) * 2; - Info->Sixty = 0x60; - Info->OneOhOne = 0x101; - Info->HighBitSet = 0x10000000; - Info->ThreeK = 0x3000; + Info->Pointer = (ULONG_PTR)TokenInformation + + sizeof(ULONG_PTR) * 2; + Info->Sixty = 0x60; + Info->OneOhOne = 0x101; + Info->HighBitSet = 0x10000000; + Info->ThreeK = 0x3000; if (ReturnLength) *ReturnLength = sizeof(TOKEN_INTEGRITY_LEVEL); @@ -871,6 +1009,96 @@ _FX NTSTATUS Secure_NtQueryInformationToken( return status; } +_FX NTSTATUS Ldr_NtQuerySecurityAttributesToken(HANDLE TokenHandle, PUNICODE_STRING Attributes, ULONG NumberOfAttributes, PVOID Buffer, ULONG Length, PULONG ReturnLength) +{ + NTSTATUS status = 0; + HANDLE hTokenReal = NULL; + + Ldr_TestToken(TokenHandle, &hTokenReal); + + status = __sys_NtQuerySecurityAttributesToken(hTokenReal ? hTokenReal : TokenHandle, Attributes, NumberOfAttributes, Buffer, Length, ReturnLength); + + if (hTokenReal) { + NtClose(hTokenReal); + } + return status; +} + +NTSTATUS Ldr_NtAccessCheckByType(PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, ACCESS_MASK DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, ULONG ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, PULONG PrivilegeSetLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) +{ + NTSTATUS rc; + HANDLE hTokenReal = NULL; + + if (Dll_ImageType == DLL_IMAGE_SANDBOXIE_BITS || + Dll_ImageType == DLL_IMAGE_SANDBOXIE_WUAU || + Dll_ImageType == DLL_IMAGE_WUAUCLT) { + *GrantedAccess = 0xFFFFFFFF; + *AccessStatus = TRUE; + SetLastError(0); + return TRUE; + } + + Ldr_TestToken(ClientToken, &hTokenReal); + + rc = __sys_NtAccessCheckByType(SecurityDescriptor, PrincipalSelfSid, hTokenReal ? hTokenReal : ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus); + + if (hTokenReal) { + NtClose(hTokenReal); + } + + return rc; +} + + +_FX NTSTATUS Ldr_NtAccessCheck(PSECURITY_DESCRIPTOR SecurityDescriptor, HANDLE ClientToken, ACCESS_MASK DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET RequiredPrivilegesBuffer, PULONG BufferLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) +{ + NTSTATUS status = 0; + HANDLE hTokenReal = NULL; + + Ldr_TestToken(ClientToken, &hTokenReal); + + status = __sys_NtAccessCheck(SecurityDescriptor, hTokenReal ? hTokenReal : ClientToken, DesiredAccess, GenericMapping, RequiredPrivilegesBuffer, BufferLength, GrantedAccess, AccessStatus); + + if (hTokenReal) { + NtClose(hTokenReal); + } + return status; +} + +_FX NTSTATUS Ldr_NtAccessCheckByTypeResultList(PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, ACCESS_MASK DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, ULONG ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, PULONG PrivilegeSetLength, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus) +{ + NTSTATUS status = 0; + HANDLE hTokenReal = NULL; + + Ldr_TestToken(ClientToken, &hTokenReal); + + status = __sys_NtAccessCheckByTypeResultList(SecurityDescriptor, PrincipalSelfSid, ClientToken, DesiredAccess, ObjectTypeList, ObjectTypeListLength, GenericMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess, AccessStatus); + + if (hTokenReal) { + NtClose(hTokenReal); + } + return status; +} + +BOOL Ldr_NtOpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle) +{ + BOOL rc; + + rc = __sys_NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle); + if (rc == STATUS_ACCESS_DENIED && OpenAsSelf) { + rc = __sys_NtOpenThreadToken(ThreadHandle, DesiredAccess, 0, TokenHandle); + } + return rc; +} + +BOOL Ldr_RtlEqualSid(void * sid1, void * sid2) +{ + if (!sid1 || !sid2) { + return FALSE; + } + return __sys_RtlEqualSid(sid1, sid2); +} + //--------------------------------------------------------------------------- // Secure_NtSetInformationToken diff --git a/Sandboxie/core/svc/serviceserver2.cpp b/Sandboxie/core/svc/serviceserver2.cpp index 9b31f70b..3feb4cd0 100644 --- a/Sandboxie/core/svc/serviceserver2.cpp +++ b/Sandboxie/core/svc/serviceserver2.cpp @@ -320,6 +320,7 @@ ULONG ServiceServer::RunHandler2( ULONG error; ULONG errlvl; BOOL ok = TRUE; + BOOL asSys; WCHAR boxname[48] = { 0 }; @@ -336,12 +337,27 @@ ULONG ServiceServer::RunHandler2( } } + asSys = RunServiceAsSystem(svcname, boxname); + if (ok) { errlvl = 0x22; - if (RunServiceAsSystem(svcname, boxname)) { + if (asSys) { // use our system token ok = OpenProcessToken(GetCurrentProcess(), TOKEN_RIGHTS, &hOldToken); } + // OriginalToken BEGIN + else if (SbieApi_QueryConfBool(boxname, L"NoSecurityIsolation", FALSE) || SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE)) { + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (ULONG)(ULONG_PTR)idProcess); + if (!hProcess) + ok = FALSE; + else + { + ok = OpenProcessToken(hProcess, TOKEN_RIGHTS, &hOldToken); + + CloseHandle(hProcess); + } + } + // OriginalToken END else { // use the callers original token hOldToken = (HANDLE)SbieApi_QueryProcessInfo(idProcess, 'ptok'); @@ -361,7 +377,7 @@ ULONG ServiceServer::RunHandler2( hNewToken, TokenSessionId, &idSession, sizeof(ULONG)); } - if (ok) { + if (ok && asSys) { // we don't need to adapt Dacl when we run this service as a regular user errlvl = 0x26; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (ULONG)(ULONG_PTR)idProcess); if (!hProcess) @@ -377,7 +393,7 @@ ULONG ServiceServer::RunHandler2( } } - if (ok && SbieApi_QueryConfBool(boxname, L"StripSystemPrivileges", TRUE)) { + if (ok && asSys && SbieApi_QueryConfBool(boxname, L"StripSystemPrivileges", TRUE)) { errlvl = 0x27; ok = ProcessServer::RunSandboxedStripPrivileges(hNewToken); } diff --git a/SandboxiePlus/SandMan/Resources/IconOff.png b/SandboxiePlus/SandMan/Resources/IconOff.png new file mode 100644 index 00000000..3d1ceefb Binary files /dev/null and b/SandboxiePlus/SandMan/Resources/IconOff.png differ diff --git a/SandboxiePlus/SandMan/Resources/SandMan.qrc b/SandboxiePlus/SandMan/Resources/SandMan.qrc index 334a942b..fe560030 100644 --- a/SandboxiePlus/SandMan/Resources/SandMan.qrc +++ b/SandboxiePlus/SandMan/Resources/SandMan.qrc @@ -52,6 +52,7 @@ IconFullD.png Actions/Ampel.png Actions/Compatibility.png + IconOff.png Boxes/sandbox-b-empty.png diff --git a/SandboxiePlus/SandMan/SandMan.cpp b/SandboxiePlus/SandMan/SandMan.cpp index d9806d9f..10528b67 100644 --- a/SandboxiePlus/SandMan/SandMan.cpp +++ b/SandboxiePlus/SandMan/SandMan.cpp @@ -182,16 +182,14 @@ CSandMan::CSandMan(QWidget *parent) m_BoxIcons[(EBoxColors)i] = qMakePair(QIcon(QString(":/Boxes/Empty%1").arg(i)), QIcon(QString(":/Boxes/Full%1").arg(i))); // Tray - QIcon Icon; - Icon.addFile(":/IconEmpty.png"); - m_pTrayIcon = new QSystemTrayIcon(Icon, this); + m_pTrayIcon = new QSystemTrayIcon(GetIcon("IconEmpty", false), this); m_pTrayIcon->setToolTip("Sandboxie-Plus"); connect(m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnSysTray(QSystemTrayIcon::ActivationReason))); m_bIconEmpty = true; m_bIconDisabled = false; m_pTrayMenu = new QMenu(); - QAction* pShowHide = m_pTrayMenu->addAction(QIcon(":/IconFull.png"), tr("Show/Hide"), this, SLOT(OnShowHide())); + QAction* pShowHide = m_pTrayMenu->addAction(GetIcon("IconFull", false), tr("Show/Hide"), this, SLOT(OnShowHide())); QFont f = pShowHide->font(); f.setBold(true); pShowHide->setFont(f); @@ -336,12 +334,12 @@ void CSandMan::StoreState() theConf->SetValue("MainWindow/LogTab", m_pLogTabs->currentIndex()); } -QIcon CSandMan::GetIcon(const QString& Name) +QIcon CSandMan::GetIcon(const QString& Name, bool bAction) { QString Path = QApplication::applicationDirPath() + "/Icons/" + Name + ".png"; if(QFile::exists(Path)) return QIcon(Path); - return QIcon(":/Actions/" + Name + ".png"); + return QIcon((bAction ? ":/Actions/" : ":/") + Name + ".png"); } void CSandMan::CreateMenus() @@ -423,7 +421,7 @@ void CSandMan::CreateMenus() m_pUpdate = m_pMenuHelp->addAction(tr("Check for Updates"), this, SLOT(CheckForUpdates())); m_pMenuHelp->addSeparator(); m_pAboutQt = m_pMenuHelp->addAction(tr("About the Qt Framework"), this, SLOT(OnAbout())); - m_pAbout = m_pMenuHelp->addAction(QIcon(":/IconFull.png"), tr("About Sandboxie-Plus"), this, SLOT(OnAbout())); + m_pAbout = m_pMenuHelp->addAction(GetIcon("IconFull", false), tr("About Sandboxie-Plus"), this, SLOT(OnAbout())); } void CSandMan::CreateToolBar() @@ -535,7 +533,7 @@ void CSandMan::closeEvent(QCloseEvent *e) QIcon CSandMan::GetBoxIcon(bool inUse, int boxType) { - EBoxColors color = eYelow; + EBoxColors color = eYellow; switch (boxType) { case CSandBoxPlus::eHardened: color = eOrang; break; //case CSandBoxPlus::eHasLogApi: color = eRed; break; @@ -649,6 +647,7 @@ void CSandMan::timerEvent(QTimerEvent* pEvent) return; bool bForceProcessDisabled = false; + bool bConnected = false; if (theAPI->IsConnected()) { @@ -666,24 +665,23 @@ void CSandMan::timerEvent(QTimerEvent* pEvent) if (!bIsMonitoring) // don't disable the view as logn as there are entries shown bIsMonitoring = !theAPI->GetTrace().isEmpty(); m_pTraceView->setEnabled(bIsMonitoring); - } - if (m_bIconEmpty != (theAPI->TotalProcesses() == 0) || m_bIconDisabled != bForceProcessDisabled) - { - m_bIconEmpty = (theAPI->TotalProcesses() == 0); - m_bIconDisabled = bForceProcessDisabled; - QString IconFile; - if (m_bIconEmpty) - IconFile += ":/IconEmpty"; - else - IconFile += ":/IconFull"; - if(m_bIconDisabled) - IconFile += "D"; + if (m_bIconEmpty != (theAPI->TotalProcesses() == 0) || m_bIconDisabled != bForceProcessDisabled) + { + m_bIconEmpty = (theAPI->TotalProcesses() == 0); + m_bIconDisabled = bForceProcessDisabled; - QIcon Icon; - Icon.addFile(IconFile + ".png"); - m_pTrayIcon->setIcon(Icon); + QString IconFile; + if (m_bIconEmpty) + IconFile = "IconEmpty"; + else + IconFile = "IconFull"; + if (m_bIconDisabled) + IconFile += "D"; + + m_pTrayIcon->setIcon(GetIcon(IconFile, false)); + } } if (!isVisible() || windowState().testFlag(Qt::WindowMinimized)) @@ -890,6 +888,9 @@ void CSandMan::OnStatusChanged() } this->setWindowTitle(appTitle); + m_pTrayIcon->setIcon(GetIcon(isConnected ? "IconEmpty" : "IconOff", false)); + m_bIconEmpty = true; + m_bIconDisabled = false; m_pNew->setEnabled(isConnected); m_pEmptyAll->setEnabled(isConnected); @@ -1664,7 +1665,7 @@ void CSandMan::OnSysTray(QSystemTrayIcon::ActivationReason Reason) m_pTrayBoxes->addTopLevelItem(pItem); } - pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBox->GetActiveProcessCount(), pBoxEx->GetType())); + pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBox->GetActiveProcessCount() != 0, pBoxEx->GetType())); } foreach(QTreeWidgetItem* pItem, OldBoxes) diff --git a/SandboxiePlus/SandMan/SandMan.h b/SandboxiePlus/SandMan/SandMan.h index a285cdee..f6584b4c 100644 --- a/SandboxiePlus/SandMan/SandMan.h +++ b/SandboxiePlus/SandMan/SandMan.h @@ -42,7 +42,7 @@ public: static QString FormatError(const SB_STATUS& Error); static void CheckResults(QList Results); - static QIcon GetIcon(const QString& Name); + static QIcon GetIcon(const QString& Name, bool bAction = true); bool IsFullyPortable(); @@ -83,7 +83,7 @@ protected: enum EBoxColors { - eYelow = 0, + eYellow = 0, eRed, eGreen, eBlue, diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp index 1cf6e2db..e4c5c0f5 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.cpp +++ b/SandboxiePlus/SandMan/Views/SbieView.cpp @@ -78,6 +78,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) m_pMenuRunAppWiz = m_pMenuRun->addAction(CSandMan::GetIcon("Software"), tr("Programs and Features"), this, SLOT(OnSandBoxAction())); m_pMenuRunCmd = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Terminal"), this, SLOT(OnSandBoxAction())); m_pMenuRunCmdAdmin = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Terminal (as Admin)"), this, SLOT(OnSandBoxAction())); + m_pMenuRunCmd32 = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Terminal (32-bit)"), this, SLOT(OnSandBoxAction())); m_pMenuRun->addSeparator(); m_iMenuRun = m_pMenuRun->actions().count(); m_pMenuEmptyBox = m_pMenu->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate All Programs"), this, SLOT(OnSandBoxAction())); @@ -574,6 +575,8 @@ void CSbieView::OnSandBoxAction(QAction* Action) Results.append(SandBoxes.first()->RunStart("cmd.exe")); else if (Action == m_pMenuRunCmdAdmin) Results.append(SandBoxes.first()->RunStart("cmd.exe", true)); + else if (Action == m_pMenuRunCmd32) + Results.append(SandBoxes.first()->RunStart("C:\\WINDOWS\\SysWOW64\\cmd.exe")); else if (Action == m_pMenuPresetsShowUAC) { SandBoxes.first()->SetBool("DropAdminRights", false); diff --git a/SandboxiePlus/SandMan/Views/SbieView.h b/SandboxiePlus/SandMan/Views/SbieView.h index 64db9c32..ce23a12b 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.h +++ b/SandboxiePlus/SandMan/Views/SbieView.h @@ -79,6 +79,7 @@ private: QAction* m_pMenuRunAppWiz; QAction* m_pMenuRunCmd; QAction* m_pMenuRunCmdAdmin; + QAction* m_pMenuRunCmd32; QAction* m_pMenuMkLink; QMenu* m_pMenuPresets; QActionGroup* m_pMenuPresetsAdmin; diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h index 85aca111..0e943221 100644 --- a/SandboxiePlus/version.h +++ b/SandboxiePlus/version.h @@ -2,8 +2,8 @@ #define VERSION_MJR 0 #define VERSION_MIN 9 -#define VERSION_REV 0 -#define VERSION_UPD 1 +#define VERSION_REV 1 +#define VERSION_UPD 0 #ifndef STR #define STR2(X) #X