diff --git a/CHANGELOG.md b/CHANGELOG.md
index 879ede99..1acc8db4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,7 +14,44 @@ This project adheres to [Semantic Versioning](http://semver.org/).
-## [0.7.2 / 5.49.0] - 2021-03-05
+
+
+
+## [0.7.3 / 5.49.5] - 2021-03-27
+
+### Added
+- added "UseSbieWndStation=y" to emulate CreateDesktop for selected processes, not only for firefox and chrome
+- added option to drop the console host process integrity use "DropConHostIntegrity=y"
+- added option to easily add local templates
+
+### Changed
+- reworked wnd hookign mechanism to improve performance
+-- resolves issues with file save dialogs taking 30+ sec to open
+-- this fix grately improves the win32 GUI proformance of sandboxes processes
+- reworked RPC resolver to be ini configurable
+-- the folowing options are now deprecated:
+--- "UseRpcMgmtSetComTimeout=some.dll,n", use "RpcPortBinding=some.dll,*,TimeOut=y"
+--- "OpenUPnP=y", "OpenBluetooth=y", "OpenSmartCard=n" use the new templates instead
+-- See the Templates.ini for usage examples
+
+### Fixed
+- fixed process specific hooks being applyed to all processes in a given sandbox
+- fixed issue with messages and templates sometimes not being properly displayed in the sandman ui
+- fixed issue with compatybility settings not being applyed properly
+- fixed auto delete issue that got introduced with 0.7.1
+- fixed issue with NtSetInformationFile, FileDispositionInformation resulting in opera instaler failing
+- fixed issue with mac type introduced in the 0.7.2 build
+- fixed global sandboxed windows hooks dont work when window rename is disabled
+- fixed issue saving local templates
+- fixed when using runas to start a process it was created outside fo the supervision of sandboxie
+-- since the runas facility is not accessible by default, this did not constitute a security issue
+-- to enable runas functionality add "OpenIpcPath=\RPC Control\SECLOGON" to your sandboxie ini
+-- please take note that doing so may open other yet unknown issus
+- fixed driver compatybility issue with windows 10 32 bit insider build 21337
+
+
+
+## [0.7.2 / 5.49.0] - 2021-03-04
### Added
- added option to alter reported Windows version "OverrideOsBuild=7601" for Windows 7 SP1
diff --git a/Sandboxie/apps/com/Crypto/crypto.c b/Sandboxie/apps/com/Crypto/crypto.c
index bc25fdbb..30804448 100644
--- a/Sandboxie/apps/com/Crypto/crypto.c
+++ b/Sandboxie/apps/com/Crypto/crypto.c
@@ -153,7 +153,7 @@ ALIGNED HANDLE my_CreateFileW(
// prevent SBIE1313, dont even try to access the block devcie for raw reading
//
- if (_wcsnicmp(lpFileName, L"\\\\.\\PhysicalDrive", 17) == 0 && wcschr(lpFileName + 17, L'\\') == NULL) {
+ if (wcsnicmp(lpFileName, L"\\\\.\\PhysicalDrive", 17) == 0 && wcschr(lpFileName + 17, L'\\') == NULL) {
if (dwDesiredAccess == GENERIC_READ)
dwDesiredAccess = 0;
}
@@ -168,7 +168,7 @@ ALIGNED HANDLE my_CreateFileW(
if (CatRoot) { // L"C:\\WINDOWS\\system32\\CatRoot2\\{00000000-0000-0000-0000-000000000000}\\catdb"
WCHAR win_dir[MAX_PATH + 64];
GetWindowsDirectory(win_dir, MAX_PATH);
- if (_wcsnicmp(win_dir, lpFileName, CatRoot - lpFileName) == 0) {
+ if (wcsnicmp(win_dir, lpFileName, CatRoot - lpFileName) == 0) {
if (dwDesiredAccess == GENERIC_READ)
dwDesiredAccess |= GENERIC_WRITE;
}
diff --git a/Sandboxie/apps/control/CreateDialog.cpp b/Sandboxie/apps/control/CreateDialog.cpp
index 41fc7322..e19a552b 100644
--- a/Sandboxie/apps/control/CreateDialog.cpp
+++ b/Sandboxie/apps/control/CreateDialog.cpp
@@ -176,22 +176,14 @@ void CCreateDialog::OnOK()
}
if (!errmsg && len <= 8) {
- static const WCHAR* deviceNames[] = {
- L"aux", L"clock$", L"con", L"nul", L"prn",
- L"com1", L"com2", L"com3", L"com4", L"com5",
- L"com6", L"com7", L"com8", L"com9",
- L"lpt1", L"lpt2", L"lpt3", L"lpt4", L"lpt5",
- L"lpt6", L"lpt7", L"lpt8", L"lpt9",
- NULL
- };
+ if(SbieDll_IsReservedFileName(name))
+ errmsg = MSG_3667;
+ }
- for (ULONG devNum = 0; deviceNames[devNum]; ++devNum) {
- const WCHAR* devName = deviceNames[devNum];
- ULONG devNameLen = wcslen(devName);
- if (_wcsnicmp(name, devName, devNameLen) == 0) {
- errmsg = MSG_3667;
- break;
- }
+ if (!errmsg) {
+ if (_wcsicmp(name, L"GlobalSettings") == 0
+ || _wcsnicmp(name, L"UserSettings_", 13) == 0) {
+ errmsg = MSG_3667;
}
}
diff --git a/Sandboxie/apps/start/delete.cpp b/Sandboxie/apps/start/delete.cpp
index bd41e449..bb0b7a8d 100644
--- a/Sandboxie/apps/start/delete.cpp
+++ b/Sandboxie/apps/start/delete.cpp
@@ -744,14 +744,6 @@ PATHELEM *AllocPathElem(HANDLE heap, const WCHAR *parent, const WCHAR *child)
void ProcessFiles(const WCHAR *BoxPath)
{
- static const WCHAR *deviceNames[] = {
- L"aux", L"clock$", L"con", L"nul", L"prn",
- L"com1", L"com2", L"com3", L"com4", L"com5",
- L"com6", L"com7", L"com8", L"com9",
- L"lpt1", L"lpt2", L"lpt3", L"lpt4", L"lpt5",
- L"lpt6", L"lpt7", L"lpt8", L"lpt9",
- NULL
- };
static const UCHAR valid_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789 ^&@{}[],$=!-#()%.+~_";
@@ -814,15 +806,8 @@ mainloop:
bool needRename = ((wcslen(elem->path) + name_len) > 220);
if ((! needRename) && (name_len <= 8)) {
- for (ULONG devNum = 0; deviceNames[devNum]; ++devNum) {
- const WCHAR *devName = deviceNames[devNum];
- ULONG devNameLen = wcslen(devName);
- if (_wcsnicmp(name, devName, devNameLen) == 0) {
- needRename = true;
- break;
- }
-
- }
+ if(SbieDll_IsReservedFileName(name))
+ needRename = true;
}
if (! needRename) {
diff --git a/Sandboxie/common/defines.h b/Sandboxie/common/defines.h
index 648c48cd..65a5161d 100644
--- a/Sandboxie/common/defines.h
+++ b/Sandboxie/common/defines.h
@@ -88,7 +88,7 @@
//#define wmemchr(mem,c, len) memchr((mem), (c), (len)*sizeof(WCHAR))
-#define SPOOLER_PORT_ID L"Spooler"
+#define SPOOLER_PORT_ID L"PrintSpooler"
#define WPAD_PORT_ID L"WPAD"
#define GAME_CONFIG_STORE_PORT_ID L"GamePort"
#define SMART_CARD_PORT_ID L"SmartCard"
diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h
index 15a15ab1..3e34eddc 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,49,0
-#define MY_VERSION_STRING "5.49.0"
+#define MY_VERSION_BINARY 5,49,5
+#define MY_VERSION_STRING "5.49.5"
#define MY_VERSION_COMPAT "5.49.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/win32_ntddk.h b/Sandboxie/common/win32_ntddk.h
index 8929d7e8..68429888 100644
--- a/Sandboxie/common/win32_ntddk.h
+++ b/Sandboxie/common/win32_ntddk.h
@@ -2382,6 +2382,19 @@ RtlNtStatusToDosError(NTSTATUS Status);
__declspec(dllimport) void __stdcall RtlRaiseStatus(NTSTATUS Status);
+__declspec(dllimport) PULONG __stdcall
+RtlSubAuthoritySid(
+ _In_ PSID Sid,
+ _In_ ULONG SubAuthority
+ );
+
+__declspec(dllimport) NTSTATUS __stdcall
+RtlInitializeSid(
+ _Out_ PSID Sid,
+ _In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
+ _In_ UCHAR SubAuthorityCount
+ );
+
//---------------------------------------------------------------------------
//__declspec(dllimport) USHORT RtlCaptureStackBackTrace(
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj
index 3d9ec800..60d95e00 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj
+++ b/Sandboxie/core/dll/SboxDll.vcxproj
@@ -99,6 +99,7 @@
ntdll.lib;uuid.lib;kernel32.lib
SboxDll32.def
+ 0x7D220000
DllMain
true
false
@@ -117,6 +118,7 @@
ntdll.lib;uuid.lib;kernel32.lib
+ 0x7D220000
DllMain
SboxDll64.def
true
@@ -138,6 +140,7 @@
ntdll.lib;uuid.lib;kernel32.lib
SboxDll32.def
+ 0x7D220000
DllMain
true
false
@@ -155,6 +158,7 @@
ntdll.lib;uuid.lib;kernel32.lib
+ 0x7D220000
DllMain
SboxDll64.def
true
diff --git a/Sandboxie/core/dll/config.c b/Sandboxie/core/dll/config.c
index 3d9f040d..93fada6b 100644
--- a/Sandboxie/core/dll/config.c
+++ b/Sandboxie/core/dll/config.c
@@ -250,6 +250,21 @@ _FX WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, UL
}
+//---------------------------------------------------------------------------
+// Config_String2Bool
+//---------------------------------------------------------------------------
+
+
+BOOLEAN Config_String2Bool(const WCHAR* value, BOOLEAN defval)
+{
+ if (*value == L'y' || *value == L'Y')
+ return TRUE;
+ if (*value == L'n' || *value == L'N')
+ return FALSE;
+ return defval;
+}
+
+
//---------------------------------------------------------------------------
// Config_GetSettingsForImageName_bool
//---------------------------------------------------------------------------
@@ -259,11 +274,7 @@ BOOLEAN Config_GetSettingsForImageName_bool(const WCHAR* setting, BOOLEAN defval
{
WCHAR value[16];
Config_GetSettingsForImageName(setting, value, sizeof(value), NULL);
- if (*value == L'y' || *value == L'Y')
- return TRUE;
- if (*value == L'n' || *value == L'N')
- return FALSE;
- return defval;
+ return Config_String2Bool(value, defval);
}
@@ -481,7 +492,37 @@ BOOLEAN SbieDll_MatchImage(const WCHAR* pat_str, const WCHAR* test_str, const WC
//---------------------------------------------------------------------------
-// CheckStringInList
+// SbieDll_GetStringForStringList
+//---------------------------------------------------------------------------
+
+
+SBIEDLL_EXPORT 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;
+ while (1) {
+ NTSTATUS status = SbieApi_QueryConfAsIs(boxname, setting, index, buf, 64 * sizeof(WCHAR));
+ ++index;
+ if (NT_SUCCESS(status)) {
+ WCHAR* ptr = wcschr(buf, L',');
+ if (ptr) *ptr = L'\0';
+ if (_wcsicmp(buf, string) == 0) {
+ if (ptr++)
+ wcscpy_s(value, value_size / sizeof(WCHAR), ptr);
+ else
+ *value = L'\0';
+ return TRUE;
+ }
+ }
+ else if (status != STATUS_BUFFER_TOO_SMALL)
+ break;
+ }
+ return FALSE;
+}
+
+
+//---------------------------------------------------------------------------
+// SbieDll_CheckStringInList
//---------------------------------------------------------------------------
@@ -505,35 +546,17 @@ BOOLEAN SbieDll_CheckStringInList(const WCHAR* string, const WCHAR* boxname, con
//---------------------------------------------------------------------------
-// CheckStringInList
+// SbieDll_GetBoolForStringFromList
//---------------------------------------------------------------------------
-SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found)
+/*SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found)
{
- WCHAR buf[128];
- ULONG index = 0;
- while (1) {
- NTSTATUS status = SbieApi_QueryConfAsIs(boxname, setting, index, buf, 64 * sizeof(WCHAR));
- ++index;
- if (NT_SUCCESS(status)) {
- WCHAR* ptr = wcschr(buf, L',');
- if (ptr) *ptr = L'\0';
- if (_wcsicmp(buf, string) == 0) {
- if (ptr++) {
- if (*ptr == L'y' || *ptr == L'Y')
- return TRUE;
- if (*ptr == L'n' || *ptr == L'N')
- return FALSE;
- }
- return def_found;
- }
- }
- else if (status != STATUS_BUFFER_TOO_SMALL)
- break;
- }
+ WCHAR buf[32];
+ if (SbieDll_GetStringForStringList(string, boxname, setting, buf, sizeof(buf)))
+ return Config_String2Bool(buf, def_found);
return not_found;
-}
+}*/
//---------------------------------------------------------------------------
diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h
index 87638f84..ab632a67 100644
--- a/Sandboxie/core/dll/dll.h
+++ b/Sandboxie/core/dll/dll.h
@@ -206,6 +206,8 @@ typedef struct _THREAD_DATA {
ULONG gui_create_window;
+ BOOLEAN gui_hooks_installed;
+
BOOL gui_should_suppress_msgbox;
//
@@ -763,6 +765,8 @@ BOOLEAN Config_InitPatternList(const WCHAR* setting, LIST* list);
NTSTATUS Config_GetSettingsForImageName(
const WCHAR* setting, WCHAR* value, ULONG value_size, const WCHAR* deftext);
+BOOLEAN Config_String2Bool(const WCHAR* value, BOOLEAN defval);
+
BOOLEAN Config_GetSettingsForImageName_bool(const WCHAR* setting, BOOLEAN defval);
WCHAR* Config_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep);
diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c
index fb072b7f..b31734ea 100644
--- a/Sandboxie/core/dll/file.c
+++ b/Sandboxie/core/dll/file.c
@@ -80,6 +80,9 @@
#define FGN_REPARSED_CLOSED_PATH 0x0200
#define FGN_REPARSED_WRITE_PATH 0x0400
+#define PATH_IS_BOXED(f) (((f) & FGN_IS_BOXED_PATH) != 0)
+#define PATH_NOT_BOXED(f) (((f) & FGN_IS_BOXED_PATH) == 0)
+
#ifndef _WIN64
#define WOW64_FS_REDIR
@@ -260,7 +263,7 @@ static NTSTATUS File_SetAttributes(
static NTSTATUS File_SetDisposition(
HANDLE FileHandle, IO_STATUS_BLOCK *IoStatusBlock,
- void *FileInformation, ULONG Length);
+ void *FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);
static NTSTATUS File_NtDeleteFile(OBJECT_ATTRIBUTES *ObjectAttributes);
@@ -2229,7 +2232,7 @@ _FX BOOLEAN File_FindSnapshotPath(WCHAR** CopyPath)
RtlInitUnicodeString(&objname, *CopyPath);
status = File_GetFileType(&objattrs, FALSE, &FileType, NULL);
if (!(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND))
- return TRUE; // file is present directly in copy path
+ return FALSE; // file is present directly in copy path
for (FILE_SNAPSHOT* Cur_Snapshot = File_Snapshot; Cur_Snapshot != NULL; Cur_Snapshot = Cur_Snapshot->Parent)
{
@@ -2246,7 +2249,7 @@ _FX BOOLEAN File_FindSnapshotPath(WCHAR** CopyPath)
}
}
- return FALSE;
+ return FALSE; // this file is not sandboxed
}
@@ -5532,7 +5535,7 @@ _FX NTSTATUS File_NtSetInformationFile(
status = STATUS_INFO_LENGTH_MISMATCH;
else
status = File_SetDisposition(
- FileHandle, IoStatusBlock, FileInformation, Length);
+ FileHandle, IoStatusBlock, FileInformation, Length, FileInformationClass);
//
// rename request
@@ -5813,7 +5816,7 @@ has_copy_path:
_FX NTSTATUS File_SetDisposition(
HANDLE FileHandle, IO_STATUS_BLOCK *IoStatusBlock,
- void *FileInformation, ULONG Length)
+ void *FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass)
{
ULONG LastError;
THREAD_DATA *TlsData = Dll_GetTlsData(&LastError);
@@ -5822,6 +5825,7 @@ _FX NTSTATUS File_SetDisposition(
WCHAR *DosPath;
NTSTATUS status;
ULONG mp_flags;
+ BOOLEAN is_direct_file;
//
// check if the specified path is an open or closed path
@@ -5831,6 +5835,7 @@ _FX NTSTATUS File_SetDisposition(
mp_flags = 0;
DosPath = NULL;
+ is_direct_file = FALSE;
Dll_PushTlsNameBuffer(TlsData);
@@ -5849,7 +5854,22 @@ _FX NTSTATUS File_SetDisposition(
if (PATH_IS_CLOSED(mp_flags))
status = STATUS_ACCESS_DENIED;
- else if (PATH_NOT_OPEN(mp_flags)) {
+ else if (PATH_IS_OPEN(mp_flags)) {
+
+ is_direct_file = TRUE; // file is open
+ }
+ else {
+
+ WCHAR* TmplPath = CopyPath;
+
+ File_FindSnapshotPath(&TmplPath); // if file is in a snapshot this updates TmplPath to point to it
+
+ if (PATH_IS_BOXED(FileFlags) && TmplPath == CopyPath)
+ is_direct_file = TRUE; // file is boxed and not located in a snapshot
+ }
+
+
+ if (!is_direct_file) {
status = File_DeleteDirectory(CopyPath, TRUE);
@@ -5889,11 +5909,11 @@ _FX NTSTATUS File_SetDisposition(
// handle the request appropriately
//
- if (PATH_IS_OPEN(mp_flags)) {
+ if (is_direct_file) {
status = __sys_NtSetInformationFile(
FileHandle, IoStatusBlock,
- FileInformation, Length, FileDispositionInformation);
+ FileInformation, Length, FileInformationClass); // FileDispositionInformation
} else if (NT_SUCCESS(status)) {
diff --git a/Sandboxie/core/dll/gui.c b/Sandboxie/core/dll/gui.c
index fabe1d81..12c8f468 100644
--- a/Sandboxie/core/dll/gui.c
+++ b/Sandboxie/core/dll/gui.c
@@ -248,7 +248,7 @@ static HWND Gui_CreateWindowExW(
LPVOID lpParam);
static BOOLEAN Gui_CanForwardMsg(
- HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam/*, LRESULT* plResult*/);
static LRESULT Gui_DefWindowProcA(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
@@ -559,7 +559,8 @@ _FX BOOLEAN Gui_Init2(void)
SBIEDLL_HOOK_GUI(ConsoleControl);
}
- if (Gui_RenameClasses) {
+ //if (Gui_RenameClasses) {
+ if (! Dll_SkipHook(L"createwin")) {
SBIEDLL_HOOK_GUI(CreateWindowExA);
SBIEDLL_HOOK_GUI(CreateWindowExW);
@@ -1238,17 +1239,7 @@ _FX HWND Gui_CreateWindowExW(
// note: the desktop window was made accessible in early v4 builds
// but this code is still here to handle any other parent windows
//
- /*//debug code
- _asm {
- nop
- nop
-//HERE1:
-// jmp HERE1
- //int 3
- nop
- nop
- }
-*/
+
if (Dll_ChromeSandbox) {
dwStyle |= WS_CHILD;
hWndParent = HWND_MESSAGE;
@@ -1267,7 +1258,10 @@ _FX HWND Gui_CreateWindowExW(
else
new_WindowName = lpWindowName;
- clsnm = Gui_CreateClassNameW(lpClassName);
+ if (! Gui_RenameClasses)
+ clsnm = lpClassName;
+ else
+ clsnm = Gui_CreateClassNameW(lpClassName);
if (hWndParent && (hWndParent != HWND_MESSAGE)
&& (! __sys_IsWindow(hWndParent))) {
@@ -1284,7 +1278,10 @@ _FX HWND Gui_CreateWindowExW(
++TlsData->gui_create_window;
if (TlsData->gui_create_window == 1) {
- Gui_ApplyWinHooks(0);
+ if (!TlsData->gui_hooks_installed) {
+ Gui_NotifyWinHooks();
+ TlsData->gui_hooks_installed = TRUE;
+ }
Taskbar_SetProcessAppUserModelId();
}
@@ -1369,7 +1366,10 @@ _FX HWND Gui_CreateWindowExA(
else
new_WindowName = lpWindowName;
- clsnm = Gui_CreateClassNameA(lpClassName);
+ if (! Gui_RenameClasses)
+ clsnm = lpClassName;
+ else
+ clsnm = Gui_CreateClassNameA(lpClassName);
if (hWndParent && (hWndParent != HWND_MESSAGE)
&& (! __sys_IsWindow(hWndParent))) {
@@ -1385,8 +1385,11 @@ _FX HWND Gui_CreateWindowExA(
++TlsData->gui_create_window;
if (TlsData->gui_create_window == 1) {
-
- Gui_ApplyWinHooks(0);
+
+ if (!TlsData->gui_hooks_installed) {
+ Gui_NotifyWinHooks();
+ TlsData->gui_hooks_installed = TRUE;
+ }
Taskbar_SetProcessAppUserModelId();
}
@@ -1440,16 +1443,10 @@ _FX HWND Gui_CreateWindowExA(
_FX BOOLEAN Gui_CanForwardMsg(
- HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam/*, LRESULT* plResult*/)
{
- if (uMsg == WM_NULL) {
-
- if (wParam == tzuk) {
- Gui_ApplyWinHooks(lParam);
- return FALSE;
- }
-
- } else if (uMsg == WM_DROPFILES) {
+ //*plResult = 0;
+ if (uMsg == WM_DROPFILES) {
if (Ole_DoDragDrop(hWnd, wParam, lParam))
return FALSE;
@@ -1486,8 +1483,8 @@ _FX LRESULT Gui_WindowProcW(
THREAD_DATA * TlsData = Dll_GetTlsData(NULL);
BOOLEAN bIgnore = FALSE;
- if (! Gui_CanForwardMsg(hWnd, uMsg, wParam, lParam))
- return 0;
+ if (! Gui_CanForwardMsg(hWnd, uMsg, wParam, lParam/*, &lResult*/))
+ return 0; //lResult;
if (uMsg == WM_DDE_INITIATE)
wParam = Gui_DDE_INITIATE_Received(hWnd, wParam);
@@ -1499,6 +1496,7 @@ _FX LRESULT Gui_WindowProcW(
wndproc = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom);
if (DLL_IMAGE_OFFICE_EXCEL == Dll_ImageType) {
+
if (WM_RENDERFORMAT == uMsg)
{
TlsData = Dll_GetTlsData(NULL);
@@ -1513,7 +1511,6 @@ _FX LRESULT Gui_WindowProcW(
if (!bIgnore)
{
lResult = __sys_CallWindowProcW(wndproc, hWnd, uMsg, wParam, new_lParam);
-
}
else
{
@@ -1542,8 +1539,8 @@ _FX LRESULT Gui_WindowProcA(
LRESULT lResult;
LPARAM new_lParam;
- if (! Gui_CanForwardMsg(hWnd, uMsg, wParam, lParam))
- return 0;
+ if (! Gui_CanForwardMsg(hWnd, uMsg, wParam, lParam/*, &lResult*/))
+ return 0; //lResult;
if (uMsg == WM_DDE_INITIATE)
wParam = Gui_DDE_INITIATE_Received(hWnd, wParam);
diff --git a/Sandboxie/core/dll/gui_p.h b/Sandboxie/core/dll/gui_p.h
index 0c6763c1..066b8d44 100644
--- a/Sandboxie/core/dll/gui_p.h
+++ b/Sandboxie/core/dll/gui_p.h
@@ -820,7 +820,9 @@ BOOLEAN Gui_InitMsg(void);
BOOLEAN Gui_InitWinHooks(void);
-LRESULT Gui_ApplyWinHooks(ULONG_PTR idThread);
+LRESULT Gui_RegisterWinHook(DWORD dwThreadId, ULONG64 ghk);
+
+LRESULT Gui_NotifyWinHooks(void);
//---------------------------------------------------------------------------
diff --git a/Sandboxie/core/dll/guienum.c b/Sandboxie/core/dll/guienum.c
index 1d4a58cc..503c22aa 100644
--- a/Sandboxie/core/dll/guienum.c
+++ b/Sandboxie/core/dll/guienum.c
@@ -236,7 +236,8 @@ _FX BOOLEAN Gui_InitEnum(void)
// raises an error when CreateDesktop is call. This hook
// is removed for chrome. See advapi.c: AdvApi_GetSecurityInfo
- if ((Dll_ImageType != DLL_IMAGE_GOOGLE_CHROME) &&
+ if (!Config_GetSettingsForImageName_bool(L"UseSbieWndStation", FALSE) &&
+ (Dll_ImageType != DLL_IMAGE_GOOGLE_CHROME) &&
(Dll_ImageType != DLL_IMAGE_MOZILLA_FIREFOX)) {
SBIEDLL_HOOK_GUI(CreateDesktopW);
SBIEDLL_HOOK_GUI(CreateDesktopA);
@@ -245,7 +246,8 @@ _FX BOOLEAN Gui_InitEnum(void)
SBIEDLL_HOOK_GUI(CreateWindowStationW);
SBIEDLL_HOOK_GUI(CreateWindowStationA);
}
-return TRUE;
+
+ return TRUE;
}
diff --git a/Sandboxie/core/dll/guihook.c b/Sandboxie/core/dll/guihook.c
index 4f9ee34d..334b35ed 100644
--- a/Sandboxie/core/dll/guihook.c
+++ b/Sandboxie/core/dll/guihook.c
@@ -24,6 +24,7 @@
#include "gui_p.h"
#include "core/drv/api_flags.h"
+#include "core/svc/GuiWire.h"
//---------------------------------------------------------------------------
@@ -85,8 +86,6 @@ static BOOLEAN Gui_HookThread(GUI_HOOK *ghk, ULONG_PTR idThread);
static BOOL Gui_UnhookWindowsHookEx(HHOOK hhk);
-static BOOL Gui_HookNotifyThreads(HWND hwnd, LPARAM lParam);
-
//---------------------------------------------------------------------------
// Variables
@@ -95,7 +94,8 @@ static BOOL Gui_HookNotifyThreads(HWND hwnd, LPARAM lParam);
static CRITICAL_SECTION Gui_HooksCritSec;
static LIST Gui_Hooks;
-
+static DWORD Gui_HookHelperThreadId = 0;
+static int Gui_HookCount = 0;
//---------------------------------------------------------------------------
// Gui_InitWinHooks
@@ -176,7 +176,9 @@ _FX HHOOK Gui_SetWindowsHookExA(
if ( idHook == WH_JOURNALRECORD || idHook == WH_JOURNALPLAYBACK ||
idHook == WH_KEYBOARD_LL || idHook == WH_MOUSE_LL ||
- Gui_IsThreadInThisProcess(dwThreadId)) {
+ //Gui_IsThreadInThisProcess(dwThreadId)
+ dwThreadId != 0 || hMod == NULL
+ ) {
//
// if this is a non-injecting hook, or if an injecting hook
@@ -225,11 +227,23 @@ _FX HHOOK Gui_SetWindowsHookExW(
// hooked to block hooks which would inject dlls outside the sandbox.
//
+ //
+ // the boxed "global" hook mechanism should only be used for global hooks
+ // using it for hooks that specify a thread ID like done in sbie 5.33.6
+ // and earlier results in a non standard conform behavioure:
+ // the hook in handled as a global one and injectted into all processes.
+ //
+ // so we let the system handle hooks on a specified thread or once without
+ // a dll module handle always as those are not global
+ //
+
HHOOK hhook;
if ( idHook == WH_JOURNALRECORD || idHook == WH_JOURNALPLAYBACK ||
idHook == WH_KEYBOARD_LL || idHook == WH_MOUSE_LL ||
- Gui_IsThreadInThisProcess(dwThreadId)) {
+ //Gui_IsThreadInThisProcess(dwThreadId)
+ dwThreadId != 0 || hMod == NULL
+ ) {
if (idHook == WH_MOUSE_LL && Dll_ImageType == DLL_IMAGE_WISPTIS) {
@@ -260,6 +274,52 @@ _FX HHOOK Gui_SetWindowsHookExW(
}
+//---------------------------------------------------------------------------
+// Gui_HookHelperProc
+//---------------------------------------------------------------------------
+
+
+ULONG CALLBACK Gui_HookHelperProc(LPVOID lpParam)
+{
+ //
+ // global hooks are turned into thread specific hooks and managed
+ // by the service worker for each session, see GuiServer::WndHookNotifySlave
+ //
+ // whenever a window is created the service gets notified and instructs
+ // the hooking pocess to hook the window's thread this is done using QueueUserAPC
+ // targeting this helper thread, whenever a APC is scheduled the thread
+ // will resume and execute it, it being Gui_NotifyWinHooksAPC
+ //
+
+ DWORD MyThreadId = Gui_HookHelperThreadId;
+ while (MyThreadId == Gui_HookHelperThreadId)
+ SleepEx(10, TRUE); // be in a waitable state for he APC's
+
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------
+// Gui_NotifyWinHooksAPC
+//---------------------------------------------------------------------------
+
+
+_FX VOID Gui_NotifyWinHooksAPC(ULONG_PTR idThread)
+{
+ GUI_HOOK *ghk;
+
+ EnterCriticalSection(&Gui_HooksCritSec);
+
+ ghk = List_Head(&Gui_Hooks);
+ while (ghk) {
+ Gui_HookThread(ghk, idThread);
+ ghk = List_Next(ghk);
+ }
+
+ LeaveCriticalSection(&Gui_HooksCritSec);
+}
+
+
//---------------------------------------------------------------------------
// Gui_SetWindowsHookEx
//---------------------------------------------------------------------------
@@ -313,13 +373,44 @@ _FX HHOOK Gui_SetWindowsHookEx(
EnterCriticalSection(&Gui_HooksCritSec);
List_Insert_After(&Gui_Hooks, NULL, ghk);
+ Gui_HookCount++;
+ if (Gui_HookHelperThreadId == 0) {
+ HANDLE HookHelperThread = CreateThread(NULL, 0, Gui_HookHelperProc, (LPVOID)0, CREATE_SUSPENDED, &Gui_HookHelperThreadId);
+ ResumeThread(HookHelperThread);
+ CloseHandle(HookHelperThread);
+ }
LeaveCriticalSection(&Gui_HooksCritSec);
+ Gui_RegisterWinHook(Gui_HookHelperThreadId, (ULONG64)ghk);
+
SetLastError(0);
return (HHOOK)ghk;
}
+//---------------------------------------------------------------------------
+// Gui_RegisterWinHook
+//---------------------------------------------------------------------------
+
+
+_FX LRESULT Gui_RegisterWinHook(DWORD dwThreadId, ULONG64 ghk)
+{
+ GUI_WND_HOOK_REGISTER_REQ req;
+ GUI_WND_HOOK_REGISTER_RPL* rpl;
+
+ req.msgid = GUI_WND_HOOK_REGISTER;
+ req.hthread = dwThreadId;
+ req.hproc = dwThreadId ? (ULONG64)&Gui_NotifyWinHooksAPC : 0ull;
+ req.hhook = ghk;
+
+ rpl = Gui_CallProxy(&req, sizeof(req), sizeof(*rpl));
+ if (rpl)
+ Dll_Free(rpl);
+
+ return 0;
+}
+
+
//---------------------------------------------------------------------------
// Gui_HookCollectThreads
//---------------------------------------------------------------------------
@@ -495,8 +586,13 @@ _FX BOOL Gui_UnhookWindowsHookEx(HHOOK hhk)
EnterCriticalSection(&Gui_HooksCritSec);
List_Remove(&Gui_Hooks, ghk);
+ Gui_HookCount--;
+ if (Gui_HookCount <= 0)
+ Gui_HookHelperThreadId = 0;
LeaveCriticalSection(&Gui_HooksCritSec);
+ Gui_RegisterWinHook(0, (ULONG64)ghk);
+
EnterCriticalSection(&ghk->crit);
while (1) {
@@ -516,68 +612,22 @@ _FX BOOL Gui_UnhookWindowsHookEx(HHOOK hhk)
//---------------------------------------------------------------------------
-// Gui_ApplyWinHooks
+// Gui_NotifyWinHooks
//---------------------------------------------------------------------------
-_FX LRESULT Gui_ApplyWinHooks(ULONG_PTR idThread)
+_FX LRESULT Gui_NotifyWinHooks()
{
- if (idThread) {
+ GUI_WND_HOOK_NOTIFY_REQ req;
+ GUI_WND_HOOK_NOTIFY_RPL *rpl;
- //
- // receive side
- //
-
- GUI_HOOK *ghk;
-
- EnterCriticalSection(&Gui_HooksCritSec);
-
- ghk = List_Head(&Gui_Hooks);
- while (ghk) {
- Gui_HookThread(ghk, idThread);
- ghk = List_Next(ghk);
- }
-
- LeaveCriticalSection(&Gui_HooksCritSec);
-
- } else {
-
- //
- // sending side
- //
-
- if (__sys_EnumWindows) {
- __sys_EnumWindows(
- Gui_HookNotifyThreads, (LPARAM)GetCurrentThreadId());
- } else
- Gui_EnumWindows(Gui_HookNotifyThreads, (LPARAM)GetCurrentThreadId());
- }
+ req.msgid = GUI_WND_HOOK_NOTIFY;
+ req.threadid = GetCurrentThreadId();
+
+ rpl = Gui_CallProxy(&req, sizeof(req), sizeof(*rpl));
+ if (rpl)
+ Dll_Free(rpl);
return 0;
}
-
-//---------------------------------------------------------------------------
-// Gui_HookNotifyThreads
-//---------------------------------------------------------------------------
-
-
-_FX BOOL Gui_HookNotifyThreads(HWND hwnd, LPARAM lParam)
-{
- LONG_PTR idProcess, idThread;
-
- if (Gui_IsSameBox(hwnd, &idProcess, &idThread)) {
-
- //
- // we don't post to ourselves because it isn't necessary
- // (any psuedo-global hooks set up by our own thread, would have
- // already hooked our own thread at the time of SetWindowsHook),
- // and also because it causes some programs to go into a loop
- //
-
- if (idThread != lParam)
- __sys_PostMessageW(hwnd, WM_NULL, tzuk, lParam);
- }
-
- return TRUE;
-}
diff --git a/Sandboxie/core/dll/proc.c b/Sandboxie/core/dll/proc.c
index 405a3d86..ec4e0eab 100644
--- a/Sandboxie/core/dll/proc.c
+++ b/Sandboxie/core/dll/proc.c
@@ -971,8 +971,8 @@ finish:
}
{
- WCHAR msg[512];
- Sbie_snwprintf(msg, 512, L"CreateProcess: %s (%s); err=%d", lpApplicationName ? lpApplicationName : L"[noName]", lpCommandLine ? lpCommandLine : L"[noCmd]", ok ? 0 : err);
+ WCHAR msg[1024];
+ Sbie_snwprintf(msg, 1024, L"CreateProcess: %s (%s); err=%d", lpApplicationName ? lpApplicationName : L"[noName]", lpCommandLine ? lpCommandLine : L"[noCmd]", ok ? 0 : err);
SbieApi_MonitorPut2(MONITOR_OTHER | MONITOR_TRACE, msg, FALSE);
}
@@ -1404,8 +1404,8 @@ finish:
}
{
- WCHAR msg[512];
- Sbie_snwprintf(msg, 512, L"CreateProcess: %s (%s); err=%d", lpApplicationName ? lpApplicationName : L"[noName]", lpCommandLine ? lpCommandLine : L"[noCmd]", ok ? 0 : err);
+ WCHAR msg[1024];
+ Sbie_snwprintf(msg, 1024, L"CreateProcess: %s (%s); err=%d", lpApplicationName ? lpApplicationName : L"[noName]", lpCommandLine ? lpCommandLine : L"[noCmd]", ok ? 0 : err);
SbieApi_MonitorPut2(MONITOR_OTHER | MONITOR_TRACE, msg, FALSE);
}
diff --git a/Sandboxie/core/dll/rpcrt.c b/Sandboxie/core/dll/rpcrt.c
index f76260da..bbde493b 100644
--- a/Sandboxie/core/dll/rpcrt.c
+++ b/Sandboxie/core/dll/rpcrt.c
@@ -387,7 +387,7 @@ BOOLEAN RpcRt_TestCallingModule(ULONG_PTR pRetAddr, ULONG_PTR hModule)
// RpcRt_FindModulePreset
//---------------------------------------------------------------------------
-/*
+
_FX NTSTATUS RpcRt_FindModulePreset(
const WCHAR* CallingModule, const WCHAR* Identifier, WCHAR* value, ULONG value_size)
{
@@ -428,8 +428,16 @@ _FX NTSTATUS RpcRt_FindModulePreset(
}
//test_value[test_len] = L'\0';
- if (!Config_MatchImage(test_value, test_len, Identifier, 1))
- continue;
+ if (*test_value == L'{') // is it a uuid?
+ {
+ if(_wcsnicmp(test_value + 1, Identifier, 36) != 0) // skip { and }
+ continue;
+ }
+ else if(*test_value && !(test_value[0] == L'*' && test_value[1] == L'\0')) // test only for non wildcards and non empty strings
+ {
+ if (!Config_MatchImage(test_value, test_len, Identifier, 1))
+ continue;
+ }
wcscpy_s(value, value_size / sizeof(WCHAR), found_value);
found_mode = mode;
@@ -438,7 +446,7 @@ _FX NTSTATUS RpcRt_FindModulePreset(
if (found_mode == -1)
return STATUS_NO_MORE_ENTRIES;
return STATUS_SUCCESS;
-}*/
+}
//---------------------------------------------------------------------------
@@ -602,11 +610,11 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW(
ULONG_PTR pRetAddr = TlsData->rpc_caller ? TlsData->rpc_caller : (ULONG_PTR)_ReturnAddress();
- WCHAR wstrPortName[DYNAMIC_PORT_NAME_CHARS];
+ WCHAR wstrPortName[MAX_PATH];
memset(wstrPortName, 0, sizeof(wstrPortName));
static const WCHAR* dynamicFalse = L"ncalrpc:[,Security=Impersonation Dynamic False]";
- static const WCHAR* dynamicTrue = L"ncalrpc:[,Security=Impersonation Dynamic True]";
+ //static const WCHAR* dynamicTrue = L"ncalrpc:[,Security=Impersonation Dynamic True]";
if (_wcsicmp(StringBinding, dynamicFalse) == 0) {
@@ -624,7 +632,7 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW(
wcscat(wstrPortName, dynamicFalse + 9);
}
}
- else if (_wcsicmp(StringBinding, L"ncalrpc:") == 0) {
+ /*else if (_wcsicmp(StringBinding, L"ncalrpc:") == 0) {
WCHAR pwszEmpty[] = L"";
WCHAR* pwszTempPortName = pwszEmpty;
@@ -666,7 +674,7 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW(
if (RpcRt_TestCallingModule(pRetAddr, pWINNSI)) {
use_RpcMgmtSetComTimeout = FALSE;
}
- }
+ }*/
else if (_wcsicmp(StringBinding, L"0497b57d-2e66-424f-a0c6-157cd5d41700@ncalrpc:") == 0) {
ULONG_PTR pkernel32 = (ULONG_PTR)GetModuleHandle(L"kernel32.dll");
@@ -683,7 +691,7 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW(
WCHAR* CallingModule = Trace_FindModuleByAddress((void*)pRetAddr);
if (CallingModule)
{
- /*WCHAR ModulePreset[256];
+ WCHAR ModulePreset[256];
if (NT_SUCCESS(RpcRt_FindModulePreset(CallingModule, StringBinding, ModulePreset, sizeof(ModulePreset)))) {
WCHAR tagValue[96];
@@ -694,22 +702,24 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW(
if (pwszTempPortName == NULL)
return RPC_S_ACCESS_DENIED;
- wcscpy(wstrPortName, L"ncalrpc:[");
- wcscpy(wstrPortName + 9, pwszTempPortName);
- wcscat(wstrPortName, L"]");
- //wcscat(wstrPortName, dynamicFalse + 9);
+ WCHAR* ptr = wcsstr(StringBinding, L":");
+ if(ptr)
+ {
+ size_t len = ptr - StringBinding;
+ wcsncpy(wstrPortName, StringBinding, len);
+ wcscat(wstrPortName, L":[");
+ wcscat(wstrPortName, pwszTempPortName);
+ if(ptr[1] == L'[')
+ wcscat(wstrPortName, ptr + 2);
+ else
+ wcscat(wstrPortName, L"]");
+ }
+ // else error let it fail
}
if (Config_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), NULL, L','))
- {
- if (*tagValue == L'y' || *tagValue == L'Y')
- use_RpcMgmtSetComTimeout = TRUE;
- else if (*tagValue == L'n' || *tagValue == L'N')
- use_RpcMgmtSetComTimeout = FALSE;
- }
- }*/
-
- use_RpcMgmtSetComTimeout = SbieDll_GetBoolForStringFromList(CallingModule, NULL, L"UseRpcMgmtSetComTimeout", TRUE, use_RpcMgmtSetComTimeout);
+ use_RpcMgmtSetComTimeout = Config_String2Bool(tagValue, use_RpcMgmtSetComTimeout);
+ }
}
@@ -792,7 +802,7 @@ _FX RPC_STATUS RpcRt_RpcBindingCreateW(
Template->StringEndpoint = (unsigned short*)L"samss lpc";
}
- else if ( (memcmp(&Template->ObjectUuid, &EMPTY_UUID, sizeof(GUID)) == 0) &&
+ /*else if ( (memcmp(&Template->ObjectUuid, &EMPTY_UUID, sizeof(GUID)) == 0) &&
RPC_PROTSEQ_LRPC == Template->ProtocolSequence &&
!Template->StringEndpoint)
{
@@ -817,38 +827,33 @@ _FX RPC_STATUS RpcRt_RpcBindingCreateW(
use_RpcMgmtSetComTimeout = TRUE;
}
}
- }
+ }*/
+
+ RPC_WSTR StringUuid;
+ __sys_UuidToStringW(&Template->ObjectUuid, &StringUuid);
WCHAR* CallingModule = Trace_FindModuleByAddress((void*)pRetAddr);
if (CallingModule)
{
- /*WCHAR ModulePreset[256];
+ WCHAR ModulePreset[256];
if (NT_SUCCESS(RpcRt_FindModulePreset(CallingModule, StringUuid, ModulePreset, sizeof(ModulePreset)))) {
WCHAR tagValue[96];
-
if (RPC_PROTSEQ_LRPC == Template->ProtocolSequence && !Template->StringEndpoint)
{
if (Config_FindTagValue(ModulePreset, L"Resolve", tagValue, sizeof(tagValue), NULL, L','))
{
Template->StringEndpoint = GetDynamicLpcPortName(tagValue);
}
- else if (Config_FindTagValue(ModulePreset, L"IpcPort", tagValue, sizeof(tagValue), NULL, L','))
+ /*else if (Config_FindTagValue(ModulePreset, L"IpcPort", tagValue, sizeof(tagValue), NULL, L','))
{
Template->StringEndpoint = (unsigned short*)...;
- }
+ }*/
}
if (Config_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), NULL, L','))
- {
- if (*tagValue == L'y' || *tagValue == L'Y')
- use_RpcMgmtSetComTimeout = TRUE;
- else if (*tagValue == L'n' || *tagValue == L'N')
- use_RpcMgmtSetComTimeout = FALSE;
- }
- }*/
-
- use_RpcMgmtSetComTimeout = SbieDll_GetBoolForStringFromList(CallingModule, NULL, L"UseRpcMgmtSetComTimeout", TRUE, use_RpcMgmtSetComTimeout);
+ use_RpcMgmtSetComTimeout = Config_String2Bool(tagValue, use_RpcMgmtSetComTimeout);
+ }
}
RPC_STATUS status;
@@ -859,20 +864,19 @@ _FX RPC_STATUS RpcRt_RpcBindingCreateW(
if (SbieApi_QueryConf(NULL, L"IpcTrace", 0, wsTraceOptions, sizeof(wsTraceOptions)) == STATUS_SUCCESS && wsTraceOptions[0] != L'\0')
{
WCHAR msg[512];
- RPC_WSTR StringUuid;
- __sys_UuidToStringW(&Template->ObjectUuid, &StringUuid);
//Sbie_snwprintf(msg, 512, L"SBIE p=%06d t=%06d RpcBindingCreateW Endpoint = '%s', UUID = %s, status = 0x%X\n", GetCurrentProcessId(), GetCurrentThreadId(),
Sbie_snwprintf(msg, 512, L"Endpoint = '%s', UUID = %s, status = 0x%08X, timeout = %d, caller = '%s'",
Template && Template->StringEndpoint ? Template->StringEndpoint : L"null",
StringUuid, status, use_RpcMgmtSetComTimeout,
CallingModule ? CallingModule : L"unknown");
- __sys_RpcStringFreeW(&StringUuid);
//OutputDebugString(msg);
SbieApi_MonitorPut2(MONITOR_IPC | MONITOR_TRACE, msg, FALSE);
}
+ __sys_RpcStringFreeW(&StringUuid);
+
if (use_RpcMgmtSetComTimeout) __sys_RpcMgmtSetComTimeout(*Binding, RPC_C_BINDING_TIMEOUT);
return status;
}
diff --git a/Sandboxie/core/dll/sbiedll.h b/Sandboxie/core/dll/sbiedll.h
index baf81dd0..feaf0bbc 100644
--- a/Sandboxie/core/dll/sbiedll.h
+++ b/Sandboxie/core/dll/sbiedll.h
@@ -202,14 +202,18 @@ SBIEDLL_EXPORT ULONG SbieDll_InjectLow(HANDLE hProcess, BOOLEAN is_wow64, BOOLE
SBIEDLL_EXPORT BOOLEAN SbieDll_MatchImage(const WCHAR* pat_str, const WCHAR* test_str, const WCHAR* BoxName);
+SBIEDLL_EXPORT BOOLEAN SbieDll_GetStringForStringList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, WCHAR* value, ULONG value_size);
SBIEDLL_EXPORT BOOLEAN SbieDll_CheckStringInList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting);
-SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found);
+//SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found);
SBIEDLL_EXPORT BOOLEAN SbieDll_GetBorderColor(const WCHAR* box_name, COLORREF* color, BOOL* title, int* width);
//---------------------------------------------------------------------------
+SBIEDLL_EXPORT BOOLEAN SbieDll_IsReservedFileName(const WCHAR* name);
+
+//---------------------------------------------------------------------------
#ifdef __cplusplus
}
diff --git a/Sandboxie/core/dll/support.c b/Sandboxie/core/dll/support.c
index b2f7729a..38a4574e 100644
--- a/Sandboxie/core/dll/support.c
+++ b/Sandboxie/core/dll/support.c
@@ -850,4 +850,31 @@ _FX WCHAR *SbieDll_FormatMessage2(
return SbieDll_FormatMessage(code, ins);
}
-#endif
\ No newline at end of file
+#endif
+
+//---------------------------------------------------------------------------
+// SbieDll_IsReservedFileName
+//---------------------------------------------------------------------------
+
+_FX BOOLEAN SbieDll_IsReservedFileName(const WCHAR *name)
+{
+ static const WCHAR* deviceNames[] = {
+ L"aux", L"clock$", L"con", L"nul", L"prn",
+ L"com1", L"com2", L"com3", L"com4", L"com5",
+ L"com6", L"com7", L"com8", L"com9",
+ L"lpt1", L"lpt2", L"lpt3", L"lpt4", L"lpt5",
+ L"lpt6", L"lpt7", L"lpt8", L"lpt9",
+ NULL
+ };
+
+ for (ULONG devNum = 0; deviceNames[devNum]; ++devNum) {
+ const WCHAR* devName = deviceNames[devNum];
+ //ULONG devNameLen = wcslen(devName);
+ //if (_wcsnicmp(name, devName, devNameLen) == 0) {
+ if (_wcsicmp(name, devName) == 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
\ No newline at end of file
diff --git a/Sandboxie/core/dll/userenv.c b/Sandboxie/core/dll/userenv.c
index d4b8aa64..4e79a966 100644
--- a/Sandboxie/core/dll/userenv.c
+++ b/Sandboxie/core/dll/userenv.c
@@ -81,7 +81,7 @@ _FX BOOLEAN UserEnv_InitVer(HMODULE module)
void* GetVersionExA;
WCHAR str[32];
- NTSTATUS status = Config_GetSettingsForImageName("OverrideOsBuild", str, sizeof(str), NULL);
+ NTSTATUS status = Config_GetSettingsForImageName(L"OverrideOsBuild", str, sizeof(str), NULL);
if (NT_SUCCESS(status))
UserEnv_dwBuildNumber = _wtoi(str);
diff --git a/Sandboxie/core/drv/process.c b/Sandboxie/core/drv/process.c
index 32e44933..34ae96b7 100644
--- a/Sandboxie/core/drv/process.c
+++ b/Sandboxie/core/drv/process.c
@@ -794,7 +794,9 @@ _FX void Process_NotifyProcess(
// hence we take for our purposes the ID of the process calling RtlCreateUserProcess instead
//
- Process_NotifyProcess_Create(ProcessId, PsGetCurrentProcessId(), NULL);
+ //DbgPrint("Process_NotifyProcess_Create pid=%d parent=%d current=%d\n", ProcessId, ParentId, PsGetCurrentProcessId());
+
+ Process_NotifyProcess_Create(ProcessId, ParentId, PsGetCurrentProcessId(), NULL);
} else {
@@ -810,7 +812,7 @@ _FX void Process_NotifyProcess(
_FX void Process_NotifyProcess_Create(
- HANDLE ProcessId, HANDLE ParentId, BOX *box)
+ HANDLE ProcessId, HANDLE ParentId, HANDLE CallerId, BOX *box)
{
void *nbuf1, *nbuf2;
ULONG nlen1, nlen2;
@@ -873,7 +875,34 @@ _FX void Process_NotifyProcess_Create(
BOOLEAN added_to_dfp_list = FALSE;
BOOLEAN check_forced_program = FALSE;
- PROCESS *parent_proc = Process_Find(ParentId, &irql);
+ //
+ // there are a couple of scenarios here
+ // a. CallerId == ParentId boring, all's fine
+ // b. Caller is sandboxed designated Parent is NOT sandboxed,
+ // possible sandbox escape atempt
+ // c. Caller is not sandboxed, designated Parent IS sandboxed,
+ // service trying to start something on the behalf of a sandboxed process
+ // eg. seclogon reacting to a runas request
+ // in which case the created process must be sandboxed to
+ //
+
+ PROCESS *parent_proc = Process_Find(CallerId, &irql);
+ if (!(parent_proc && !parent_proc->bHostInject) && CallerId != ParentId) {
+
+ //
+ // release lock on process list
+ //
+
+ ExReleaseResourceLite(Process_ListLock);
+ KeLowerIrql(irql);
+
+ //
+ // Process_Find will lock process list again
+ //
+
+ parent_proc = Process_Find(ParentId, &irql);
+ }
+
if (parent_proc && !parent_proc->bHostInject) {
//
diff --git a/Sandboxie/core/drv/process.h b/Sandboxie/core/drv/process.h
index f9abf00d..04c78811 100644
--- a/Sandboxie/core/drv/process.h
+++ b/Sandboxie/core/drv/process.h
@@ -199,7 +199,7 @@ PROCESS *Process_FindSandboxed(HANDLE ProcessId, KIRQL *out_irql);
// Start supervising a new process
void Process_NotifyProcess_Create(
- HANDLE ProcessId, HANDLE ParentId, BOX *box);
+ HANDLE ProcessId, HANDLE ParentId, HANDLE CallerId, BOX *box);
// Process_IsSameBox returns TRUE if the other process identified by
diff --git a/Sandboxie/core/drv/process_api.c b/Sandboxie/core/drv/process_api.c
index 13f7a4ed..8782ac7a 100644
--- a/Sandboxie/core/drv/process_api.c
+++ b/Sandboxie/core/drv/process_api.c
@@ -174,7 +174,7 @@ _FX NTSTATUS Process_Api_Start(PROCESS *proc, ULONG64 *parms)
} else {
Process_NotifyProcess_Create(
- user_pid_parm, Api_ServiceProcessId, box);
+ user_pid_parm, Api_ServiceProcessId, Api_ServiceProcessId, box);
box = NULL; // freed by Process_NotifyProcess_Create
}
diff --git a/Sandboxie/core/drv/syscall_32.c b/Sandboxie/core/drv/syscall_32.c
index ddeaab16..cdefb0a7 100644
--- a/Sandboxie/core/drv/syscall_32.c
+++ b/Sandboxie/core/drv/syscall_32.c
@@ -162,8 +162,20 @@ _FX void *Syscall_GetServiceTable(void)
if (ShadowTable)
return ShadowTable;
+ // Hard Offset Dependency
+
//Set flags2 offset
- if (Driver_OsVersion > DRIVER_WINDOWS_XP) {
+ if (Driver_OsBuild > 21286) { // 21H2
+
+ //
+ // on windows 21337 MSFT changed MmMapViewInSessionSpaceEx
+ // so lets go with a known good value from 21286
+ // Flags2_Offset=248 MitigationFlags_Offset=1168 SignatureLevel_Offset=932
+ //
+
+ Process_Flags2 = 0xF8;
+ }
+ else if (Driver_OsVersion > DRIVER_WINDOWS_XP) {
Process_Flags1 = Syscall_GetProcessFlagsOffset();
if (Process_Flags1 > 0x80 && Process_Flags1 < 0x500) {
Process_Flags2 = Process_Flags1 - 4;
diff --git a/Sandboxie/core/svc/EpMapperServer.cpp b/Sandboxie/core/svc/EpMapperServer.cpp
index aee7b0f7..12aa70d1 100644
--- a/Sandboxie/core/svc/EpMapperServer.cpp
+++ b/Sandboxie/core/svc/EpMapperServer.cpp
@@ -72,35 +72,36 @@ MSG_HEADER *EpMapperServer::EpmapperGetPortNameHandler(MSG_HEADER *msg)
return SHORT_REPLY(E_FAIL);
const WCHAR* wstrSpooler = L"Spooler";
- const WCHAR* wstrWPAD = L"WinHttpAutoProxySvc";
+ /*const WCHAR* wstrWPAD = L"WinHttpAutoProxySvc";
//const WCHAR* wstrBT = L"bthserv";
//const WCHAR* wstrSSDP = L"ssdpsrv";
RPC_IF_ID ifidGCS = { {0x88abcbc3, 0x34EA, 0x76AE, { 0x82, 0x15, 0x76, 0x75, 0x20, 0x65, 0x5A, 0x23 }}, 0, 0 }; // {88ABCBC3-34EA-76AE-8215-767520655A23}
RPC_IF_ID ifidSmartCard = { {0xC6B5235A, 0xE413, 0x481D, { 0x9A, 0xC8, 0x31, 0x68, 0x1B, 0x1F, 0xAA, 0xF5 }}, 1, 1 }; // {C6B5235A-E413-481D-9AC8-31681B1FAAF5}
RPC_IF_ID ifidBluetooth = { {0x2ACB9D68, 0xB434, 0x4B3E, { 0xB9, 0x66, 0xE0, 0x6B, 0x4B, 0x3A, 0x84, 0xCB }}, 1, 0 }; // {2ACB9D68-B434-4B3E-B966-E06B4B3A84CB}
- RPC_IF_ID ifidSSDP = { {0x4B112204, 0x0E19, 0x11D3, { 0xB4, 0x2B, 0x00, 0x00, 0xF8, 0x1F, 0xEB, 0x9F }}, 1, 0 }; // {4B112204-0E19-11D3-B42B-0000F81FEB9F}
+ RPC_IF_ID ifidSSDP = { {0x4B112204, 0x0E19, 0x11D3, { 0xB4, 0x2B, 0x00, 0x00, 0xF8, 0x1F, 0xEB, 0x9F }}, 1, 0 }; // {4B112204-0E19-11D3-B42B-0000F81FEB9F}*/
RPC_IF_ID ifidRequest;
- const WCHAR* pwszServiceName = NULL;
+ WCHAR pwszServiceName [81];
+ *pwszServiceName = 0;
if (_wcsicmp(req->wszPortId, SPOOLER_PORT_ID) == 0) {
if (SbieApi_QueryConfBool(boxname, L"ClosePrintSpooler", FALSE))
return SHORT_REPLY(E_ACCESSDENIED);
- pwszServiceName = wstrSpooler;
+ wcscpy_s(pwszServiceName, 81, wstrSpooler);
}
- else if (_wcsicmp(req->wszPortId, WPAD_PORT_ID) == 0) {
- pwszServiceName = wstrWPAD;
+ /*else if (_wcsicmp(req->wszPortId, WPAD_PORT_ID) == 0) {
+ wcscpy_s(pwszServiceName, 81, wstrWPAD);
}
else if (_wcsicmp(req->wszPortId, BT_PORT_ID) == 0) {
if (!SbieApi_QueryConfBool(boxname, L"OpenBluetooth", FALSE))
return SHORT_REPLY(E_ACCESSDENIED);
- //pwszServiceName = wstrBT;
+ //wcscpy_s(pwszServiceName, 81, wstrBT);
memcpy(&ifidRequest, &ifidBluetooth, sizeof(RPC_IF_ID));
}
else if (_wcsicmp(req->wszPortId, SSDP_PORT_ID) == 0) {
if (!SbieApi_QueryConfBool(boxname, L"OpenUPnP", FALSE))
return SHORT_REPLY(E_ACCESSDENIED);
- //pwszServiceName = wstrSSDP;
+ //wcscpy_s(pwszServiceName, 81, wstrSSDP);
memcpy(&ifidRequest, &ifidSSDP, sizeof(RPC_IF_ID));
}
else if (_wcsicmp(req->wszPortId, GAME_CONFIG_STORE_PORT_ID) == 0) {
@@ -112,7 +113,27 @@ MSG_HEADER *EpMapperServer::EpmapperGetPortNameHandler(MSG_HEADER *msg)
memcpy(&ifidRequest, &ifidSmartCard, sizeof(RPC_IF_ID));
}
else
- return SHORT_REPLY(E_INVALIDARG);
+ return SHORT_REPLY(E_INVALIDARG);*/
+ else
+ {
+ WCHAR buf[MAX_PATH];
+ if (SbieDll_GetStringForStringList(req->wszPortId, boxname, L"RpcPortBindingIfId", buf, sizeof(buf)))
+ {
+ unsigned short uuid[37];
+ wmemcpy((WCHAR*)uuid, buf + 1, 36); uuid[36] = 0;
+
+ ifidRequest.VersMajor = 0;
+ ifidRequest.VersMinor = 0;
+ if(UuidFromString(uuid, &ifidRequest.Uuid) != RPC_S_OK)
+ return SHORT_REPLY(E_INVALIDARG);
+ }
+ else if (SbieDll_GetStringForStringList(req->wszPortId, boxname, L"RpcPortBindingSvc", buf, sizeof(buf)))
+ {
+ wcscpy_s(pwszServiceName, 81, buf);
+ }
+ else
+ return SHORT_REPLY(E_INVALIDARG);
+ }
EPMAPPER_GET_PORT_NAME_RPL *rpl = (EPMAPPER_GET_PORT_NAME_RPL *)LONG_REPLY(sizeof(EPMAPPER_GET_PORT_NAME_RPL));
if (rpl == NULL)
@@ -121,7 +142,7 @@ MSG_HEADER *EpMapperServer::EpmapperGetPortNameHandler(MSG_HEADER *msg)
rpl->h.status = STATUS_NOT_FOUND;
rpl->wszPortName[0] = L'\0';
- if (pwszServiceName != NULL) {
+ if (*pwszServiceName) {
HANDLE hPid = NULL;
diff --git a/Sandboxie/core/svc/GuiServer.cpp b/Sandboxie/core/svc/GuiServer.cpp
index eea9af21..ab3ebcb0 100644
--- a/Sandboxie/core/svc/GuiServer.cpp
+++ b/Sandboxie/core/svc/GuiServer.cpp
@@ -65,6 +65,16 @@ typedef struct _GUI_SLAVE {
} GUI_SLAVE;
+typedef struct _WND_HOOK {
+
+ LIST_ELEM list_elem;
+ ULONG pid;
+ DWORD hthread;
+ ULONG64 hproc;
+ int HookCount;
+
+} WND_HOOK;
+
//---------------------------------------------------------------------------
// Variables
//---------------------------------------------------------------------------
@@ -89,6 +99,8 @@ GuiServer::GuiServer()
m_ParentPid = 0;
m_SessionId = 0;
+ List_Init(&m_WndHooks);
+
OSVERSIONINFOW osvi = { 0 };
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
/*NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOW);
@@ -531,8 +543,10 @@ void GuiServer::RunSlave(const WCHAR *cmdline)
//
PCWCH ConsoleCmdline = wcsstr(cmdline, L"_GuiProxy_Console,");
- if (ConsoleCmdline)
- RunConsoleSlave(ConsoleCmdline + 18);
+ if (ConsoleCmdline) {
+ RunConsoleSlave(ConsoleCmdline + 18); // this exits the process
+ return;
+ }
GuiServer *pThis = GetInstance();
@@ -749,6 +763,9 @@ bool GuiServer::CreateQueueSlave(const WCHAR *cmdline)
m_SlaveFuncs[GUI_SET_CURSOR_POS] = &GuiServer::SetCursorPosSlave;
m_SlaveFuncs[GUI_REMOVE_HOST_WINDOW] = &GuiServer::RemoveHostWindow;
m_SlaveFuncs[GUI_GET_RAW_INPUT_DEVICE_INFO] = &GuiServer::GetRawInputDeviceInfoSlave;
+ m_SlaveFuncs[GUI_WND_HOOK_NOTIFY] = &GuiServer::WndHookNotifySlave;
+ m_SlaveFuncs[GUI_WND_HOOK_REGISTER] = &GuiServer::WndHookRegisterSlave;
+
//
// register a worker thread to process incoming queue requests
@@ -1504,6 +1521,7 @@ ULONG GuiServer::CreateConsoleSlave(SlaveArgs *args)
if (! hProcess)
return STATUS_INVALID_CID;
+ WCHAR boxname[48];
WCHAR image_name[128];
WCHAR *cmdline = NULL;
HANDLE hToken1 = NULL;
@@ -1512,7 +1530,7 @@ ULONG GuiServer::CreateConsoleSlave(SlaveArgs *args)
BOOL ok;
ULONG session_id;
- ULONG status = SbieApi_QueryProcess((HANDLE)(ULONG_PTR)args->pid, NULL,
+ ULONG status = SbieApi_QueryProcess((HANDLE)(ULONG_PTR)args->pid, boxname,
image_name, NULL, &session_id);
if (status != 0 || session_id != m_SessionId) {
@@ -1556,7 +1574,7 @@ ULONG GuiServer::CreateConsoleSlave(SlaveArgs *args)
sa.bInheritHandle = FALSE;
WCHAR evtname[96];
- wsprintf(evtname, SANDBOXIE L"_ConsoleReadyEvent_%08X", GetTickCount());
+ wsprintf(evtname, SANDBOXIE L"_ConsoleReadyEvent_%08X:%s", GetTickCount(), boxname);
hEvent = CreateEvent(&sa, TRUE, FALSE, evtname);
if (! hEvent) {
status = STATUS_OBJECT_NAME_COLLISION;
@@ -3440,6 +3458,112 @@ ULONG GuiServer::GetRawInputDeviceInfoSlave(SlaveArgs *args)
}
+//---------------------------------------------------------------------------
+// WndHookNotifySlave
+//---------------------------------------------------------------------------
+
+ULONG GuiServer::WndHookNotifySlave(SlaveArgs *args)
+{
+ GUI_WND_HOOK_NOTIFY_REQ *req = (GUI_WND_HOOK_NOTIFY_REQ *)args->req_buf;
+ GUI_WND_HOOK_NOTIFY_RPL *rpl = (GUI_WND_HOOK_NOTIFY_RPL *)args->rpl_buf;
+
+ if (args->req_len != sizeof(GUI_WND_HOOK_NOTIFY_REQ))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ rpl->status = STATUS_UNSUCCESSFUL;
+
+ EnterCriticalSection(&m_SlavesLock);
+
+ WND_HOOK* whk = (WND_HOOK*)List_Head(&m_WndHooks);
+ while (whk) {
+
+ HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, (DWORD)whk->hthread);
+ if (hThread)
+ {
+ QueueUserAPC((PAPCFUNC)whk->hproc, hThread, (ULONG_PTR)req->threadid);
+
+ CloseHandle(hThread);
+
+ whk = (WND_HOOK*)List_Next(whk);
+ }
+ else // hook helper thread is no longer valid
+ {
+ WND_HOOK* old_whk = whk; // invalid entry
+
+ whk = (WND_HOOK*)List_Next(whk); // advance next
+
+ // remove invalid entries
+ List_Remove(&m_WndHooks, old_whk);
+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, old_whk);
+ }
+ }
+
+ LeaveCriticalSection(&m_SlavesLock);
+
+ rpl->status = STATUS_SUCCESS;
+
+ args->rpl_len = sizeof(GUI_WND_HOOK_NOTIFY_RPL);
+
+ return STATUS_SUCCESS;
+}
+
+
+//---------------------------------------------------------------------------
+// WndHookRegisterSlave
+//---------------------------------------------------------------------------
+
+ULONG GuiServer::WndHookRegisterSlave(SlaveArgs* args)
+{
+ GUI_WND_HOOK_REGISTER_REQ* req = (GUI_WND_HOOK_REGISTER_REQ*)args->req_buf;
+ GUI_WND_HOOK_REGISTER_RPL* rpl = (GUI_WND_HOOK_REGISTER_RPL*)args->rpl_buf;
+
+ if (args->req_len != sizeof(GUI_WND_HOOK_REGISTER_REQ))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ rpl->status = STATUS_UNSUCCESSFUL;
+
+ EnterCriticalSection(&m_SlavesLock);
+
+ WND_HOOK* whk = (WND_HOOK*)List_Head(&m_WndHooks);
+ while (whk) {
+ if (whk->pid == args->pid)
+ break;
+ whk = (WND_HOOK*)List_Next(whk);
+ }
+
+ if (req->hthread && req->hproc) // register
+ {
+ if (!whk) // add if not already added
+ {
+ whk = (WND_HOOK *)HeapAlloc(GetProcessHeap(), 0, sizeof(WND_HOOK));
+ whk->pid = args->pid;
+ whk->hthread = req->hthread;
+ whk->hproc = req->hproc;
+ whk->HookCount = 0;
+
+ List_Insert_After(&m_WndHooks, NULL, whk);
+ }
+ whk->HookCount++;
+ }
+ else if (whk) // unregister
+ {
+ whk->HookCount--;
+ if (whk->HookCount <= 0) { // remobe if this was the last hook
+ List_Remove(&m_WndHooks, whk);
+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, whk);
+ }
+ }
+
+ LeaveCriticalSection(&m_SlavesLock);
+
+ rpl->status = STATUS_SUCCESS;
+
+ args->rpl_len = sizeof(GUI_WND_HOOK_REGISTER_RPL);
+
+ return STATUS_SUCCESS;
+}
+
+
//---------------------------------------------------------------------------
// GetProcessPathList
//---------------------------------------------------------------------------
@@ -4005,6 +4129,44 @@ bool GuiServer::AllowSendPostMessage(
#undef ISWNDCLASS
#undef IS_INPUT_MESSAGE
+//---------------------------------------------------------------------------
+// GuiServer__DropConsoleIntegrity
+//---------------------------------------------------------------------------
+
+
+void GuiServer::DropConsoleIntegrity()
+{
+ ULONG_PTR consoleHostProcess;
+ if (!NT_SUCCESS(NtQueryInformationProcess(GetCurrentProcess(), ProcessConsoleHostProcess, &consoleHostProcess, sizeof(ULONG_PTR), NULL)))
+ return;
+
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)consoleHostProcess);
+ if (! hProcess)
+ return;
+
+ HANDLE tokenHandle;
+ if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &tokenHandle))
+ {
+ static SID_IDENTIFIER_AUTHORITY mandatoryLabelAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;
+
+ UCHAR newSidBuffer[FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)];
+ PSID newSid;
+ newSid = (PSID)newSidBuffer;
+ RtlInitializeSid(newSid, &mandatoryLabelAuthority, 1);
+ *RtlSubAuthoritySid(newSid, 0) = SECURITY_MANDATORY_UNTRUSTED_RID;
+
+ TOKEN_MANDATORY_LABEL mandatoryLabel;
+ mandatoryLabel.Label.Sid = newSid;
+ mandatoryLabel.Label.Attributes = SE_GROUP_INTEGRITY;
+
+ NtSetInformationToken(tokenHandle, (TOKEN_INFORMATION_CLASS)TokenIntegrityLevel, &mandatoryLabel, sizeof(TOKEN_MANDATORY_LABEL));
+
+ NtClose(tokenHandle);
+ }
+
+ CloseHandle(hProcess);
+}
+
//---------------------------------------------------------------------------
// RunConsoleSlave
@@ -4020,6 +4182,8 @@ void GuiServer::RunConsoleSlave(const WCHAR *evtname)
// to this console using the process id of the console helper
//
+ const WCHAR* boxname = wcsrchr(evtname, L':');
+
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, evtname);
const ULONG max_pids = 16000;
@@ -4030,6 +4194,9 @@ void GuiServer::RunConsoleSlave(const WCHAR *evtname)
if (AllocConsole()) {
+ if (boxname++ && SbieApi_QueryConfBool(boxname, L"DropConHostIntegrity", FALSE))
+ DropConsoleIntegrity();
+
AdjustConsoleTaskbarButton();
SetEvent(hEvent);
diff --git a/Sandboxie/core/svc/GuiServer.h b/Sandboxie/core/svc/GuiServer.h
index 577253e8..4541b58a 100644
--- a/Sandboxie/core/svc/GuiServer.h
+++ b/Sandboxie/core/svc/GuiServer.h
@@ -57,6 +57,8 @@ protected:
static void ConsoleCallbackSlave(void *arg, BOOLEAN timeout);
+ static void DropConsoleIntegrity();
+
static void AdjustConsoleTaskbarButton();
static ULONG DdeProxyThreadSlave(void *xDdeArgs);
@@ -159,6 +161,10 @@ protected:
ULONG GetRawInputDeviceInfoSlave(SlaveArgs* args);
+ ULONG WndHookNotifySlave(SlaveArgs* args);
+
+ ULONG WndHookRegisterSlave(SlaveArgs* args);
+
//
// window access check utilities
//
@@ -196,6 +202,7 @@ protected:
ULONG m_SessionId;
ULONG m_nOSVersion;
+ LIST m_WndHooks;
};
diff --git a/Sandboxie/core/svc/GuiWire.h b/Sandboxie/core/svc/GuiWire.h
index 7a83e7b9..3b6dc9b7 100644
--- a/Sandboxie/core/svc/GuiWire.h
+++ b/Sandboxie/core/svc/GuiWire.h
@@ -61,6 +61,8 @@ enum {
GUI_GET_CLIPBOARD_METAFILE,
GUI_REMOVE_HOST_WINDOW,
GUI_GET_RAW_INPUT_DEVICE_INFO,
+ GUI_WND_HOOK_NOTIFY,
+ GUI_WND_HOOK_REGISTER,
GUI_MAX_REQUEST_CODE
};
@@ -706,6 +708,48 @@ struct tagGUI_GET_RAW_INPUT_DEVICE_INFO_RPL
typedef struct tagGUI_GET_RAW_INPUT_DEVICE_INFO_REQ GUI_GET_RAW_INPUT_DEVICE_INFO_REQ;
typedef struct tagGUI_GET_RAW_INPUT_DEVICE_INFO_RPL GUI_GET_RAW_INPUT_DEVICE_INFO_RPL;
+
+//---------------------------------------------------------------------------
+// Notify the service of a window creation and set global hooks
+//---------------------------------------------------------------------------
+
+
+struct tagGUI_WND_HOOK_NOTIFY_REQ
+{
+ ULONG msgid;
+ DWORD threadid;
+};
+
+struct tagGUI_WND_HOOK_NOTIFY_RPL
+{
+ ULONG status;
+};
+
+typedef struct tagGUI_WND_HOOK_NOTIFY_REQ GUI_WND_HOOK_NOTIFY_REQ;
+typedef struct tagGUI_WND_HOOK_NOTIFY_RPL GUI_WND_HOOK_NOTIFY_RPL;
+
+
+//---------------------------------------------------------------------------
+// Register and unregister global hooks
+//---------------------------------------------------------------------------
+
+
+struct tagGUI_WND_HOOK_REGISTER_REQ
+{
+ ULONG msgid;
+ DWORD hthread;
+ ULONG64 hproc;
+ ULONG64 hhook;
+};
+
+struct tagGUI_WND_HOOK_REGISTER_RPL
+{
+ ULONG status;
+};
+
+typedef struct tagGUI_WND_HOOK_REGISTER_REQ GUI_WND_HOOK_REGISTER_REQ;
+typedef struct tagGUI_WND_HOOK_REGISTER_RPL GUI_WND_HOOK_REGISTER_RPL;
+
//---------------------------------------------------------------------------
diff --git a/Sandboxie/install/SandboxieVS.nsi b/Sandboxie/install/SandboxieVS.nsi
index 9fe1a196..282bd3b6 100644
--- a/Sandboxie/install/SandboxieVS.nsi
+++ b/Sandboxie/install/SandboxieVS.nsi
@@ -98,6 +98,7 @@ VIAddVersionKey "CompanyName" "${COMPANY_NAME}"
VIAddVersionKey "LegalCopyright" "${COPYRIGHT_STRING}"
VIAddVersionKey "FileDescription" "${PRODUCT_NAME} Installer"
VIAddVersionKey "FileVersion" "${VERSION}"
+VIAddVersionKey "ProductVersion" "${VERSION}"
;----------------------------------------------------------------------------
; Pages
diff --git a/Sandboxie/install/Templates.ini b/Sandboxie/install/Templates.ini
index 1829c066..db8042ee 100644
--- a/Sandboxie/install/Templates.ini
+++ b/Sandboxie/install/Templates.ini
@@ -2824,6 +2824,12 @@ OpenIpcPath=\RPC Control\nvdaHelperRemote_*
OpenIpcPath=*\BaseNamedObjects*\Serotek-*
OpenWinClass=*
+# [Template_PlugPlayService]
+# Tmpl.Title=#3938
+# Tmpl.Class=Misc
+# OpenIpcPath=\RPC Control\plugplay
+# OpenIpcPath=\RPC Control\ntsvcs
+
[Template_TaskbarJumpList]
Tmpl.Title=#4294
Tmpl.Class=Misc
@@ -2943,6 +2949,65 @@ CopyAlways=*\cbs.log
# internet explorer 10 web cache
CopyAlways=*\webcachev*.dat
+[Template_RpcPortBindings]
+Tmpl.Title=Default RPC Port Bindings
+Tmpl.Class=Misc
+Tmpl.Scan=s
+Tmpl.ScanService=RpcSs
+#Tmpl.ScanService=RpcEptMapper
+#Tmpl.ScanService=DcomLaunch
+
+# hardcoded options:
+#RpcPortBinding=kernel32.dll,'0497b57d-2e66-424f-a0c6-157cd5d41700@ncalrpc:',TimeOut=y
+#RpcPortBinding=*,{906B0CE0-C70B-1067-B317-00DD010662DA},IpcPort="samss lpc"
+#RpcPortBinding=winspool.drv,'ncalrpc:[,Security=Impersonation Dynamic False]',Resolve=PrintSpooler
+#RpcPortBindingSvc=Spooler,PrintSpooler
+
+# RpcMgmtSetComTimeout presets
+RpcPortBinding=WINNSI.DLL,'ncalrpc:[,Security=Impersonation Dynamic True]',TimeOut=n
+RpcPortBinding=AppXDeploymentClient.dll,{00000000-0000-0000-0000-000000000000},TimeOut=y
+
+# windows proxy auto discovery
+#Tmpl.ScanService=WinHttpAutoProxySvc
+RpcPortBinding=WinHttp.dll,'ncalrpc:',Resolve=WPAD,TimeOut=y
+RpcPortBindingSvc=WPAD,WinHttpAutoProxySvc
+
+# windows 10 game port
+#Tmpl.ScanService=???
+RpcPortBinding=resourcepolicyclient.dll,{00000000-0000-0000-0000-000000000000},Resolve=GamePort
+RpcPortBindingIfId=GamePort,{88ABCBC3-34EA-76AE-8215-767520655A23}
+
+
+#
+# Optional RPC Port Config
+#
+
+[Template_OpenBluetooth]
+Tmpl.Title=Open Bluetooth RPC port
+Tmpl.Class=Misc
+#bluetooth
+RpcPortBinding=BluetoothApis.dll,'ncalrpc:',Resolve=Bluetooth,TimeOut=y
+RpcPortBindingIfId=Bluetooth,{2ACB9D68-B434-4B3E-B966-E06B4B3A84CB}
+#RpcPortBindingSvc=Bluetooth,bthserv
+
+[Template_OpenSmartCard]
+Tmpl.Title=Open Cmart Card RPC port
+Tmpl.Class=Misc
+#smartcard
+RpcPortBinding=WinSCard.dll,{00000000-0000-0000-0000-000000000000},Resolve=SmartCard
+RpcPortBindingIfId=SmartCard,{C6B5235A-E413-481D-9AC8-31681B1FAAF5}
+
+[Template_SSDP]
+Tmpl.Title=Open Simple Service Discovery Protocol (SSDP, UPnP) RPC port
+Tmpl.Class=Misc
+#upnp
+#Tmpl.ScanService=ssdpsrv
+RpcPortBinding=SSDPAPI.dll,'ncalrpc:',Resolve=SSDP
+RpcPortBindingIfId=SSDP,{4B112204-0E19-11D3-B42B-0000F81FEB9F}
+#RpcPortBindingSvc=SSDP,ssdpsrv
+
+
+
#
# Known Conflicts
@@ -3035,9 +3100,3 @@ CopyAlways=*\infcache.1
CopyAlways=*\cbs.log
# internet explorer 10 web cache
CopyAlways=*\webcachev*.dat
-
-# [Template_PlugPlayService]
-# Tmpl.Title=#3938
-# Tmpl.Class=Misc
-# OpenIpcPath=\RPC Control\plugplay
-# OpenIpcPath=\RPC Control\ntsvcs
diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp
index 1218f20f..cc90627c 100644
--- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp
+++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp
@@ -1052,6 +1052,11 @@ SB_STATUS CSbieAPI::ValidateName(const QString& BoxName)
if (DeviceNames.contains(BoxName, Qt::CaseInsensitive))
return SB_ERR(SB_BadNameDev);
+ if(BoxName.compare("GlobalSettings", Qt::CaseInsensitive) == 0)
+ return SB_ERR(SB_BadNameDev);
+ if(BoxName.left(13).compare("UserSettings_", Qt::CaseInsensitive) == 0)
+ return SB_ERR(SB_BadNameDev);
+
if (BoxName.contains(QRegExp("[^A-Za-z0-9_]")))
return SB_ERR(SB_BadNameChar);
@@ -1145,8 +1150,8 @@ SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, const CSandBoxPtr& pBox)
}
}
- bool WasBoxClosed = pBox->m_ActiveProcessCount > 0 && boxed_pids[0] == 0;
- pBox->m_ActiveProcessCount = boxed_pids[0];
+ bool WasBoxClosed = pBox->m_ActiveProcessCount > 0 && count == 0;
+ pBox->m_ActiveProcessCount = count;
if (WasBoxClosed) {
pBox->CloseBox();
emit BoxClosed(pBox->GetName());
@@ -1969,7 +1974,8 @@ QString CSbieAPI::GetSbieMsgStr(quint32 code, quint32 Lang)
{
ULONG FormatFlags = FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER;
WCHAR* ret_str = NULL;
- if (!m->SbieMsgDll || FormatMessage(FormatFlags, m->SbieMsgDll, code, Lang, (LPWSTR)&ret_str, 4, NULL) == 0)
+ if (!m->SbieMsgDll || (FormatMessage(FormatFlags, m->SbieMsgDll, code, Lang, (LPWSTR)&ret_str, 4, NULL) == 0
+ && FormatMessage(FormatFlags, m->SbieMsgDll, code, 1033, (LPWSTR)&ret_str, 4, NULL) == 0))
return QString("SBIE%0: %1; %2").arg(code, 4, 10);
QString qStr = QString::fromWCharArray(ret_str);
LocalFree(ret_str);
diff --git a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
index 3790f4fc..ed86d825 100644
--- a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
+++ b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
@@ -45,7 +45,7 @@
QTabWidget::West
- 0
+ 9
@@ -55,7 +55,7 @@
-
- 0
+ 2
@@ -433,62 +433,7 @@
- -
-
-
-
- 0
- 0
-
-
-
- Allow the print spooler to print to files outside the sandbox
-
-
-
- -
-
-
-
- 20
- 0
-
-
-
-
- 20
- 16777215
-
-
-
-
-
-
-
- -
-
-
- Block access to the printer spooler
-
-
-
- -
-
-
-
- 75
- true
-
-
-
- Protect the system from sandboxed processes
-
-
- Other restrictions
-
-
-
- -
+
-
Qt::Vertical
@@ -517,7 +462,41 @@
- -
+
-
+
+
+ Open Windows Credentials Store
+
+
+
+ -
+
+
+ Open System Protected Storage
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Allow the print spooler to print to files outside the sandbox
+
+
+
+ -
+
+
+ Block access to the printer spooler
+
+
+
+ -
Qt::Horizontal
@@ -530,31 +509,38 @@
- -
-
+
-
+
+
+
+ 20
+ 0
+
+
+
+
+ 20
+ 16777215
+
+
- Open System Protected Storage
+
- -
-
-
- Open Windows Credentials Store
+
-
+
+
+
+ 75
+ true
+
-
-
- -
-
-
- Allow access to Bluetooth
+
+ Protect the system from sandboxed processes
-
-
- -
-
- Allow access to Smart Cards
+ Other restrictions
@@ -2047,9 +2033,6 @@ instead of "*".
-
-
-
-
-
-
@@ -2060,6 +2043,9 @@ instead of "*".
+ -
+
+
-
@@ -2067,10 +2053,47 @@ instead of "*".
+ -
+
+
+ Add Template
+
+
+
+ -
+
+
+ This list contains a large amount of sandbox compatibility enhancing templates
+
+
+ true
+
+
+
-
- -
+
-
+
+
+ Remove Template
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
true
@@ -2087,16 +2110,6 @@ instead of "*".
- -
-
-
- This list contains a large amount of sandbox compatibility enhancing templates
-
-
- true
-
-
-
diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
index 6de0fca1..cb77421b 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
@@ -164,8 +164,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
connect(ui.chkOpenCredentials, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.chkOpenProtectedStorage, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
- connect(ui.chkOpenSmartCard, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
- connect(ui.chkOpenBluetooth, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ //connect(ui.chkOpenSmartCard, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ //connect(ui.chkOpenBluetooth, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.txtCopyLimit, SIGNAL(textChanged(const QString&)), this, SLOT(OnGeneralChanged()));
connect(ui.chkCopyLimit, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
@@ -304,6 +304,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
connect(ui.txtTemplates, SIGNAL(textChanged(const QString&)), this, SLOT(OnFilterTemplates()));
connect(ui.treeTemplates, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnTemplateClicked(QTreeWidgetItem*, int)));
connect(ui.treeTemplates, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnTemplateDoubleClicked(QTreeWidgetItem*, int)));
+ connect(ui.btnAddTemplate, SIGNAL(clicked(bool)), this, SLOT(OnAddTemplates()));
+ connect(ui.btnDelTemplate, SIGNAL(clicked(bool)), this, SLOT(OnDelTemplates()));
//
connect(ui.tabs, SIGNAL(currentChanged(int)), this, SLOT(OnTab()));
@@ -444,8 +446,8 @@ void COptionsWindow::LoadConfig()
ui.chkOpenProtectedStorage->setChecked(m_pBox->GetBool("OpenProtectedStorage", false));
ui.chkOpenCredentials->setEnabled(!ui.chkOpenProtectedStorage->isChecked());
ui.chkOpenCredentials->setChecked(!ui.chkOpenCredentials->isEnabled() || m_pBox->GetBool("OpenCredentials", false));
- ui.chkOpenSmartCard->setChecked(m_pBox->GetBool("OpenSmartCard", true));
- ui.chkOpenBluetooth->setChecked(m_pBox->GetBool("OpenBluetooth", false));
+ //ui.chkOpenSmartCard->setChecked(m_pBox->GetBool("OpenSmartCard", true));
+ //ui.chkOpenBluetooth->setChecked(m_pBox->GetBool("OpenBluetooth", false));
ui.treeAutoStart->clear();
foreach(const QString & Value, m_pBox->GetTextList("StartProgram", m_Template))
@@ -617,8 +619,8 @@ void COptionsWindow::SaveConfig()
WriteAdvancedCheck(ui.chkOpenProtectedStorage, "OpenProtectedStorage", "y", "");
if (ui.chkOpenCredentials->isEnabled())
WriteAdvancedCheck(ui.chkOpenCredentials, "OpenCredentials", "y", "");
- WriteAdvancedCheck(ui.chkOpenSmartCard, "OpenSmartCard", "", "n");
- WriteAdvancedCheck(ui.chkOpenBluetooth, "OpenBluetooth", "y", "");
+ //WriteAdvancedCheck(ui.chkOpenSmartCard, "OpenSmartCard", "", "n");
+ //WriteAdvancedCheck(ui.chkOpenBluetooth, "OpenBluetooth", "y", "");
QStringList StartProgram;
@@ -751,7 +753,7 @@ void COptionsWindow::SaveConfig()
void COptionsWindow::apply()
{
- if (m_pBox->GetText("Enabled").isEmpty()) {
+ if (m_pBox->GetText("Enabled").isEmpty() && !(m_Template && m_pBox->GetName().mid(9, 6).compare("Local_", Qt::CaseInsensitive) == 0)) {
QMessageBox::critical(this, "Sandboxie-Plus", tr("This sandbox has been deleted hence configuration can not be saved."));
return;
}
@@ -2092,7 +2094,7 @@ void COptionsWindow::OnDelUser()
void COptionsWindow::LoadTemplates()
{
m_AllTemplates.clear();
- ui.cmbCategories->clear();
+ //ui.cmbCategories->clear();
QStringList Templates;
for (int index = 0; ; index++)
@@ -2119,7 +2121,7 @@ void COptionsWindow::LoadTemplates()
int End = Title.mid(1).indexOf(",");
if (End == -1) End = Title.length() - 1;
int MsgNum = Title.mid(1, End).toInt();
- Title = theAPI->GetSbieMsgStr(MsgNum, theGUI->m_LanguageId).arg(Title.mid(End + 2)).arg("");
+ Title = m_pBox->GetAPI()->GetSbieMsgStr(MsgNum, theGUI->m_LanguageId).arg(Title.mid(End + 2)).arg("");
}
if (Title.isEmpty()) Title = Name;
//else Title += " (" + Name + ")";
@@ -2129,13 +2131,16 @@ void COptionsWindow::LoadTemplates()
m_AllTemplates.insertMulti(Category, qMakePair(Name, Title));
}
- ui.cmbCategories->addItem(tr("All Categories"), "");
- ui.cmbCategories->setCurrentIndex(0);
- foreach(const QString& Category, m_AllTemplates.uniqueKeys())
+ if (ui.cmbCategories->count() == 0)
{
- if (Category.isEmpty())
- continue;
- ui.cmbCategories->addItem(Category, Category);
+ ui.cmbCategories->addItem(tr("All Categories"), "");
+ ui.cmbCategories->setCurrentIndex(0);
+ foreach(const QString & Category, m_AllTemplates.uniqueKeys())
+ {
+ if (Category.isEmpty())
+ continue;
+ ui.cmbCategories->addItem(Category, Category);
+ }
}
m_GlobalTemplates = m_pBox->GetAPI()->GetGlobalSettings()->GetTextList("Template", false);
@@ -2203,8 +2208,54 @@ void COptionsWindow::OnTemplateDoubleClicked(QTreeWidgetItem* pItem, int Column)
{
QSharedPointer pTemplate = QSharedPointer(new CSbieIni(pItem->data(1, Qt::UserRole).toString(), m_pBox->GetAPI()));
- COptionsWindow* pOptionsWindow = new COptionsWindow(pTemplate, pItem->text(1));
- pOptionsWindow->show();
+ COptionsWindow OptionsWindow(pTemplate, pItem->text(1));
+ OptionsWindow.exec();
+
+ if(pItem->text(0) == "Local")
+ LoadTemplates();
+}
+
+void COptionsWindow::OnAddTemplates()
+{
+ QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter the template identifier"), QLineEdit::Normal);
+ if (Value.isEmpty())
+ return;
+
+ QString Name = QString(Value).replace(" ", "_");
+
+ SB_STATUS Status = m_pBox->GetAPI()->ValidateName(Name);
+ if (Status.IsError()) {
+ QMessageBox::critical(this, "Sandboxie-Plus", tr("Error: %1").arg(CSandMan::FormatError(Status)));
+ return;
+ }
+
+ QSharedPointer pTemplate = QSharedPointer(new CSbieIni("Template_Local_" + Name, m_pBox->GetAPI()));
+
+ pTemplate->SetText("Tmpl.Title", Value);
+ pTemplate->SetText("Tmpl.Class", "Local");
+
+ COptionsWindow OptionsWindow(pTemplate, Value);
+ OptionsWindow.exec();
+
+ LoadTemplates();
+}
+
+void COptionsWindow::OnDelTemplates()
+{
+ QTreeWidgetItem* pItem = ui.treeTemplates->currentItem();
+ if (!pItem || pItem->text(0) != "Local")
+ {
+ QMessageBox::critical(this, "Sandboxie-Plus", tr("Only local templates can be removed!"));
+ return;
+ }
+
+ if (QMessageBox("Sandboxie-Plus", tr("Do you really want to delete the selected local template?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes)
+ return;
+
+ // delete section
+ m_pBox->GetAPI()->SbieIniSet(pItem->data(1, Qt::UserRole).toString(), "*", "");
+
+ LoadTemplates();
}
void COptionsWindow::SaveTemplates()
diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.h b/SandboxiePlus/SandMan/Windows/OptionsWindow.h
index be59c8cc..f713d777 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsWindow.h
+++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.h
@@ -94,6 +94,8 @@ private slots:
void OnFilterTemplates() { ShowTemplates(); }
void OnTemplateClicked(QTreeWidgetItem* pItem, int Column);
void OnTemplateDoubleClicked(QTreeWidgetItem* pItem, int Column);
+ void OnAddTemplates();
+ void OnDelTemplates();
void OnTab();
diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
index 5d2a1f0c..eda446fe 100644
--- a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
+++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
@@ -365,7 +365,7 @@ void CSettingsWindow::OnTab()
}
m_CompatLoaded = 1;
- m_CompatChanged = false;
+ m_CompatChanged = true;
}
}
diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h
index 400d7b53..36650e45 100644
--- a/SandboxiePlus/version.h
+++ b/SandboxiePlus/version.h
@@ -2,7 +2,7 @@
#define VERSION_MJR 0
#define VERSION_MIN 7
-#define VERSION_REV 2
+#define VERSION_REV 3
#define VERSION_UPD 0
#ifndef STR