michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include michael@0: michael@0: #include "sandbox/win/src/policy_broker.h" michael@0: michael@0: #include "base/logging.h" michael@0: #include "base/win/pe_image.h" michael@0: #include "base/win/windows_version.h" michael@0: #include "sandbox/win/src/interception.h" michael@0: #include "sandbox/win/src/interceptors.h" michael@0: #include "sandbox/win/src/policy_target.h" michael@0: #include "sandbox/win/src/process_thread_interception.h" michael@0: #include "sandbox/win/src/sandbox.h" michael@0: #include "sandbox/win/src/sandbox_nt_types.h" michael@0: #include "sandbox/win/src/sandbox_types.h" michael@0: #include "sandbox/win/src/target_process.h" michael@0: michael@0: // This code executes on the broker side, as a callback from the policy on the michael@0: // target side (the child). michael@0: michael@0: namespace sandbox { michael@0: michael@0: // This is the list of all imported symbols from ntdll.dll. michael@0: SANDBOX_INTERCEPT NtExports g_nt; michael@0: michael@0: #define INIT_GLOBAL_NT(member) \ michael@0: g_nt.member = reinterpret_cast( \ michael@0: ntdll_image.GetProcAddress("Nt" #member)); \ michael@0: if (NULL == g_nt.member) \ michael@0: return false michael@0: michael@0: #define INIT_GLOBAL_RTL(member) \ michael@0: g_nt.member = reinterpret_cast( \ michael@0: ntdll_image.GetProcAddress(#member)); \ michael@0: if (NULL == g_nt.member) \ michael@0: return false michael@0: michael@0: bool SetupNtdllImports(TargetProcess *child) { michael@0: HMODULE ntdll = ::GetModuleHandle(kNtdllName); michael@0: base::win::PEImage ntdll_image(ntdll); michael@0: michael@0: // Bypass purify's interception. michael@0: wchar_t* loader_get = reinterpret_cast( michael@0: ntdll_image.GetProcAddress("LdrGetDllHandle")); michael@0: if (loader_get) { michael@0: GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | michael@0: GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, michael@0: loader_get, &ntdll); michael@0: } michael@0: michael@0: INIT_GLOBAL_NT(AllocateVirtualMemory); michael@0: INIT_GLOBAL_NT(Close); michael@0: INIT_GLOBAL_NT(DuplicateObject); michael@0: INIT_GLOBAL_NT(FreeVirtualMemory); michael@0: INIT_GLOBAL_NT(MapViewOfSection); michael@0: INIT_GLOBAL_NT(ProtectVirtualMemory); michael@0: INIT_GLOBAL_NT(QueryInformationProcess); michael@0: INIT_GLOBAL_NT(QueryObject); michael@0: INIT_GLOBAL_NT(QuerySection); michael@0: INIT_GLOBAL_NT(QueryVirtualMemory); michael@0: INIT_GLOBAL_NT(UnmapViewOfSection); michael@0: michael@0: INIT_GLOBAL_RTL(RtlAllocateHeap); michael@0: INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString); michael@0: INIT_GLOBAL_RTL(RtlCompareUnicodeString); michael@0: INIT_GLOBAL_RTL(RtlCreateHeap); michael@0: INIT_GLOBAL_RTL(RtlCreateUserThread); michael@0: INIT_GLOBAL_RTL(RtlDestroyHeap); michael@0: INIT_GLOBAL_RTL(RtlFreeHeap); michael@0: INIT_GLOBAL_RTL(_strnicmp); michael@0: INIT_GLOBAL_RTL(strlen); michael@0: INIT_GLOBAL_RTL(wcslen); michael@0: michael@0: #ifndef NDEBUG michael@0: // Verify that the structure is fully initialized. michael@0: for (size_t i = 0; i < sizeof(g_nt)/sizeof(void*); i++) michael@0: DCHECK(reinterpret_cast(&g_nt)[i]); michael@0: #endif michael@0: return (SBOX_ALL_OK == child->TransferVariable("g_nt", &g_nt, sizeof(g_nt))); michael@0: } michael@0: michael@0: #undef INIT_GLOBAL_NT michael@0: #undef INIT_GLOBAL_RTL michael@0: michael@0: bool SetupBasicInterceptions(InterceptionManager* manager) { michael@0: // Interceptions provided by process_thread_policy, without actual policy. michael@0: if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_TREAD_ID, 20) || michael@0: !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || michael@0: !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16)) michael@0: return false; michael@0: michael@0: // Interceptions with neither policy nor IPC. michael@0: if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID, michael@0: 20) || michael@0: !INTERCEPT_NT(manager, NtOpenThreadToken, OPEN_THREAD_TOKEN_ID, 20)) michael@0: return false; michael@0: michael@0: if (base::win::GetVersion() >= base::win::VERSION_XP) { michael@0: // Bug 27218: We don't have dispatch for some x64 syscalls. michael@0: // This one is also provided by process_thread_policy. michael@0: if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID, michael@0: 20)) michael@0: return false; michael@0: michael@0: return INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID, michael@0: 24); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: } // namespace sandbox