1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <map>
6
7#include "sandbox/win/src/policy_broker.h"
8
9#include "base/logging.h"
10#include "base/win/pe_image.h"
11#include "base/win/windows_version.h"
12#include "sandbox/win/src/interception.h"
13#include "sandbox/win/src/interceptors.h"
14#include "sandbox/win/src/policy_target.h"
15#include "sandbox/win/src/process_thread_interception.h"
16#include "sandbox/win/src/sandbox.h"
17#include "sandbox/win/src/sandbox_nt_types.h"
18#include "sandbox/win/src/sandbox_types.h"
19#include "sandbox/win/src/target_process.h"
20
21// This code executes on the broker side, as a callback from the policy on the
22// target side (the child).
23
24namespace sandbox {
25
26// This is the list of all imported symbols from ntdll.dll.
27SANDBOX_INTERCEPT NtExports g_nt;
28
29#define INIT_GLOBAL_NT(member) \
30  g_nt.member = reinterpret_cast<Nt##member##Function>( \
31                      ntdll_image.GetProcAddress("Nt" #member)); \
32  if (NULL == g_nt.member) \
33    return false
34
35#define INIT_GLOBAL_RTL(member) \
36  g_nt.member = reinterpret_cast<member##Function>( \
37                      ntdll_image.GetProcAddress(#member)); \
38  if (NULL == g_nt.member) \
39    return false
40
41bool SetupNtdllImports(TargetProcess *child) {
42  HMODULE ntdll = ::GetModuleHandle(kNtdllName);
43  base::win::PEImage ntdll_image(ntdll);
44
45  // Bypass purify's interception.
46  wchar_t* loader_get = reinterpret_cast<wchar_t*>(
47                            ntdll_image.GetProcAddress("LdrGetDllHandle"));
48  if (loader_get) {
49    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
50                          GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
51                      loader_get, &ntdll);
52  }
53
54  INIT_GLOBAL_NT(AllocateVirtualMemory);
55  INIT_GLOBAL_NT(Close);
56  INIT_GLOBAL_NT(DuplicateObject);
57  INIT_GLOBAL_NT(FreeVirtualMemory);
58  INIT_GLOBAL_NT(MapViewOfSection);
59  INIT_GLOBAL_NT(ProtectVirtualMemory);
60  INIT_GLOBAL_NT(QueryInformationProcess);
61  INIT_GLOBAL_NT(QueryObject);
62  INIT_GLOBAL_NT(QuerySection);
63  INIT_GLOBAL_NT(QueryVirtualMemory);
64  INIT_GLOBAL_NT(UnmapViewOfSection);
65
66  INIT_GLOBAL_RTL(RtlAllocateHeap);
67  INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
68  INIT_GLOBAL_RTL(RtlCompareUnicodeString);
69  INIT_GLOBAL_RTL(RtlCreateHeap);
70  INIT_GLOBAL_RTL(RtlCreateUserThread);
71  INIT_GLOBAL_RTL(RtlDestroyHeap);
72  INIT_GLOBAL_RTL(RtlFreeHeap);
73  INIT_GLOBAL_RTL(_strnicmp);
74  INIT_GLOBAL_RTL(strlen);
75  INIT_GLOBAL_RTL(wcslen);
76  INIT_GLOBAL_RTL(memcpy);
77
78#ifndef NDEBUG
79  // Verify that the structure is fully initialized.
80  for (size_t i = 0; i < sizeof(g_nt)/sizeof(void*); i++)
81    DCHECK(reinterpret_cast<char**>(&g_nt)[i]);
82#endif
83  return (SBOX_ALL_OK == child->TransferVariable("g_nt", &g_nt, sizeof(g_nt)));
84}
85
86#undef INIT_GLOBAL_NT
87#undef INIT_GLOBAL_RTL
88
89bool SetupBasicInterceptions(InterceptionManager* manager) {
90  // Interceptions provided by process_thread_policy, without actual policy.
91  if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_TREAD_ID, 20) ||
92      !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) ||
93      !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16))
94    return false;
95
96  // Interceptions with neither policy nor IPC.
97  if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID,
98                    20) ||
99      !INTERCEPT_NT(manager, NtOpenThreadToken, OPEN_THREAD_TOKEN_ID, 20))
100    return false;
101
102  if (base::win::GetVersion() >= base::win::VERSION_XP) {
103    // Bug 27218: We don't have dispatch for some x64 syscalls.
104    // This one is also provided by process_thread_policy.
105    if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID,
106                      20))
107      return false;
108
109    return INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID,
110                        24);
111  }
112
113  return true;
114}
115
116}  // namespace sandbox
117