519 lines
15 KiB
C
519 lines
15 KiB
C
/*
|
|
* Copyright 2004-2020 Sandboxie Holdings, LLC
|
|
* Copyright 2020-2021 David Xanatos, xanasoft.com
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Process Management
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef _MY_PROCESS_H
|
|
#define _MY_PROCESS_H
|
|
|
|
|
|
#include "driver.h"
|
|
#include "box.h"
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Defines
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#ifdef _WIN64
|
|
#define PROCESS_TERMINATED ((PROCESS *) 0xFFFFFFFFFFFFFFFF)
|
|
#else
|
|
#define PROCESS_TERMINATED ((PROCESS *) 0xFFFFFFFF)
|
|
#endif
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Structures and Types
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
struct _PROCESS {
|
|
|
|
// changes to the linked list of PROCESS blocks are synchronized by
|
|
// an exclusive lock on Process_ListLock
|
|
|
|
#ifndef USE_PROCESS_MAP
|
|
LIST_ELEM list_elem;
|
|
#endif
|
|
|
|
// process id
|
|
|
|
HANDLE pid;
|
|
#ifdef DRV_BREAKOUT
|
|
HANDLE starter_id;
|
|
#endif
|
|
|
|
// process pool. created on process creation. it is freed in its
|
|
// entirety when the process terminates
|
|
|
|
POOL *pool;
|
|
|
|
// box parameters
|
|
|
|
BOX *box;
|
|
|
|
// full name and extension of executable image, and an indication if
|
|
// the image was loaded from within the copy system
|
|
|
|
WCHAR *image_path;
|
|
|
|
WCHAR *image_name;
|
|
ULONG image_name_len; // in bytes, including NULL
|
|
|
|
BOOLEAN image_from_box;
|
|
BOOLEAN image_sbie;
|
|
|
|
// process creation time and integrity level
|
|
|
|
ULONG64 create_time;
|
|
|
|
ULONG integrity_level;
|
|
|
|
ULONG ntdll32_base;
|
|
|
|
ULONG detected_image_type;
|
|
|
|
// original process primary access token
|
|
|
|
void *primary_token;
|
|
|
|
PSID *SandboxieLogonSid;
|
|
|
|
// thread data
|
|
|
|
PERESOURCE threads_lock;
|
|
|
|
#ifdef USE_PROCESS_MAP
|
|
HASH_MAP thread_map;
|
|
#else
|
|
LIST threads;
|
|
#endif
|
|
|
|
// flags
|
|
|
|
volatile BOOLEAN initialized; // process initialized once?
|
|
volatile BOOLEAN terminated; // process termination started?
|
|
volatile ULONG reason; // process termination reason
|
|
|
|
BOOLEAN untouchable; // protected process?
|
|
|
|
BOOLEAN drop_rights; // admin rights should be dropped?
|
|
BOOLEAN rights_dropped; // admin rights were dropped?
|
|
|
|
BOOLEAN forced_process;
|
|
|
|
BOOLEAN sbiedll_loaded;
|
|
BOOLEAN sbielow_loaded;
|
|
|
|
BOOLEAN is_start_exe;
|
|
BOOLEAN parent_was_start_exe;
|
|
BOOLEAN parent_was_sandboxed;
|
|
|
|
BOOLEAN change_notify_token_flag;
|
|
|
|
BOOLEAN bAppCompartment;
|
|
|
|
BOOLEAN in_pca_job;
|
|
BOOLEAN can_use_jobs;
|
|
|
|
UCHAR create_console_flag;
|
|
|
|
BOOLEAN disable_monitor;
|
|
|
|
BOOLEAN always_close_for_boxed;
|
|
BOOLEAN dont_open_for_boxed;
|
|
#ifdef USE_MATCH_PATH_EX
|
|
BOOLEAN use_rule_specificity;
|
|
BOOLEAN use_privacy_mode;
|
|
#endif
|
|
|
|
ULONG call_trace;
|
|
|
|
// file-related
|
|
|
|
PERESOURCE file_lock;
|
|
#ifdef USE_MATCH_PATH_EX
|
|
LIST normal_file_paths; // PATTERN elements
|
|
#endif
|
|
LIST open_file_paths; // PATTERN elements
|
|
LIST closed_file_paths; // PATTERN elements
|
|
LIST read_file_paths; // PATTERN elements
|
|
LIST write_file_paths; // PATTERN elements
|
|
BOOLEAN file_block_network_files;
|
|
LIST blocked_dlls;
|
|
ULONG file_trace;
|
|
ULONG pipe_trace;
|
|
BOOLEAN disable_file_flt;
|
|
BOOLEAN file_warn_internet;
|
|
BOOLEAN file_warn_direct_access;
|
|
BOOLEAN AllowInternetAccess;
|
|
BOOLEAN file_open_devapi_cmapi;
|
|
|
|
// key-related
|
|
|
|
PERESOURCE key_lock;
|
|
KEY_MOUNT *key_mount;
|
|
#ifdef USE_MATCH_PATH_EX
|
|
LIST normal_key_paths; // PATTERN elements
|
|
#endif
|
|
LIST open_key_paths; // PATTERN elements
|
|
LIST closed_key_paths; // PATTERN elements
|
|
LIST read_key_paths; // PATTERN elements
|
|
LIST write_key_paths; // PATTERN elements
|
|
ULONG key_trace;
|
|
BOOLEAN disable_key_flt;
|
|
|
|
// ipc-related
|
|
|
|
PERESOURCE ipc_lock;
|
|
#ifdef USE_MATCH_PATH_EX
|
|
LIST normal_ipc_paths; // PATTERN elements
|
|
#endif
|
|
LIST open_ipc_paths; // PATTERN elements
|
|
LIST closed_ipc_paths; // PATTERN elements
|
|
LIST read_ipc_paths; // PATTERN elements
|
|
ULONG ipc_trace;
|
|
BOOLEAN disable_object_flt;
|
|
BOOLEAN ipc_warn_startrun;
|
|
BOOLEAN ipc_warn_open_proc;
|
|
BOOLEAN ipc_block_password;
|
|
BOOLEAN ipc_open_lsa_endpoint;
|
|
BOOLEAN ipc_open_sam_endpoint;
|
|
BOOLEAN ipc_allowSpoolerPrintToFile;
|
|
BOOLEAN ipc_openPrintSpooler;
|
|
|
|
// gui-related
|
|
|
|
PERESOURCE gui_lock;
|
|
BOOLEAN open_all_win_classes;
|
|
void *block_fake_input_hwnd;
|
|
void *gui_user_area;
|
|
WCHAR *gui_class_name;
|
|
LIST open_win_classes;
|
|
ULONG gui_trace;
|
|
|
|
BOOLEAN bHostInject;
|
|
|
|
};
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Functions
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
BOOLEAN Process_Init(void);
|
|
|
|
void Process_Unload(BOOLEAN FreeLock);
|
|
|
|
|
|
// Process_Find finds the PROCESS block for the specified process id.
|
|
// If ProcessId is NULL, returns current sandboxed process.
|
|
// If ProcessId is NULL and current sandboxed process is scheduled for
|
|
// termination, the return value is PROCESS_TERMINATED
|
|
|
|
PROCESS *Process_Find(HANDLE ProcessId, KIRQL *out_irql);
|
|
|
|
PROCESS *Process_FindSandboxed(HANDLE ProcessId, KIRQL *out_irql);
|
|
|
|
|
|
// Start supervising a new process
|
|
|
|
BOOLEAN Process_NotifyProcess_Create(
|
|
HANDLE ProcessId, HANDLE ParentId, HANDLE CallerId, BOX *box);
|
|
|
|
|
|
// Process_IsSameBox returns TRUE if the other process identified by
|
|
// 'proc2' or 'proc2_pid' is in the same sandbox as the caller 'proc'.
|
|
// note that 'proc2_pid' is used only if 'proc2' is passed as NULL.
|
|
|
|
BOOLEAN Process_IsSameBox(PROCESS *proc, PROCESS *proc2, ULONG_PTR proc2_pid);
|
|
|
|
#ifdef DRV_BREAKOUT
|
|
// Process_IsStarter returns TRUE if proc2 was started by proc1
|
|
|
|
BOOLEAN Process_IsStarter(PROCESS* proc1, PROCESS* proc2);
|
|
#endif
|
|
|
|
// Process_MatchImage: given an image name pattern 'pat_str', which
|
|
// may contain wild cards, tests the image name 'test_str' against
|
|
// the pattern. If 'pat_len' is specified, only the first 'pat_len'
|
|
// characters of 'pat_str' are used for the pattern. All memory
|
|
// temporarily needed is is allocated from specified pool
|
|
|
|
BOOLEAN Process_MatchImage(
|
|
BOX *box, const WCHAR *pat_str, ULONG pat_len, const WCHAR *test_str,
|
|
ULONG depth);
|
|
|
|
|
|
// Process_GetPaths: given a process and the name of a path-list
|
|
// setting (e.g. OpenFilePath), adds the settings into the specified list.
|
|
// if AddStar is TRUE, then for each value for this setting, a star (*)
|
|
// is suffixed unless the value already contains a star anywhere
|
|
|
|
BOOLEAN Process_GetPaths(
|
|
PROCESS *proc, LIST *list, const WCHAR *setting_name, BOOLEAN AddStar);
|
|
|
|
|
|
// Process_GetPaths2: similar to Process_GetPaths, but adds the path
|
|
// only if it does not already match the second path-list
|
|
|
|
BOOLEAN Process_GetPaths2(
|
|
PROCESS *proc, LIST *list, LIST *list2,
|
|
const WCHAR *setting_name, BOOLEAN AddStar);
|
|
|
|
|
|
// Process_AddPath: given a process and the name of a path-list
|
|
// setting (e.g. OpenFilePath), add the value as the first or last
|
|
// entry, depending on AddFirst. does not add a suffix wildcard
|
|
|
|
BOOLEAN Process_AddPath(
|
|
PROCESS *proc, LIST *list, const WCHAR *setting_name,
|
|
BOOLEAN AddFirst, const WCHAR *value, BOOLEAN AddStar);
|
|
|
|
|
|
// Process_MatchPath: given a list that was previously initialized with
|
|
// Process_GetPaths, tests if the passed string 'path' matches any pattern.
|
|
// path_len specifies the number of characters in path, excluding the
|
|
// null terminator, or in other words, path_len is wcslen(path).
|
|
// Returns the source string for the pattern that matched the path.
|
|
|
|
const WCHAR *Process_MatchPath(
|
|
POOL *pool, const WCHAR *path, ULONG path_len,
|
|
LIST *open_list, LIST *closed_list,
|
|
BOOLEAN *is_open, BOOLEAN *is_closed);
|
|
|
|
// Process_MatchPathEx: given a list that was previously initialized with
|
|
// Process_GetPaths, tests if the passed string 'path' matches any pattern.
|
|
// path_len specifies the number of characters in path, excluding the
|
|
// null terminator, or in other words, path_len is wcslen(path).
|
|
// Returns the highest priority true path permission
|
|
|
|
#define TRUE_PATH_CLOSED_FLAG 0x00
|
|
#define TRUE_PATH_READ_FLAG 0x10
|
|
#define TRUE_PATH_WRITE_FLAG 0x20
|
|
#define TRUE_PATH_OPEN_FLAG 0x30
|
|
#define TRUE_PATH_MASK 0x30
|
|
|
|
#define COPY_PATH_CLOSED_FLAG 0x00
|
|
#define COPY_PATH_READ_FLAG 0x01
|
|
#define COPY_PATH_WRITE_FLAG 0x02
|
|
#define COPY_PATH_OPEN_FLAG 0x03
|
|
#define COPY_PATH_MASK 0x03
|
|
|
|
ULONG Process_MatchPathEx(
|
|
PROCESS *proc, const WCHAR *path, ULONG path_len, WCHAR path_code,
|
|
LIST *normal_list,
|
|
LIST *open_list, LIST *closed_list,
|
|
LIST *read_list, LIST *write_list,
|
|
const WCHAR** patsrc);
|
|
|
|
// Process_GetConf: retrieves a configuration data value for a given process
|
|
// use with Conf_AdjustUseCount to make sure the returned pointer is valid
|
|
|
|
const WCHAR* Process_GetConf(PROCESS* proc, const WCHAR* setting);
|
|
|
|
|
|
// Process_GetConf_bool: parses a y/n setting. this function does not
|
|
// have to be protected with Conf_AdjustUseCount
|
|
|
|
BOOLEAN Process_GetConf_bool(PROCESS* proc, const WCHAR* setting, BOOLEAN def);
|
|
|
|
|
|
// Build a standard entry for hooks. The standard entry calls
|
|
// Process_Find(NULL, NULL). If non-zero (this includes -1 for
|
|
// PROCESS_TERMINATED), the entry jumps to NewProc, where
|
|
// the process object is available to _GetAx (see util.h).
|
|
// If Process_Find returns zero, the entry jumps to OldProc.
|
|
// In either case, if IncPtr was specified, the entry includes
|
|
// code to increment the ULONG at IncPtr
|
|
|
|
ULONG_PTR Process_BuildHookEntry(
|
|
ULONG_PTR NewProc, ULONG_PTR OldProc, ULONG *IncPtr);
|
|
|
|
void Process_DisableHookEntry(ULONG_PTR HookEntry);
|
|
|
|
|
|
// Return the current process as prepared by the standard hook entry
|
|
|
|
PROCESS *Process_GetCurrent(void);
|
|
|
|
|
|
|
|
// Returns ProcessName.exe for idProcess, allocated from the specified pool.
|
|
// On return, *out_buf points to a UNICODE_STRING structure which points
|
|
// to the NULL-terminated process name immediately following the structure.
|
|
// *out_len contains the length of *out_buf.
|
|
// *out_ptr receives out_buf->Buffer.
|
|
// Free buffer using Mem_Free(*out_buf, *out_len).
|
|
// On error, out_buf, out_len, out_ptr receive NULL
|
|
|
|
void Process_GetProcessName(
|
|
POOL *pool, ULONG_PTR idProcess,
|
|
void **out_buf, ULONG *out_len, WCHAR **out_ptr);
|
|
|
|
|
|
// Check if open_path contains setting "$:ProcessName.exe"
|
|
// where ProcessName matches the specified idProcess.
|
|
// If not contained, returns FALSE with *pSetting = NULL
|
|
// If contained, returns TRUE with *pSetting -> matching setting
|
|
|
|
BOOLEAN Process_CheckProcessName(
|
|
PROCESS *proc, LIST *open_paths, ULONG_PTR idProcess,
|
|
const WCHAR **pSetting);
|
|
|
|
|
|
// Return SID string and session ID for the process specified by the
|
|
// process handle or process id number.
|
|
// To free the returned SidString, use RtlFreeUnicodeString
|
|
|
|
NTSTATUS Process_GetSidStringAndSessionId(
|
|
HANDLE ProcessHandle, HANDLE ProcessId,
|
|
UNICODE_STRING *SidString, ULONG *SessionId);
|
|
|
|
|
|
// Get a box for a forced sandboxed process
|
|
|
|
BOX *Process_GetForcedStartBox(
|
|
HANDLE ProcessId, HANDLE ParentId, const WCHAR *ImagePath, BOOLEAN* pHostInject, const WCHAR *pSidString);
|
|
|
|
|
|
#ifdef DRV_BREAKOUT
|
|
BOOLEAN Process_IsBreakoutProcess(BOX *box, const WCHAR *ImagePath);
|
|
#endif
|
|
|
|
// Manipulation of the List of Disabled Forced Processes: (Process_List2)
|
|
// Add ProcessId to list if ParentId is already listed
|
|
// Hold Process_ListLock before calling, if ParentId != PROCESS_TERMINATED
|
|
|
|
BOOLEAN Process_DfpInsert(HANDLE ParentId, HANDLE ProcessId);
|
|
|
|
|
|
// Manipulation of the List of Disabled Forced Processes: (Process_List2)
|
|
// Delete ProcessId from list
|
|
// Hold Process_ListLock before calling
|
|
|
|
void Process_DfpDelete(HANDLE ProcessId);
|
|
|
|
|
|
// Manipulation of the List of Disabled Forced Processes: (Process_List2)
|
|
// Check if ProcessId is listed
|
|
// Do not hold Process_ListLock before calling
|
|
|
|
BOOLEAN Process_DfpCheck(HANDLE ProcessId, BOOLEAN *silent);
|
|
|
|
|
|
// Enumerate or count processes in a sandbox
|
|
|
|
NTSTATUS Process_Enumerate(
|
|
const WCHAR *boxname, BOOLEAN all_sessions, ULONG session_id,
|
|
ULONG *pids, ULONG *count);
|
|
|
|
|
|
// Issue log message with detail "ProcessName [BoxName]"
|
|
|
|
void Process_LogMessage(PROCESS *proc, ULONG msgid);
|
|
|
|
|
|
// Track process limit
|
|
|
|
//void Process_TrackProcessLimit(PROCESS *proc);
|
|
|
|
// Terminate process
|
|
|
|
BOOLEAN Process_TerminateProcess(PROCESS *proc);
|
|
|
|
// Cancel process through SbieSvc
|
|
|
|
BOOLEAN Process_CancelProcess(PROCESS *proc);
|
|
|
|
// Terminate a process using a helper thread
|
|
|
|
BOOLEAN Process_ScheduleKill(PROCESS *proc, LONG delay_ms);
|
|
|
|
// Check if process is running within a
|
|
// Program Compatibility Assistant (PCA) job
|
|
|
|
BOOLEAN Process_IsInPcaJob(HANDLE ProcessId);
|
|
|
|
|
|
void Process_SetTerminated(PROCESS *proc, ULONG reason);
|
|
|
|
|
|
//
|
|
// low level syscal interface (process_low.c)
|
|
//
|
|
|
|
|
|
BOOLEAN Process_Low_Init(void);
|
|
|
|
void Process_Low_Unload(void);
|
|
|
|
BOOLEAN Process_Low_Inject(
|
|
HANDLE process_id, ULONG session_id, ULONG64 create_time,
|
|
const WCHAR *image_name, BOOLEAN add_process_to_job, BOOLEAN bHostInject);
|
|
|
|
BOOLEAN Process_Low_InitConsole(PROCESS *proc);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS Process_Api_Start(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_Query(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_QueryInfo(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_QueryBoxPath(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_QueryProcessPath(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_QueryPathList(PROCESS *proc, ULONG64 *parms);
|
|
|
|
NTSTATUS Process_Api_Enum(PROCESS *proc, ULONG64 *parms);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Variables
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#ifdef USE_PROCESS_MAP
|
|
extern HASH_MAP Process_Map;
|
|
extern HASH_MAP Process_MapDfp;
|
|
#else
|
|
extern LIST Process_List;
|
|
extern LIST Process_ListDfp;
|
|
#endif
|
|
extern PERESOURCE Process_ListLock;
|
|
|
|
extern volatile BOOLEAN Process_ReadyToSandbox;
|
|
|
|
extern const WCHAR *Process_UnknownImageName;
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#endif // _MY_PROCESS_H
|