From 80958824392b9ea4ec1932f02e2bd98b814591ad Mon Sep 17 00:00:00 2001 From: liamjm Date: Tue, 9 Feb 2016 14:45:28 -0800 Subject: Intercept CreateThread inside renderer and proxy out to CreateRemoteThread in browser. summary: * Create new interception * Create new IPC (IPC_CREATETHREAD_TAG) * new tests in process_policy_test.cc * Interception is installed, but passes call through by default. Proxy is only done for tests, when ALPC ports are closed. Note: the IPC uses VOIDPTR_TYPE for a size_t param. These are not guaranteed to be the same (http://stackoverflow.com/questions/1464174/size-t-vs-intptr-t). Should we create a size_t IPC type? BUG=464430 Review URL: https://codereview.chromium.org/1225183003 Cr-Commit-Position: refs/heads/master@{#374510} --- sandbox/win/src/interceptors.h | 1 + sandbox/win/src/interceptors_64.cc | 14 ++++ sandbox/win/src/interceptors_64.h | 9 +++ sandbox/win/src/ipc_tags.h | 1 + sandbox/win/src/policy_broker.cc | 14 +++- sandbox/win/src/policy_broker.h | 3 +- sandbox/win/src/process_policy_test.cc | 105 ++++++++++++++++++++++++- sandbox/win/src/process_thread_dispatcher.cc | 31 ++++++++ sandbox/win/src/process_thread_dispatcher.h | 7 ++ sandbox/win/src/process_thread_interception.cc | 79 ++++++++++++++++++- sandbox/win/src/process_thread_interception.h | 14 +++- sandbox/win/src/process_thread_policy.cc | 22 ++++++ sandbox/win/src/process_thread_policy.h | 10 +++ sandbox/win/src/sandbox_policy.h | 18 +++-- sandbox/win/src/sandbox_policy_base.cc | 10 ++- sandbox/win/src/sandbox_policy_base.h | 2 + sandbox/win/src/top_level_dispatcher.cc | 1 + sandbox/win/tests/common/controller.cc | 8 +- 18 files changed, 326 insertions(+), 23 deletions(-) (limited to 'sandbox/win') diff --git a/sandbox/win/src/interceptors.h b/sandbox/win/src/interceptors.h index 5ee6fd3..2391957 100644 --- a/sandbox/win/src/interceptors.h +++ b/sandbox/win/src/interceptors.h @@ -34,6 +34,7 @@ enum InterceptorId { // Process-thread dispatcher: CREATE_PROCESSW_ID, CREATE_PROCESSA_ID, + CREATE_THREAD_ID, // Registry dispatcher: CREATE_KEY_ID, OPEN_KEY_ID, diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc index cdef943..a9b38b6 100644 --- a/sandbox/win/src/interceptors_64.cc +++ b/sandbox/win/src/interceptors_64.cc @@ -201,6 +201,20 @@ SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA64( process_information); } +SANDBOX_INTERCEPT HANDLE WINAPI +TargetCreateThread64(LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + PVOID parameter, + DWORD creation_flags, + LPDWORD thread_id) { + CreateThreadFunction orig_fn = + reinterpret_cast(g_originals[CREATE_THREAD_ID]); + return TargetCreateThread(orig_fn, thread_attributes, stack_size, + start_address, parameter, creation_flags, + thread_id); +} + // ----------------------------------------------------------------------- SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateKey64( diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h index 7368ceb..16d1c9f 100644 --- a/sandbox/win/src/interceptors_64.h +++ b/sandbox/win/src/interceptors_64.h @@ -122,6 +122,15 @@ SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA64( LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, LPPROCESS_INFORMATION process_information); +// Interception of CreateThread in kernel32.dll. +SANDBOX_INTERCEPT HANDLE WINAPI +TargetCreateThread64(LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + PVOID parameter, + DWORD creation_flags, + LPDWORD thread_id); + // ----------------------------------------------------------------------- // Interceptors handled by the registry dispatcher. diff --git a/sandbox/win/src/ipc_tags.h b/sandbox/win/src/ipc_tags.h index d680411..3a1724b 100644 --- a/sandbox/win/src/ipc_tags.h +++ b/sandbox/win/src/ipc_tags.h @@ -32,6 +32,7 @@ enum { IPC_GDI_GDIDLLINITIALIZE_TAG, IPC_GDI_GETSTOCKOBJECT_TAG, IPC_USER_REGISTERCLASSW_TAG, + IPC_CREATETHREAD_TAG, IPC_LAST_TAG }; diff --git a/sandbox/win/src/policy_broker.cc b/sandbox/win/src/policy_broker.cc index e6c2b26..74a93f0 100644 --- a/sandbox/win/src/policy_broker.cc +++ b/sandbox/win/src/policy_broker.cc @@ -96,7 +96,8 @@ bool SetupNtdllImports(TargetProcess *child) { #undef INIT_GLOBAL_NT #undef INIT_GLOBAL_RTL -bool SetupBasicInterceptions(InterceptionManager* manager) { +bool SetupBasicInterceptions(InterceptionManager* manager, + bool is_csrss_connected) { // Interceptions provided by process_thread_policy, without actual policy. if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_THREAD_ID, 20) || !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || @@ -116,8 +117,15 @@ bool SetupBasicInterceptions(InterceptionManager* manager) { 20)) return false; - return INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID, - 24); + if (!INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID, + 24)) + return false; + } + + if (!is_csrss_connected) { + if (!INTERCEPT_EAT(manager, kKerneldllName, CreateThread, CREATE_THREAD_ID, + 28)) + return false; } return true; diff --git a/sandbox/win/src/policy_broker.h b/sandbox/win/src/policy_broker.h index 15d3b21..a8d819d 100644 --- a/sandbox/win/src/policy_broker.h +++ b/sandbox/win/src/policy_broker.h @@ -15,7 +15,8 @@ class TargetProcess; bool InitGlobalNt(); // Sets up interceptions not controlled by explicit policies. -bool SetupBasicInterceptions(InterceptionManager* manager); +bool SetupBasicInterceptions(InterceptionManager* manager, + bool is_csrss_connected); // Sets up imports from NTDLL for the given target process so the interceptions // can work. diff --git a/sandbox/win/src/process_policy_test.cc b/sandbox/win/src/process_policy_test.cc index 4dcefd9..0498d3c 100644 --- a/sandbox/win/src/process_policy_test.cc +++ b/sandbox/win/src/process_policy_test.cc @@ -11,6 +11,7 @@ #include "base/win/scoped_handle.h" #include "base/win/scoped_process_information.h" #include "base/win/windows_version.h" +#include "sandbox/win/src/process_thread_interception.h" #include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/sandbox_policy.h" @@ -269,6 +270,74 @@ SBOX_TESTS_COMMAND int Process_OpenToken(int argc, wchar_t **argv) { return SBOX_TEST_FAILED; } +// Generate a event name, used to test thread creation. +std::wstring GenerateEventName(DWORD pid) { + wchar_t buff[30] = {0}; + int res = swprintf_s(buff, sizeof(buff) / sizeof(buff[0]), + L"ProcessPolicyTest_%08x", pid); + if (-1 != res) { + return std::wstring(buff); + } + return std::wstring(); +} + +// This is the function that is called when testing thread creation. +// It is expected to set an event that the caller is waiting on. +DWORD TestThreadFunc(LPVOID lpdwThreadParam) { + std::wstring event_name = + GenerateEventName(reinterpret_cast(lpdwThreadParam)); + if (!event_name.length()) { + return 1; + } + HANDLE event = ::OpenEvent(EVENT_ALL_ACCESS | EVENT_MODIFY_STATE, FALSE, + event_name.c_str()); + if (!event) { + return 1; + } + if (!SetEvent(event)) { + return 1; + } + return 0; +} + +SBOX_TESTS_COMMAND int Process_CreateThread(int argc, wchar_t** argv) { + DWORD pid = ::GetCurrentProcessId(); + std::wstring event_name = GenerateEventName(pid); + if (!event_name.length()) { + return SBOX_TEST_FIRST_ERROR; + } + HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, event_name.c_str()); + if (!event) { + return SBOX_TEST_SECOND_ERROR; + } + + DWORD thread_id = 0; + HANDLE thread = NULL; + thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&TestThreadFunc, + (LPVOID)pid, 0, &thread_id); + + if (!thread) { + return SBOX_TEST_THIRD_ERROR; + } + if (!thread_id) { + return SBOX_TEST_FOURTH_ERROR; + } + if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) { + return SBOX_TEST_FIFTH_ERROR; + } + DWORD exit_code = 0; + if (!GetExitCodeThread(thread, &exit_code)) { + return SBOX_TEST_SIXTH_ERROR; + } + if (exit_code) { + return SBOX_TEST_SEVENTH_ERROR; + } + if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) { + return SBOX_TEST_FAILED; + } + return SBOX_TEST_SUCCEEDED; +} + TEST(ProcessPolicyTest, TestAllAccess) { // Check if the "all access" rule fails to be added when the token is too // powerful. @@ -397,7 +466,6 @@ TEST(ProcessPolicyTest, TestCreateProcessA) { sandbox::TargetPolicy* policy = runner.GetPolicy(); policy->SetJobLevel(JOB_NONE, 0); policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED); - base::string16 exe_path = MakePathToSys(L"calc.exe", false); ASSERT_TRUE(!exe_path.empty()); EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, @@ -406,4 +474,37 @@ TEST(ProcessPolicyTest, TestCreateProcessA) { runner.RunTest(L"Process_CreateProcessA calc.exe")); } -} // namespace sandbox +// This tests that the CreateThread works with CSRSS not locked down. +// In other words, that the interception passes through OK. +TEST(ProcessPolicyTest, TestCreateThreadWithCsrss) { + TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); + runner.SetDisableCsrss(false); + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_CreateThread")); +} + +// This tests that the CreateThread works with CSRSS locked down. +// In other words, that the interception correctly works. +TEST(ProcessPolicyTest, TestCreateThreadWithoutCsrss) { + TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_CreateThread")); +} + +// This tests that our CreateThread interceptors works when called directly. +TEST(ProcessPolicyTest, TestCreateThreadOutsideSandbox) { + DWORD pid = ::GetCurrentProcessId(); + std::wstring event_name = GenerateEventName(pid); + ASSERT_STRNE(NULL, event_name.c_str()); + HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, event_name.c_str()); + EXPECT_NE(static_cast(NULL), event); + + DWORD thread_id = 0; + HANDLE thread = NULL; + thread = TargetCreateThread(::CreateThread, NULL, 0, + (LPTHREAD_START_ROUTINE)&TestThreadFunc, + (LPVOID)pid, 0, &thread_id); + EXPECT_NE(static_cast(NULL), thread); + EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE)); + EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(event, INFINITE)); +} + +} // namespace sandbox \ No newline at end of file diff --git a/sandbox/win/src/process_thread_dispatcher.cc b/sandbox/win/src/process_thread_dispatcher.cc index 8debd1e..886017c 100644 --- a/sandbox/win/src/process_thread_dispatcher.cc +++ b/sandbox/win/src/process_thread_dispatcher.cc @@ -124,11 +124,22 @@ ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base) reinterpret_cast( &ThreadProcessDispatcher::CreateProcessW)}; + // NOTE(liamjm): 2nd param is size_t: Using VOIDPTR_TYPE as they are + // the same size on windows. + static_assert(sizeof(size_t) == sizeof(void*), + "VOIDPTR_TYPE not same size as size_t"); + static const IPCCall create_thread_params = { + {IPC_CREATETHREAD_TAG, + {VOIDPTR_TYPE, VOIDPTR_TYPE, VOIDPTR_TYPE, UINT32_TYPE}}, + reinterpret_cast( + &ThreadProcessDispatcher::CreateThread)}; + ipc_calls_.push_back(open_thread); ipc_calls_.push_back(open_process); ipc_calls_.push_back(process_token); ipc_calls_.push_back(process_tokenex); ipc_calls_.push_back(create_params); + ipc_calls_.push_back(create_thread_params); } bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager, @@ -138,6 +149,7 @@ bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager, case IPC_NTOPENPROCESS_TAG: case IPC_NTOPENPROCESSTOKEN_TAG: case IPC_NTOPENPROCESSTOKENEX_TAG: + case IPC_CREATETHREAD_TAG: // There is no explicit policy for these services. NOTREACHED(); return false; @@ -244,4 +256,23 @@ bool ThreadProcessDispatcher::CreateProcessW(IPCInfo* ipc, base::string16* name, return true; } +bool ThreadProcessDispatcher::CreateThread(IPCInfo* ipc, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + LPVOID parameter, + DWORD creation_flags) { + if (!start_address) { + return false; + } + + HANDLE handle; + DWORD ret = ProcessPolicy::CreateThreadAction(*ipc->client_info, stack_size, + start_address, parameter, + creation_flags, NULL, &handle); + + ipc->return_info.nt_status = ret; + ipc->return_info.handle = handle; + return true; +} + } // namespace sandbox diff --git a/sandbox/win/src/process_thread_dispatcher.h b/sandbox/win/src/process_thread_dispatcher.h index 008385f..d39ac65 100644 --- a/sandbox/win/src/process_thread_dispatcher.h +++ b/sandbox/win/src/process_thread_dispatcher.h @@ -50,6 +50,13 @@ class ThreadProcessDispatcher : public Dispatcher { base::string16* cur_dir, CountedBuffer* info); + // Processes IPC requests coming from calls to CreateThread() in the target. + bool CreateThread(IPCInfo* ipc, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + LPVOID parameter, + DWORD creation_flags); + PolicyBase* policy_base_; DISALLOW_COPY_AND_ASSIGN(ThreadProcessDispatcher); }; diff --git a/sandbox/win/src/process_thread_interception.cc b/sandbox/win/src/process_thread_interception.cc index f8a144f..9cb20b9 100644 --- a/sandbox/win/src/process_thread_interception.cc +++ b/sandbox/win/src/process_thread_interception.cc @@ -5,7 +5,7 @@ #include "sandbox/win/src/process_thread_interception.h" #include - +#include "base/win/windows_version.h" #include "sandbox/win/src/crosscall_client.h" #include "sandbox/win/src/ipc_tags.h" #include "sandbox/win/src/policy_params.h" @@ -408,4 +408,81 @@ BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA, return FALSE; } +HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread, + LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + LPVOID parameter, + DWORD creation_flags, + LPDWORD thread_id) { + HANDLE hThread = NULL; + + TargetServices* target_services = SandboxFactory::GetTargetServices(); + if (NULL == target_services || + target_services->GetState()->IsCsrssConnected()) { + hThread = orig_CreateThread(thread_attributes, stack_size, start_address, + parameter, creation_flags, thread_id); + if (hThread) { + return hThread; + } + } + + DWORD original_error = ::GetLastError(); + do { + if (NULL == target_services) + break; + + // We don't trust that the IPC can work this early. + if (!target_services->GetState()->InitCalled()) + break; + + __try { + if (NULL != thread_id && + !ValidParameter(thread_id, sizeof(*thread_id), WRITE)) + break; + + if (nullptr == start_address) + break; + // We don't support thread_attributes not being null. + if (nullptr != thread_attributes) + break; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + + void* memory = GetGlobalIPCMemory(); + if (nullptr == memory) + break; + + SharedMemIPCClient ipc(memory); + CrossCallReturn answer = {0}; + + // NOTE: we don't pass the thread_attributes through. This matches the + // approach in CreateProcess and in CreateThreadInternal(). + ResultCode code = CrossCall(ipc, IPC_CREATETHREAD_TAG, + reinterpret_cast(stack_size), + reinterpret_cast(start_address), + parameter, creation_flags, &answer); + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + if (ERROR_SUCCESS != answer.win32_result) { + return NULL; + } + + __try { + if (thread_id != NULL) { + *thread_id = ::GetThreadId(answer.handle); + } + return answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + } while (false); + + ::SetLastError(original_error); + return NULL; +} + } // namespace sandbox diff --git a/sandbox/win/src/process_thread_interception.h b/sandbox/win/src/process_thread_interception.h index 31dc231..aff1f6d 100644 --- a/sandbox/win/src/process_thread_interception.h +++ b/sandbox/win/src/process_thread_interception.h @@ -36,11 +36,11 @@ typedef BOOL (WINAPI *CreateProcessAFunction)( LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); -typedef HANDLE (WINAPI *CreateThreadFunction)( +typedef HANDLE(WINAPI* CreateThreadFunction)( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, - PVOID lpParameter, + LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); @@ -83,6 +83,16 @@ SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA( LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, LPPROCESS_INFORMATION process_information); +// Interception of CreateThread in kernel32.dll. +SANDBOX_INTERCEPT HANDLE WINAPI +TargetCreateThread(CreateThreadFunction orig_CreateThread, + LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + LPVOID parameter, + DWORD creation_flags, + LPDWORD thread_id); + } // extern "C" } // namespace sandbox diff --git a/sandbox/win/src/process_thread_policy.cc b/sandbox/win/src/process_thread_policy.cc index b4976c0b..11928c8 100644 --- a/sandbox/win/src/process_thread_policy.cc +++ b/sandbox/win/src/process_thread_policy.cc @@ -238,4 +238,26 @@ DWORD ProcessPolicy::CreateProcessWAction(EvalResult eval_result, return ERROR_SUCCESS; } +DWORD ProcessPolicy::CreateThreadAction( + const ClientInfo& client_info, + const SIZE_T stack_size, + const LPTHREAD_START_ROUTINE start_address, + const LPVOID parameter, + const DWORD creation_flags, + LPDWORD thread_id, + HANDLE* handle) { + HANDLE local_handle = + ::CreateRemoteThread(client_info.process, nullptr, stack_size, + start_address, parameter, creation_flags, thread_id); + if (!local_handle) { + return ::GetLastError(); + } + if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, + client_info.process, handle, 0, FALSE, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { + return ERROR_ACCESS_DENIED; + } + return ERROR_SUCCESS; +} + } // namespace sandbox diff --git a/sandbox/win/src/process_thread_policy.h b/sandbox/win/src/process_thread_policy.h index a66b52e..0cfa451 100644 --- a/sandbox/win/src/process_thread_policy.h +++ b/sandbox/win/src/process_thread_policy.h @@ -76,6 +76,16 @@ class ProcessPolicy { const base::string16 &app_name, const base::string16 &command_line, PROCESS_INFORMATION* process_info); + + // Processes a 'CreateThread()' request from the target. + // 'client_info' : the target process that is making the request. + static DWORD CreateThreadAction(const ClientInfo& client_info, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + PVOID parameter, + DWORD creation_flags, + LPDWORD thread_id, + HANDLE* handle); }; } // namespace sandbox diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h index 43b272b..909066f 100644 --- a/sandbox/win/src/sandbox_policy.h +++ b/sandbox/win/src/sandbox_policy.h @@ -48,17 +48,17 @@ class TargetPolicy { // over the resulting process and thread handles. // No other parameters besides the command line are // passed to the child process. - PROCESS_ALL_EXEC, // Allows the creation of a process and return fill + PROCESS_ALL_EXEC, // Allows the creation of a process and return full // access on the returned handles. // This flag can be used only when the main token of // the sandboxed application is at least INTERACTIVE. EVENTS_ALLOW_ANY, // Allows the creation of an event with full access. - EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. - REG_ALLOW_READONLY, // Allows readonly access to a registry key. - REG_ALLOW_ANY, // Allows read and write access to a registry key. - FAKE_USER_GDI_INIT // Fakes user32 and gdi32 initialization. This can - // be used to allow the DLLs to load and initialize - // even if the process cannot access that subsystem. + EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. + REG_ALLOW_READONLY, // Allows readonly access to a registry key. + REG_ALLOW_ANY, // Allows read and write access to a registry key. + FAKE_USER_GDI_INIT // Fakes user32 and gdi32 initialization. This can + // be used to allow the DLLs to load and initialize + // even if the process cannot access that subsystem. }; // Increments the reference count of this object. The reference count must @@ -209,6 +209,10 @@ class TargetPolicy { // Returns the currently set delayed mitigation flags. virtual MitigationFlags GetDelayedProcessMitigations() const = 0; + // Disconnect the target from CSRSS when TargetServices::LowerToken() is + // called inside the target. + virtual void SetDisconnectCsrss() = 0; + // Sets the interceptions to operate in strict mode. By default, interceptions // are performed in "relaxed" mode, where if something inside NTDLL.DLL is // already patched we attempt to intercept it anyway. Setting interceptions diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc index dc3ed1f..f7002bf 100644 --- a/sandbox/win/src/sandbox_policy_base.cc +++ b/sandbox/win/src/sandbox_policy_base.cc @@ -133,6 +133,7 @@ PolicyBase::PolicyBase() delayed_integrity_level_(INTEGRITY_LEVEL_LAST), mitigations_(0), delayed_mitigations_(0), + is_csrss_connected_(true), policy_maker_(NULL), policy_(NULL), lowbox_sid_(NULL) { @@ -625,6 +626,13 @@ bool PolicyBase::OnJobEmpty(HANDLE job) { return true; } +void PolicyBase::SetDisconnectCsrss() { + if (base::win::GetVersion() >= base::win::VERSION_WIN8) { + is_csrss_connected_ = false; + AddKernelObjectToClose(L"ALPC Port", NULL); + } +} + EvalResult PolicyBase::EvalPolicy(int service, CountedParameterSetBase* params) { if (NULL != policy_) { @@ -677,7 +685,7 @@ bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { } } - if (!SetupBasicInterceptions(&manager)) + if (!SetupBasicInterceptions(&manager, is_csrss_connected_)) return false; if (!manager.InitializeInterceptions()) diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h index 6520915..cd30eba 100644 --- a/sandbox/win/src/sandbox_policy_base.h +++ b/sandbox/win/src/sandbox_policy_base.h @@ -61,6 +61,7 @@ class PolicyBase final : public TargetPolicy { MitigationFlags GetProcessMitigations() override; ResultCode SetDelayedProcessMitigations(MitigationFlags flags) override; MitigationFlags GetDelayedProcessMitigations() const override; + void SetDisconnectCsrss() override; void SetStrictInterceptions() override; ResultCode SetStdoutHandle(HANDLE handle) override; ResultCode SetStderrHandle(HANDLE handle) override; @@ -145,6 +146,7 @@ class PolicyBase final : public TargetPolicy { IntegrityLevel delayed_integrity_level_; MitigationFlags mitigations_; MitigationFlags delayed_mitigations_; + bool is_csrss_connected_; // Object in charge of generating the low level policy. LowLevelPolicy* policy_maker_; // Memory structure that stores the low level policy. diff --git a/sandbox/win/src/top_level_dispatcher.cc b/sandbox/win/src/top_level_dispatcher.cc index e6e224b..1880c62 100644 --- a/sandbox/win/src/top_level_dispatcher.cc +++ b/sandbox/win/src/top_level_dispatcher.cc @@ -47,6 +47,7 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; + ipc_targets_[IPC_CREATETHREAD_TAG] = dispatcher; thread_process_dispatcher_.reset(dispatcher); dispatcher = new SyncDispatcher(policy_); diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc index c9c63ae..3b710578 100644 --- a/sandbox/win/tests/common/controller.cc +++ b/sandbox/win/tests/common/controller.cc @@ -213,12 +213,8 @@ int TestRunner::InternalRunTest(const wchar_t* command) { target_process_id_ = 0; } - if (disable_csrss_) { - // Close all ALPC ports to disable CSRSS. - if (base::win::GetVersion() >= base::win::VERSION_WIN8) { - policy_->AddKernelObjectToClose(L"ALPC Port", NULL); - } - } + if (disable_csrss_) + policy_->SetDisconnectCsrss(); // Get the path to the sandboxed process. wchar_t prog_name[MAX_PATH]; -- cgit v1.1