diff --git a/CHANGELOG.md b/CHANGELOG.md index 0779a7c7..71cbcaf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - added experimental option "CreateToken=y" ability to create a new token instead of repurposing an existing one -- added option "DisableRtClsBlacklist=y" allowing to disable the hardcoded runtime class blacklist +- added option "DisableRTBlacklist=y" allowing to disable the hardcoded runtime class blacklist +- added new template "DeviceSecurity" template to lock down access to device drviers on the system +-- Note: This template requires RuleSpecificity being available to work properly +- added option to set a custom ini editor in the plus ui [#1475](https://github.com/sandboxie-plus/Sandboxie/issues/1475) ### Changed - reworked syscall invocation code in the driver diff --git a/Sandboxie/common/ntproto.h b/Sandboxie/common/ntproto.h index 38bd15b4..625c3af6 100644 --- a/Sandboxie/common/ntproto.h +++ b/Sandboxie/common/ntproto.h @@ -325,6 +325,30 @@ typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION } Attribute; } TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION; +// private +typedef enum _TOKEN_SECURITY_ATTRIBUTE_OPERATION +{ + TOKEN_SECURITY_ATTRIBUTE_OPERATION_NONE, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_REPLACE_ALL, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_ADD, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_DELETE, + TOKEN_SECURITY_ATTRIBUTE_OPERATION_REPLACE +} TOKEN_SECURITY_ATTRIBUTE_OPERATION, *PTOKEN_SECURITY_ATTRIBUTE_OPERATION; + +// private +typedef struct _TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION +{ + PTOKEN_SECURITY_ATTRIBUTES_INFORMATION Attributes; + PTOKEN_SECURITY_ATTRIBUTE_OPERATION Operations; +} TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION; + +// rev +typedef struct _TOKEN_PROCESS_TRUST_LEVEL +{ + PSID TrustLevelSid; +} TOKEN_PROCESS_TRUST_LEVEL, *PTOKEN_PROCESS_TRUST_LEVEL; + + typedef NTSTATUS (*P_NtCreateTokenEx)( _Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj b/Sandboxie/core/drv/SboxDrv.vcxproj index 2535f91b..baf13554 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj +++ b/Sandboxie/core/drv/SboxDrv.vcxproj @@ -31,6 +31,7 @@ Windows7 WDM false + 1 Driver @@ -39,6 +40,7 @@ Windows7 WDM false + 1 Driver @@ -49,6 +51,7 @@ WDM Windows7 false + 1 Driver @@ -57,6 +60,7 @@ Windows7 WDM false + 1 @@ -417,7 +421,12 @@ - + + false + false + false + false + true true diff --git a/Sandboxie/core/drv/syscall.c b/Sandboxie/core/drv/syscall.c index 2f190fe6..903719f7 100644 --- a/Sandboxie/core/drv/syscall.c +++ b/Sandboxie/core/drv/syscall.c @@ -108,6 +108,86 @@ static BOOLEAN Syscall_GetKernelAddr( #endif +//--------------------------------------------------------------------------- + + +typedef NTSTATUS (*P_SystemService00)(void); +typedef NTSTATUS (*P_SystemService01)( + ULONG_PTR arg01); +typedef NTSTATUS (*P_SystemService02)( + ULONG_PTR arg01, ULONG_PTR arg02); +typedef NTSTATUS (*P_SystemService03)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03); +typedef NTSTATUS (*P_SystemService04)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04); +typedef NTSTATUS (*P_SystemService05)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05); +typedef NTSTATUS (*P_SystemService06)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06); +typedef NTSTATUS (*P_SystemService07)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07); +typedef NTSTATUS (*P_SystemService08)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08); +typedef NTSTATUS (*P_SystemService09)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09); +typedef NTSTATUS (*P_SystemService10)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10); +typedef NTSTATUS (*P_SystemService11)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11); +typedef NTSTATUS (*P_SystemService12)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12); +typedef NTSTATUS (*P_SystemService13)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13); +typedef NTSTATUS (*P_SystemService14)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14); +typedef NTSTATUS (*P_SystemService15)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15); +typedef NTSTATUS (*P_SystemService16)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16); +typedef NTSTATUS (*P_SystemService17)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, + ULONG_PTR arg17); +typedef NTSTATUS (*P_SystemService18)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, + ULONG_PTR arg17, ULONG_PTR arg18); +typedef NTSTATUS (*P_SystemService19)( + ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04, + ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08, + ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12, + ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16, + ULONG_PTR arg17, ULONG_PTR arg18, ULONG_PTR arg19); +// (count & 0x0F) + 4 -> 19 is absolute maximum + //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- @@ -522,8 +602,6 @@ _FX void Syscall_ErrorForAsciiName(const UCHAR *name_a) //--------------------------------------------------------------------------- extern unsigned int g_TrapFrameOffset; -_FX NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args); - _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack) { NTSTATUS status; @@ -531,14 +609,146 @@ _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack) // // Note: when directly calling win32k functions with "Core Isolation" (HVCI) enabled // the nt!guard_dispatch_icall will cause a bugcheck! - // Hence we use a call proxy Sbie_InvokeSyscall_asm instead of a direct call + // Hence we it is required to disable "Control Flow Guard" for this file // __try { //DbgPrint("[syscall] request param count = %d\n", entry->param_count); - status = Sbie_InvokeSyscall_asm(entry->ntos_func, entry->param_count, stack); + if (entry->param_count == 0) { + + P_SystemService00 nt = (P_SystemService00)entry->ntos_func; + status = nt(); + + } else if (entry->param_count == 1) { + + P_SystemService01 nt = (P_SystemService01)entry->ntos_func; + status = nt(stack[0]); + + } else if (entry->param_count == 2) { + + P_SystemService02 nt = (P_SystemService02)entry->ntos_func; + status = nt(stack[0], stack[1]); + + } else if (entry->param_count == 3) { + + P_SystemService03 nt = (P_SystemService03)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2]); + + } else if (entry->param_count == 4) { + + P_SystemService04 nt = (P_SystemService04)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3]); + + } else if (entry->param_count == 5) { + + P_SystemService05 nt = (P_SystemService05)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4]); + + } else if (entry->param_count == 6) { + + P_SystemService06 nt = (P_SystemService06)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5]); + + } else if (entry->param_count == 7) { + + P_SystemService07 nt = (P_SystemService07)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6]); + + } else if (entry->param_count == 8) { + + P_SystemService08 nt = (P_SystemService08)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7]); + + } else if (entry->param_count == 9) { + + P_SystemService09 nt = (P_SystemService09)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8]); + + } else if (entry->param_count == 10) { + + P_SystemService10 nt = (P_SystemService10)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9]); + + } else if (entry->param_count == 11) { + + P_SystemService11 nt = (P_SystemService11)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10]); + + } else if (entry->param_count == 12) { + + P_SystemService12 nt = (P_SystemService12)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11]); + + } else if (entry->param_count == 13) { + + P_SystemService13 nt = (P_SystemService13)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12]); + + } else if (entry->param_count == 14) { + + P_SystemService14 nt = (P_SystemService14)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13]); + + } else if (entry->param_count == 15) { + + P_SystemService15 nt = (P_SystemService15)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13], + stack[14]); + + } else if (entry->param_count == 16) { + + P_SystemService16 nt = (P_SystemService16)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13], + stack[14], stack[15]); + + } else if (entry->param_count == 17) { + + P_SystemService17 nt = (P_SystemService17)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13], + stack[14], stack[15], stack[16]); + + } else if (entry->param_count == 18) { + + P_SystemService18 nt = (P_SystemService18)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13], + stack[14], stack[15], stack[16], stack[17]); + + } else if (entry->param_count == 19) { + + P_SystemService19 nt = (P_SystemService19)entry->ntos_func; + status = nt(stack[0], stack[1], stack[2], stack[3], stack[4], + stack[5], stack[6], stack[7], stack[8], stack[9], + stack[10], stack[11], stack[12], stack[13], + stack[14], stack[15], stack[16], stack[17], + stack[18]); + + } else { + + status = STATUS_INVALID_SYSTEM_SERVICE; + } } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); diff --git a/Sandboxie/core/drv/syscall_win32.c b/Sandboxie/core/drv/syscall_win32.c index 399b795b..df45f818 100644 --- a/Sandboxie/core/drv/syscall_win32.c +++ b/Sandboxie/core/drv/syscall_win32.c @@ -444,6 +444,36 @@ _FX BOOLEAN Syscall_Init_Table32(void) } +//--------------------------------------------------------------------------- +// Syscall_InvokeNew +//--------------------------------------------------------------------------- + +_FX NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args); + +_FX NTSTATUS Syscall_InvokeNew(SYSCALL_ENTRY *entry, ULONG_PTR *stack) +{ + NTSTATUS status; + + // + // Note: when directly calling win32k functions with "Core Isolation" (HVCI) enabled + // the nt!guard_dispatch_icall will cause a bugcheck! + // Hence we use a call proxy Sbie_InvokeSyscall_asm instead of a direct call + // + + __try { + + //DbgPrint("[syscall] request param count = %d\n", entry->param_count); + + status = Sbie_InvokeSyscall_asm(entry->ntos_func, entry->param_count, stack); + + } __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + + return status; +} + + //--------------------------------------------------------------------------- // Syscall_Api_Invoke32 //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/token.c b/Sandboxie/core/drv/token.c index d5c796db..5b537240 100644 --- a/Sandboxie/core/drv/token.c +++ b/Sandboxie/core/drv/token.c @@ -2411,6 +2411,45 @@ _FX void* Token_CreateNew(void* TokenObject, PROCESS* proc) ULONG virtualizationAllowed = 1; status = ZwSetInformationToken(TokenHandle, TokenVirtualizationAllowed, &virtualizationAllowed, sizeof(ULONG)); + + /*HANDLE OldTokenHandle; + status = ObOpenObjectByPointer( + TokenObject, OBJ_KERNEL_HANDLE, NULL, TOKEN_ALL_ACCESS, + *SeTokenObjectType, KernelMode, &OldTokenHandle); + if (NT_SUCCESS(status)) { + + __try { + + void* ptr = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, tzuk); + if (ptr) { + ULONG len = 0; + status = ZwQueryInformationToken(OldTokenHandle, TokenSecurityAttributes, ptr, PAGE_SIZE, &len); + if (NT_SUCCESS(status)) { + + PTOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION data = (PTOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION)(((UCHAR*)ptr) + len); + len += sizeof(TOKEN_SECURITY_ATTRIBUTES_AND_OPERATION_INFORMATION); + + data->Attributes = ptr; + data->Operations = (PTOKEN_SECURITY_ATTRIBUTE_OPERATION)(((UCHAR*)ptr) + len); + len += sizeof(TOKEN_SECURITY_ATTRIBUTE_OPERATION) * data->Attributes->AttributeCount; + for (ULONG i = 0; i < data->Attributes->AttributeCount; i++) + data->Operations[i] = TOKEN_SECURITY_ATTRIBUTE_OPERATION_ADD; + + status = ZwSetInformationToken(TokenHandle, TokenSecurityAttributes, data, len); + } + } + if (ptr)ExFreePool(ptr); + + + } __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode() + 0x01000000; + } + + DbgPrint("TokenSecurityAttributes %08x", status); + + ZwClose(OldTokenHandle); + }*/ + finish: if (LocalStatistics) ExFreePool((PVOID)LocalStatistics); if (LocalUser) ExFreePool((PVOID)LocalUser); diff --git a/Sandboxie/core/drv/util.c b/Sandboxie/core/drv/util.c index f109a05f..2e14b19e 100644 --- a/Sandboxie/core/drv/util.c +++ b/Sandboxie/core/drv/util.c @@ -351,8 +351,8 @@ _FX NTSTATUS MyValidateCertificate(void) Driver_Certified = NT_SUCCESS(status); - //if (status == STATUS_ACCOUNT_EXPIRED) - // status = STATUS_SUCCESS; + if (status == STATUS_ACCOUNT_EXPIRED) + status = STATUS_SUCCESS; return status; } diff --git a/Sandboxie/core/drv/verify.c b/Sandboxie/core/drv/verify.c index 9b95a4be..97ac7ab8 100644 --- a/Sandboxie/core/drv/verify.c +++ b/Sandboxie/core/drv/verify.c @@ -400,8 +400,90 @@ extern POOL *Driver_Pool; NTSTATUS Conf_Read_Line(STREAM *stream, WCHAR *line, int *linenum); +_FX VOID KphParseDate(const WCHAR* date_str, LARGE_INTEGER* date) +{ + TIME_FIELDS timeFiled = { 0 }; + const WCHAR* ptr = date_str; + const WCHAR* end = wcschr(ptr, L'.'); + if (end) { + //*end = L'\0'; + timeFiled.Day = (CSHORT)_wtoi(ptr); + //*end = L'.'; + ptr = end + 1; + + end = wcschr(ptr, L'.'); + if (end) { + //*end++ = L'\0'; + timeFiled.Month = (CSHORT)_wtoi(ptr); + //*end = L'.'; + ptr = end + 1; + + timeFiled.Year = (CSHORT)_wtoi(ptr); + + RtlTimeFieldsToTime(&timeFiled, date); + } + } +} + +// Example of __DATE__ string: "Jul 27 2012" +// 01234567890 + +#define BUILD_YEAR_CH0 (__DATE__[ 7]) +#define BUILD_YEAR_CH1 (__DATE__[ 8]) +#define BUILD_YEAR_CH2 (__DATE__[ 9]) +#define BUILD_YEAR_CH3 (__DATE__[10]) + +#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') + +#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +#define BUILD_DAY_CH1 (__DATE__[ 5]) + +_FX VOID KphGetBuildDate(LARGE_INTEGER* date) +{ + TIME_FIELDS timeFiled = { 0 }; + WCHAR DayW[3] = { BUILD_DAY_CH0, BUILD_DAY_CH1, L'\0' }; + timeFiled.Day = (CSHORT)_wtoi(DayW); + timeFiled.Month = ( + (BUILD_MONTH_IS_JAN) ? 1 : (BUILD_MONTH_IS_FEB) ? 2 : (BUILD_MONTH_IS_MAR) ? 3 : + (BUILD_MONTH_IS_APR) ? 4 : (BUILD_MONTH_IS_MAY) ? 5 : (BUILD_MONTH_IS_JUN) ? 6 : + (BUILD_MONTH_IS_JUL) ? 7 : (BUILD_MONTH_IS_AUG) ? 8 : (BUILD_MONTH_IS_SEP) ? 9 : + (BUILD_MONTH_IS_OCT) ? 10 : (BUILD_MONTH_IS_NOV) ? 11 : (BUILD_MONTH_IS_DEC) ? 12 + : 0); + WCHAR YearW[5] = { BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3, L'\0' }; + timeFiled.Year = (CSHORT)_wtoi(YearW); + + RtlTimeFieldsToTime(&timeFiled, date); +} + +_FX LONGLONG KphGetDateInterval(CSHORT days, CSHORT months, CSHORT years) +{ + LARGE_INTEGER date; + TIME_FIELDS timeFiled = { 0 }; + timeFiled.Day = days; + timeFiled.Month = months; + timeFiled.Year = years; + RtlTimeFieldsToTime(&timeFiled, &date); + return date.QuadPart; +} + + +#define SOFTWARE_NAME L"Sandboxie-Plus" + _FX NTSTATUS KphValidateCertificate(void) { + BOOLEAN CertDbg = TRUE; + static const WCHAR *path_cert = L"%s\\Certificate.dat"; NTSTATUS status; ULONG path_len = 0; @@ -419,6 +501,11 @@ _FX NTSTATUS KphValidateCertificate(void) char *temp = NULL; //1024 chars, utf8 encoded int line_num = 0; + WCHAR* type = NULL; + WCHAR* level = NULL; + //WCHAR* key = NULL; + LARGE_INTEGER cert_date = { 0 }; + if(!NT_SUCCESS(status = MyInitHash(&hashObj))) goto CleanupExit; @@ -500,27 +587,65 @@ _FX NTSTATUS KphValidateCertificate(void) } *ptr = L'\0'; - // - // hash the new tag - // - /*if (*value == '"') { value++; value[wcslen(value) - 1] = 0; }*/ - if (wcscmp(L"SIGNATURE", name) == 0 && signature == NULL) { + // + // Extract and decode the signature + // + + if (_wcsicmp(L"SIGNATURE", name) == 0 && signature == NULL) { signatureSize = b64_decoded_size(value); signature = Mem_Alloc(Driver_Pool, signatureSize); + if (!signature) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } b64_decode(value, signature, signatureSize); goto next; } + // + // Hash the tag + // + if (NT_SUCCESS(RtlUnicodeToUTF8N(temp, line_size, &temp_len, name, wcslen(name) * sizeof(wchar_t)))) MyHashData(&hashObj, temp, temp_len); if (NT_SUCCESS(RtlUnicodeToUTF8N(temp, line_size, &temp_len, value, wcslen(value) * sizeof(wchar_t)))) MyHashData(&hashObj, temp, temp_len); + + // + // Note: when parsing we may change the value of value, by adding \0's, hence we do all that after the hashing + // + + if (_wcsicmp(L"DATE", name) == 0 && cert_date.QuadPart == 0) { + // DD.MM.YYYY + KphParseDate(value, &cert_date); + } + else if (_wcsicmp(L"TYPE", name) == 0 && type == NULL) { + // TYPE-LEVEL + WCHAR* ptr = wcschr(value, L'-'); + if (ptr != NULL) { + *ptr++ = L'\0'; + if(level == NULL) level = Mem_AllocString(Driver_Pool, ptr); + } + type = Mem_AllocString(Driver_Pool, value); + } + else if (_wcsicmp(L"LEVEL", name) == 0 && level == NULL) { + level = Mem_AllocString(Driver_Pool, value); + } + //else if (_wcsicmp(L"UPDATEKEY", name) == 0 && key == NULL) { + // key = Mem_AllocString(Driver_Pool, value); + //} + else if (_wcsicmp(L"SOFTWARE", name) == 0) { // if software is specified it must be the right one + if (_wcsicmp(value, SOFTWARE_NAME) != 0) { + status = STATUS_OBJECT_TYPE_MISMATCH; + goto CleanupExit; + } + } next: status = Conf_Read_Line(stream, line, &line_num); @@ -538,22 +663,74 @@ _FX NTSTATUS KphValidateCertificate(void) } status = KphVerifySignature(hash, hashSize, signature, signatureSize); - DbgPrint("Sbie Cert status: %08x\n", status); + if (NT_SUCCESS(status)) { + + if(CertDbg) DbgPrint("Sbie Cert type: %S-%S\n", type, level); + + TIME_FIELDS timeFiled = { 0 }; + if (CertDbg) { + RtlTimeToTimeFields(&cert_date, &timeFiled); + DbgPrint("Sbie Cert date: %02d.%02d.%d\n", timeFiled.Day, timeFiled.Month, timeFiled.Year); + } + + LARGE_INTEGER BuildDate = { 0 }; + KphGetBuildDate(&BuildDate); + + if (CertDbg) { + RtlTimeToTimeFields(&BuildDate, &timeFiled); + if (CertDbg) DbgPrint("Sbie Build date: %02d.%02d.%d\n", timeFiled.Day, timeFiled.Month, timeFiled.Year); + } + + LARGE_INTEGER SystemTime; + LARGE_INTEGER LocalTime; + KeQuerySystemTime(&SystemTime); + ExSystemTimeToLocalTime(&SystemTime, &LocalTime); + if (CertDbg) { + RtlTimeToTimeFields(&LocalTime, &timeFiled); + DbgPrint("Sbie Current time: %02d:%02d:%02d %02d.%02d.%d\n" + , timeFiled.Hour, timeFiled.Minute, timeFiled.Second, timeFiled.Day, timeFiled.Month, timeFiled.Year); + } + + if (type && _wcsicmp(type, L"CONTRIBUTOR") == 0) { + // forever - nothing to check here + } + else if (type && _wcsicmp(type, L"PATREON") == 0) { + // todo: expire patrons which have left, use the update key + } + else if (type && _wcsicmp(type, L"BUSINESS") == 0) { + if (cert_date.QuadPart + KphGetDateInterval(0, 0, 1) < LocalTime.QuadPart) // valid for 1 year + status = STATUS_ACCOUNT_EXPIRED; + } + else /*if (!type || _wcsicmp(type, L"PERSONAL") == 0 || _wcsicmp(type, L"SUPPORTER") == 0) */ { + if (level && _wcsicmp(level, L"LARGE") == 0) { + // ok for now + } + else if (level && _wcsicmp(level, L"MEDIUM") == 0) { // valid for all builds released with 1 year + if (cert_date.QuadPart + KphGetDateInterval(0, 0, 1) < BuildDate.QuadPart) + status = STATUS_ACCOUNT_EXPIRED; + } + else /*if (!level || _wcsicmp(level, L"SMALL") == 0)*/ { // valid for 1 year + if (cert_date.QuadPart + KphGetDateInterval(0, 0, 1) < LocalTime.QuadPart) + status = STATUS_ACCOUNT_EXPIRED; + } + } + } CleanupExit: - if(path) - Mem_Free(path, path_len); - if(line) - Mem_Free(line, line_size); - if(temp) - Mem_Free(temp, line_size); + if(CertDbg) DbgPrint("Sbie Cert status: %08x\n", status); - MyFreeHash(&hashObj); - if(hash) - ExFreePoolWithTag(hash, 'vhpK'); - if(signature) - Mem_Free(signature, signatureSize); + if(path) Mem_Free(path, path_len); + if(line) Mem_Free(line, line_size); + if(temp) Mem_Free(temp, line_size); + + if (type) Mem_FreeString(type); + if (level) Mem_FreeString(level); + //if (key) Mem_FreeString(key); + + MyFreeHash(&hashObj); + if(hash) ExFreePoolWithTag(hash, 'vhpK'); + if(signature) Mem_Free(signature, signatureSize); return status; } diff --git a/Sandboxie/install/Templates.ini b/Sandboxie/install/Templates.ini index f2e854db..cb666772 100644 --- a/Sandboxie/install/Templates.ini +++ b/Sandboxie/install/Templates.ini @@ -3458,6 +3458,33 @@ RpcPortBindingIfId=SSDP,{4B112204-0E19-11D3-B42B-0000F81FEB9F} #RpcPortBindingSvc=SSDP,ssdpsrv +# +# Templates for Security Hardened boxes +# + +[Template_DeviceSecurity] +Tmpl.Title=Filter access to \Devices\ +Tmpl.Class=Misc +UseRuleSpecificity=y +ClosedFilePath=\Device\ +NormalFilePath=\Device\NamedPipe\ +NormalFilePath=\Device\Floppy*\ +NormalFilePath=\Device\CdRom*\ +NormalFilePath=\Device\HarddiskVolume*\ +NormalFilePath=\Device\Harddisk*\ +NormalFilePath=\Device\CNG +NormalFilePath=\Device\ConDrv\* +NormalFilePath=\Device\DeviceApi +NormalFilePath=\Device\DfsClient +NormalFilePath=\Device\KsecDD +NormalFilePath=\Device\MMCSS\MmThread +NormalFilePath=\Device\MountPointManager +NormalFilePath=\Device\Mup\ +NormalFilePath=\Device\Ndis +NormalFilePath=\Device\NDMP75 +NormalFilePath=\Device\PcwDrv +NormalFilePath=\Device\USBPDO-* + # diff --git a/SandboxiePlus/SandMan/SandMan.cpp b/SandboxiePlus/SandMan/SandMan.cpp index 623f3f49..60faab6a 100644 --- a/SandboxiePlus/SandMan/SandMan.cpp +++ b/SandboxiePlus/SandMan/SandMan.cpp @@ -1158,7 +1158,7 @@ void CSandMan::OnLogSbieMessage(quint32 MsgCode, const QStringList& MsgData, qui bool CSandMan::CheckCertificate() { - if (!g_Certificate.isEmpty()) + if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) != 0) return true; //if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { @@ -1678,6 +1678,7 @@ void CSandMan::OnEditIni() theConf->SetValue("Options/NoEditInfo", false); } + wstring Editor = theConf->GetString("Options/Editor", "notepad.exe").toStdWString(); wstring IniPath = theAPI->GetIniPath().toStdWString(); SHELLEXECUTEINFO si = { 0 }; @@ -1685,7 +1686,7 @@ void CSandMan::OnEditIni() si.fMask = SEE_MASK_NOCLOSEPROCESS; si.hwnd = NULL; si.lpVerb = L"runas"; - si.lpFile = L"notepad.exe"; + si.lpFile = Editor.c_str(); si.lpParameters = IniPath.c_str(); si.lpDirectory = NULL; si.nShow = SW_SHOW; @@ -2266,7 +2267,7 @@ void CSandMan::OnAbout() QString AboutCaption = tr( "

About Sandboxie-Plus

" "

Version %1

" - "

Copyright (c) 2020-2021 by DavidXanatos

" + "

Copyright (c) 2020-2022 by DavidXanatos

" ).arg(GetVersion()); QString CertInfo; diff --git a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp index 45eb1172..3963be2f 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp @@ -27,7 +27,7 @@ void COptionsWindow::CreateGeneral() ui.cmbBoxType->addItem(theGUI->GetBoxIcon(CSandBoxPlus::eAppBox), tr("Application Compartment (NO Isolation)"), (int)CSandBoxPlus::eAppBox); ui.lblSupportCert->setVisible(false); - if (g_Certificate.isEmpty()) + if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) { ui.lblSupportCert->setVisible(true); connect(ui.lblSupportCert, SIGNAL(linkActivated(const QString&)), theGUI, SLOT(OpenUrl(const QString&))); @@ -43,7 +43,6 @@ void COptionsWindow::CreateGeneral() } } - m_HoldBoxType = false; connect(ui.cmbBoxType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnBoxTypChanged())); @@ -403,6 +402,7 @@ void COptionsWindow::OnBoxTypChanged() //ui.chkRestrictServices->setChecked(true); ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eHardenedPlus); SetTemplate("NoUACProxy", false); + //SetTemplate("DeviceSecurity", true); break; case CSandBoxPlus::eDefaultPlus: case CSandBoxPlus::eDefault: @@ -413,6 +413,7 @@ void COptionsWindow::OnBoxTypChanged() //ui.chkRestrictServices->setChecked(true); ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eDefaultPlus); SetTemplate("NoUACProxy", false); + //SetTemplate("DeviceSecurity", false); break; case CSandBoxPlus::eAppBoxPlus: case CSandBoxPlus::eAppBox: @@ -420,6 +421,7 @@ void COptionsWindow::OnBoxTypChanged() //ui.chkRestrictServices->setChecked(false); ui.chkPrivacy->setChecked(BoxType == CSandBoxPlus::eAppBoxPlus); SetTemplate("NoUACProxy", true); + //SetTemplate("DeviceSecurity", false); break; }