From f5c5224a264d81a1ecdae8d3ac92367ad198c299 Mon Sep 17 00:00:00 2001 From: DavidXanatos <3890945+DavidXanatos@users.noreply.github.com> Date: Fri, 10 May 2024 17:50:03 +0200 Subject: [PATCH] /fcp --- CHANGELOG.md | 1 + Sandboxie/apps/start/start.cpp | 35 ++++++- Sandboxie/core/drv/api_defs.h | 1 + Sandboxie/core/drv/process.c | 8 ++ Sandboxie/core/drv/process.h | 7 ++ Sandboxie/core/drv/process_force.c | 141 ++++++++++++++++++++++++++++- Sandboxie/core/drv/session.c | 35 +++++++ 7 files changed, 221 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cade017f..ee2ed1eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Add option to limit the memory of sandboxed process and the number of process in single sandbox through job object. (thanks Yeyixiao) - Add ability to modified sandboxed process logic speed (reduced fixed latency, modified single-player speed, etc.) (thanks Yeyixiao) +- Added /fcp /force_children commandline option to start.exe it allows to start a program unsandboxed but have all its children sandboxed diff --git a/Sandboxie/apps/start/start.cpp b/Sandboxie/apps/start/start.cpp index 349e7d90..5e5c857c 100644 --- a/Sandboxie/apps/start/start.cpp +++ b/Sandboxie/apps/start/start.cpp @@ -28,6 +28,7 @@ #include "core/svc/SbieIniWire.h" #include "common/my_version.h" #include "msgs/msgs.h" +#include "core/drv/api_defs.h" //--------------------------------------------------------------------------- @@ -88,6 +89,7 @@ BOOL execute_auto_run = FALSE; BOOL execute_open_with = FALSE; BOOL run_elevated_2 = FALSE; BOOL disable_force_on_this_program = FALSE; +BOOL force_children_on_this_program = FALSE; BOOL auto_select_default_box = FALSE; WCHAR *StartMenuSectionName = NULL; BOOL run_silent = FALSE; @@ -716,6 +718,17 @@ BOOL Parse_Command_Line(void) disable_force_on_this_program = TRUE; + // + // Command line switch /force_children or /fcp + // + + } else if (_wcsnicmp(cmd, L"force_children", 14) == 0 || + _wcsnicmp(cmd, L"fcp", 3) == 0) { + + cmd = Eat_String(cmd); + + force_children_on_this_program = TRUE; + // // Command line switch /hide_window // @@ -1193,7 +1206,7 @@ int Program_Start(void) shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); shExecInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOZONECHECKS; - if (wait_for_process || keep_alive) + if (wait_for_process || keep_alive || force_children_on_this_program) shExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS; shExecInfo.hwnd = NULL; shExecInfo.lpVerb = NULL; @@ -1337,6 +1350,8 @@ int Program_Start(void) if (ok && (wait_for_process || keep_alive)) hNewProcess = shExecInfo.hProcess; + else if(ok && force_children_on_this_program) + pi.dwProcessId = GetProcessId(shExecInfo.hProcess); if (! ok) { @@ -1364,9 +1379,16 @@ int Program_Start(void) // we know for sure that SandboxieRpcSs has opened it // - if (ok && (! disable_force_on_this_program)) { + if (ok) { - SbieDll_StartCOM(FALSE); + if (force_children_on_this_program) { + + SbieApi_Call(API_FORCE_CHILDREN, 2, pi.dwProcessId, BoxName); + + } else if (!disable_force_on_this_program) { + + SbieDll_StartCOM(FALSE); + } } // @@ -1395,7 +1417,9 @@ int Program_Start(void) } } - } else if (GetModuleHandle(L"protect.dll")) { + } + // $Workaround$ - 3rd party fix + else if (GetModuleHandle(L"protect.dll")) { // // hack for FortKnox firewall -- keep Start.exe around for a few @@ -1833,8 +1857,9 @@ int __stdcall WinMainCRTStartup( ULONG NewState = DISABLE_JUST_THIS_PROCESS; SbieApi_DisableForceProcess(&NewState, NULL); - return die(Program_Start()); } + if (disable_force_on_this_program || force_children_on_this_program) + return die(Program_Start()); } return die(RestartInSandbox()); diff --git a/Sandboxie/core/drv/api_defs.h b/Sandboxie/core/drv/api_defs.h index 35672861..81ab1288 100644 --- a/Sandboxie/core/drv/api_defs.h +++ b/Sandboxie/core/drv/api_defs.h @@ -162,6 +162,7 @@ enum { API_PROTECT_ROOT, API_UNPROTECT_ROOT, API_KILL_PROCESS, + API_FORCE_CHILDREN, API_LAST }; diff --git a/Sandboxie/core/drv/process.c b/Sandboxie/core/drv/process.c index 7564cffc..4e23e07a 100644 --- a/Sandboxie/core/drv/process.c +++ b/Sandboxie/core/drv/process.c @@ -101,9 +101,11 @@ static NTSTATUS Process_CreateUserProcess( #ifdef USE_PROCESS_MAP HASH_MAP Process_Map; HASH_MAP Process_MapDfp; +HASH_MAP Process_MapFcp; #else LIST Process_List; LIST Process_ListDfp; +LIST Process_ListFcp; #endif PERESOURCE Process_ListLock = NULL; @@ -136,9 +138,13 @@ _FX BOOLEAN Process_Init(void) map_init(&Process_MapDfp, Driver_Pool); map_resize(&Process_MapDfp, 128); // prepare some buckets for better performance + + map_init(&Process_MapFcp, Driver_Pool); + map_resize(&Process_MapFcp, 128); // prepare some buckets for better performance #else List_Init(&Process_List); List_Init(&Process_ListDfp); + List_Init(&Process_ListFcp); #endif if (! Mem_GetLockResource(&Process_ListLock, TRUE)) @@ -1537,6 +1543,8 @@ _FX void Process_Delete(HANDLE ProcessId) Process_DfpDelete(ProcessId); + Process_FcpDelete(ProcessId); + ExReleaseResourceLite(Process_ListLock); KeLowerIrql(irql); diff --git a/Sandboxie/core/drv/process.h b/Sandboxie/core/drv/process.h index b9087a23..d819dede 100644 --- a/Sandboxie/core/drv/process.h +++ b/Sandboxie/core/drv/process.h @@ -447,6 +447,11 @@ void Process_DfpDelete(HANDLE ProcessId); BOOLEAN Process_DfpCheck(HANDLE ProcessId, BOOLEAN *silent); +// Force Child Processes + +VOID Process_FcpInsert(HANDLE ProcessId, const WCHAR* boxname); +void Process_FcpDelete(HANDLE ProcessId); +BOOLEAN Process_FcpCheck(HANDLE ProcessId, WCHAR* boxname); // Enumerate or count processes in a sandbox @@ -533,9 +538,11 @@ NTSTATUS Process_Api_Kill(PROCESS *proc, ULONG64 *parms); #ifdef USE_PROCESS_MAP extern HASH_MAP Process_Map; extern HASH_MAP Process_MapDfp; +extern HASH_MAP Process_MapFcp; #else extern LIST Process_List; extern LIST Process_ListDfp; +extern LIST Process_ListFcp; #endif extern PERESOURCE Process_ListLock; diff --git a/Sandboxie/core/drv/process_force.c b/Sandboxie/core/drv/process_force.c index c03c4fd2..936d53e0 100644 --- a/Sandboxie/core/drv/process_force.c +++ b/Sandboxie/core/drv/process_force.c @@ -79,6 +79,16 @@ typedef struct _FORCE_PROCESS_2 { } FORCE_PROCESS_2; +typedef struct _FORCE_PROCESS_3 { + +#ifndef USE_PROCESS_MAP + LIST_ELEM list_elem; +#endif + HANDLE pid; + WCHAR boxname[BOXNAME_COUNT]; + +} FORCE_PROCESS_3; + //--------------------------------------------------------------------------- // Functions //--------------------------------------------------------------------------- @@ -274,6 +284,23 @@ _FX BOX *Process_GetForcedStartBox( Process_DfpInsert(PROCESS_TERMINATED, ProcessId); } + if (!box) { + + WCHAR boxname[BOXNAME_COUNT]; + + if (Process_FcpCheck(ParentId, boxname)) { + + ULONG boxname_len = (wcslen(boxname) + 1) * sizeof(WCHAR); + for (FORCE_BOX* cur_box = List_Head(&boxes); cur_box; cur_box = List_Next(cur_box)) { + if (cur_box->box->name_len == boxname_len + && _wcsicmp(cur_box->box->name, boxname) == 0) { + box = cur_box->box; + break; + } + } + } + } + if (alert != 1) force_alert = FALSE; @@ -794,7 +821,6 @@ _FX BOOLEAN Process_IsProcessParent(HANDLE ParentId, WCHAR* Name) _FX BOOLEAN Process_IsWindowsExplorerParent(HANDLE ParentId) { - return Process_IsProcessParent(ParentId,L"explorer.exe"); } @@ -1399,10 +1425,12 @@ _FX BOX *Process_CheckForceProcess( return box->box; } - //if (Process_IsWindowsExplorerParent(ParentId) && Conf_Get_Boolean(box->box->name, L"ForceExplorerChild", FALSE)) { + + //if (Process_IsWindowsExplorerParent(ParentId) && Conf_Get_Boolean(box->box->name, L"ForceExplorerChild", 0, FALSE)) { // if(_wcsicmp(name,L"Sandman.exe")!=0) // return box->box; //} + box = List_Next(box); } @@ -1758,3 +1786,112 @@ _FX BOOLEAN Process_DfpCheck(HANDLE ProcessId, BOOLEAN *silent) return found; } + + +//--------------------------------------------------------------------------- +// Process_FcpInsert +//--------------------------------------------------------------------------- + + +_FX VOID Process_FcpInsert(HANDLE ProcessId, const WCHAR* boxname) +{ + FORCE_PROCESS_3 *proc; + KIRQL irql; + + // + // called by Session_Api_ForceChildren, process list not locked + // + + KeRaiseIrql(APC_LEVEL, &irql); + ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); + + Process_FcpDelete(ProcessId); + + proc = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS_3)); + proc->pid = ProcessId; + wmemcpy(proc->boxname, boxname, BOXNAME_COUNT); + +#ifdef USE_PROCESS_MAP + map_insert(&Process_MapFcp, ProcessId, proc, 0); +#else + List_Insert_After(&Process_ListFcp, NULL, proc); +#endif + + ExReleaseResourceLite(Process_ListLock); + KeLowerIrql(irql); + + +} + + +//--------------------------------------------------------------------------- +// Process_FcpDelete +//--------------------------------------------------------------------------- + + +_FX void Process_FcpDelete(HANDLE ProcessId) +{ + FORCE_PROCESS_3 *proc; + +#ifdef USE_PROCESS_MAP + if(map_take(&Process_MapFcp, ProcessId, &proc, 0)) + Mem_Free(proc, sizeof(FORCE_PROCESS_3)); +#else + proc = List_Head(&Process_ListFcp); + while (proc) { + + if (proc->pid == ProcessId) { + + List_Remove(&Process_ListFcp, proc); + + Mem_Free(proc, sizeof(FORCE_PROCESS_3)); + + return; + } + + proc = List_Next(proc); + } +#endif +} + + +//--------------------------------------------------------------------------- +// Process_FcpCheck +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Process_FcpCheck(HANDLE ProcessId, WCHAR* boxname) +{ + FORCE_PROCESS_3 *proc; + KIRQL irql; + BOOLEAN found = FALSE; + + KeRaiseIrql(APC_LEVEL, &irql); + ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); + +#ifdef USE_PROCESS_MAP + proc = map_get(&Process_MapFcp, ProcessId); + if (proc) { +#else + proc = List_Head(&Process_ListFcp); + while (proc) { + + if (proc->pid == ProcessId) { +#endif + if(boxname) + wmemcpy(boxname, proc->boxname, BOXNAME_COUNT); + + found = TRUE; +#ifndef USE_PROCESS_MAP + break; + } + + proc = List_Next(proc); +#endif + } + + ExReleaseResourceLite(Process_ListLock); + KeLowerIrql(irql); + + return found; +} \ No newline at end of file diff --git a/Sandboxie/core/drv/session.c b/Sandboxie/core/drv/session.c index b35cecee..aedca89a 100644 --- a/Sandboxie/core/drv/session.c +++ b/Sandboxie/core/drv/session.c @@ -104,6 +104,8 @@ static NTSTATUS Session_Api_Leader(PROCESS *proc, ULONG64 *parms); static NTSTATUS Session_Api_DisableForce(PROCESS *proc, ULONG64 *parms); +static NTSTATUS Session_Api_ForceChildren(PROCESS *proc, ULONG64 *parms); + static NTSTATUS Session_Api_MonitorControl(PROCESS *proc, ULONG64 *parms); //static NTSTATUS Session_Api_MonitorPut(PROCESS *proc, ULONG64 *parms); @@ -141,6 +143,7 @@ _FX BOOLEAN Session_Init(void) Api_SetFunction(API_SESSION_LEADER, Session_Api_Leader); Api_SetFunction(API_DISABLE_FORCE_PROCESS, Session_Api_DisableForce); + Api_SetFunction(API_FORCE_CHILDREN, Session_Api_ForceChildren); Api_SetFunction(API_MONITOR_CONTROL, Session_Api_MonitorControl); //Api_SetFunction(API_MONITOR_PUT, Session_Api_MonitorPut); Api_SetFunction(API_MONITOR_PUT2, Session_Api_MonitorPut2); @@ -496,6 +499,38 @@ _FX BOOLEAN Session_IsForceDisabled(ULONG SessionId) } +//--------------------------------------------------------------------------- +// Session_Api_ForceChildren +//--------------------------------------------------------------------------- + + +_FX NTSTATUS Session_Api_ForceChildren(PROCESS *proc, ULONG64 *parms) +{ + HANDLE process_id; + WCHAR *user_boxname; + WCHAR boxname[BOXNAME_COUNT]; + + if (proc) + return STATUS_NOT_IMPLEMENTED; + + process_id = (HANDLE)parms[1]; + + memzero(boxname, sizeof(boxname)); + user_boxname = (WCHAR *)parms[2]; + if (user_boxname) { + ProbeForRead(user_boxname, sizeof(WCHAR) * (BOXNAME_COUNT - 2), sizeof(UCHAR)); + if (user_boxname[0]) + wcsncpy(boxname, user_boxname, (BOXNAME_COUNT - 2)); + } + if(!process_id || process_id == (HANDLE)-1 || !boxname[0]) + return STATUS_INVALID_PARAMETER; + + Process_FcpInsert(process_id, boxname); + + return STATUS_SUCCESS; +} + + //--------------------------------------------------------------------------- // Session_IsLeader //---------------------------------------------------------------------------