OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "sandbox/win/src/process_mitigations.h" |
| 6 |
| 7 #include <psapi.h> |
| 8 |
| 9 #include <chrono> |
| 10 #include <thread> |
| 11 |
| 12 #include "base/command_line.h" |
5 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
6 #include "base/files/scoped_temp_dir.h" | 14 #include "base/files/scoped_temp_dir.h" |
7 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
8 #include "base/path_service.h" | 16 #include "base/path_service.h" |
9 #include "base/process/launch.h" | 17 #include "base/process/launch.h" |
10 #include "base/strings/stringprintf.h" | 18 #include "base/win/registry.h" |
11 #include "base/win/scoped_handle.h" | 19 #include "base/win/scoped_handle.h" |
| 20 #include "base/win/startup_information.h" |
| 21 #include "base/win/win_util.h" |
12 #include "base/win/windows_version.h" | 22 #include "base/win/windows_version.h" |
13 #include "sandbox/win/src/nt_internals.h" | 23 #include "sandbox/win/src/nt_internals.h" |
14 #include "sandbox/win/src/process_mitigations.h" | |
15 #include "sandbox/win/src/sandbox.h" | 24 #include "sandbox/win/src/sandbox.h" |
16 #include "sandbox/win/src/sandbox_factory.h" | 25 #include "sandbox/win/src/sandbox_factory.h" |
17 #include "sandbox/win/src/target_services.h" | 26 #include "sandbox/win/src/target_services.h" |
18 #include "sandbox/win/src/win_utils.h" | |
19 #include "sandbox/win/tests/common/controller.h" | 27 #include "sandbox/win/tests/common/controller.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
21 | 29 |
22 namespace { | 30 namespace { |
23 | 31 |
24 // API defined in winbase.h. | 32 // API defined in winbase.h. |
25 typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; | 33 typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; |
26 | 34 |
27 // API defined in processthreadsapi.h. | 35 // API defined in processthreadsapi.h. |
28 typedef decltype( | 36 typedef decltype( |
29 GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction; | 37 GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction; |
30 GetProcessMitigationPolicyFunction get_process_mitigation_policy; | 38 GetProcessMitigationPolicyFunction get_process_mitigation_policy; |
31 | 39 |
32 // APIs defined in wingdi.h. | 40 // APIs defined in wingdi.h. |
33 typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; | 41 typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; |
34 typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; | 42 typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; |
35 | 43 |
| 44 // WinProc event name for synchronization. |
| 45 const wchar_t* winproc_event = L"ChromeExtensionTestEvent"; |
| 46 DWORD event_max_wait_ms = 3 * 1000; |
| 47 |
36 #if !defined(_WIN64) | 48 #if !defined(_WIN64) |
37 bool CheckWin8DepPolicy() { | 49 bool CheckWin8DepPolicy() { |
38 PROCESS_MITIGATION_DEP_POLICY policy = {}; | 50 PROCESS_MITIGATION_DEP_POLICY policy = {}; |
39 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, | 51 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, |
40 &policy, sizeof(policy))) { | 52 &policy, sizeof(policy))) { |
41 return false; | 53 return false; |
42 } | 54 } |
43 return policy.Enable && policy.Permanent; | 55 return policy.Enable && policy.Permanent; |
44 } | 56 } |
45 #endif // !defined(_WIN64) | 57 #endif // !defined(_WIN64) |
(...skipping 23 matching lines...) Expand all Loading... |
69 bool CheckWin8Win32CallPolicy() { | 81 bool CheckWin8Win32CallPolicy() { |
70 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; | 82 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; |
71 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 83 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
72 ProcessSystemCallDisablePolicy, | 84 ProcessSystemCallDisablePolicy, |
73 &policy, sizeof(policy))) { | 85 &policy, sizeof(policy))) { |
74 return false; | 86 return false; |
75 } | 87 } |
76 return policy.DisallowWin32kSystemCalls; | 88 return policy.DisallowWin32kSystemCalls; |
77 } | 89 } |
78 | 90 |
79 bool CheckWin8DllExtensionPolicy() { | 91 bool CheckWin8ExtensionPointPolicy() { |
80 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; | 92 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; |
81 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 93 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
82 ProcessExtensionPointDisablePolicy, | 94 ProcessExtensionPointDisablePolicy, |
83 &policy, sizeof(policy))) { | 95 &policy, sizeof(policy))) { |
84 return false; | 96 return false; |
85 } | 97 } |
86 return policy.DisableExtensionPoints; | 98 return policy.DisableExtensionPoints; |
87 } | 99 } |
88 | 100 |
89 bool CheckWin10FontPolicy() { | 101 bool CheckWin10FontPolicy() { |
90 PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {}; | 102 PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {}; |
91 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 103 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
92 ProcessFontDisablePolicy, &policy, | 104 ProcessFontDisablePolicy, &policy, |
93 sizeof(policy))) { | 105 sizeof(policy))) { |
94 return false; | 106 return false; |
95 } | 107 } |
96 return policy.DisableNonSystemFonts; | 108 return policy.DisableNonSystemFonts; |
97 } | 109 } |
98 | 110 |
99 bool CheckWin10ImageLoadNoRemotePolicy() { | 111 bool CheckWin10ImageLoadNoRemotePolicy() { |
100 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; | 112 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; |
101 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 113 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
102 ProcessImageLoadPolicy, &policy, | 114 ProcessImageLoadPolicy, &policy, |
103 sizeof(policy))) { | 115 sizeof(policy))) { |
104 return false; | 116 return false; |
105 } | 117 } |
106 return policy.NoRemoteImages; | 118 return policy.NoRemoteImages; |
107 } | 119 } |
108 | 120 |
| 121 // Spawn our Windows process (with or without mitigation enabled). |
| 122 void SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) { |
| 123 base::win::StartupInformation startup_info; |
| 124 DWORD creation_flags = 0; |
| 125 |
| 126 if (!success_test) { |
| 127 DWORD64 flags = |
| 128 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; |
| 129 // This test only runs on >= Win8, so I don't have to worry about |
| 130 // illegal 64-bit flags on 32-bit <= Win7. |
| 131 size_t flags_size = sizeof(flags); |
| 132 |
| 133 EXPECT_TRUE(startup_info.InitializeProcThreadAttributeList(1)); |
| 134 EXPECT_TRUE(startup_info.UpdateProcThreadAttribute( |
| 135 PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)); |
| 136 creation_flags = EXTENDED_STARTUPINFO_PRESENT; |
| 137 } |
| 138 |
| 139 std::wstring cmd_line = L"sbox_integration_test_win_proc.exe "; |
| 140 scoped_ptr<wchar_t, base::FreeDeleter> cmd_writeable( |
| 141 ::wcsdup(cmd_line.c_str())); |
| 142 |
| 143 EXPECT_TRUE(::CreateProcessW(NULL, cmd_writeable.get(), NULL, NULL, FALSE, |
| 144 creation_flags, NULL, NULL, |
| 145 startup_info.startup_info(), pi)); |
| 146 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_max_wait_ms)); |
| 147 |
| 148 return; |
| 149 } |
| 150 |
| 151 //------------------------------------------------------------------------------ |
| 152 // 1. Spawn our Windows process (with or without mitigation enabled). |
| 153 // 2. Load our hook Dll locally. |
| 154 // 3. Start the hook (for our WinProc or globally). |
| 155 // 4. Send a keystroke event. |
| 156 // 5. Ask the hook Dll if it received a hook callback. |
| 157 // 6. Cleanup the hooking. |
| 158 // 7. Signal our Windows process to shutdown. |
| 159 // |
| 160 // Do NOT use any ASSERTs in this function. Cleanup required. |
| 161 //------------------------------------------------------------------------------ |
| 162 |
| 163 typedef BOOL (*WasHookCalledFunction)(); |
| 164 |
| 165 void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) { |
| 166 HMODULE dll = NULL; |
| 167 HHOOK hook = NULL; |
| 168 HOOKPROC hook_proc = NULL; |
| 169 WasHookCalledFunction WasHookCalled = NULL; |
| 170 PROCESS_INFORMATION proc_info = {}; |
| 171 |
| 172 // 1. Spawn WinProc. |
| 173 HANDLE event = ::CreateEventW(NULL, FALSE, FALSE, winproc_event); |
| 174 EXPECT_TRUE(event != NULL && event != INVALID_HANDLE_VALUE); |
| 175 SpawnWinProc(&proc_info, is_success_test, &event); |
| 176 |
| 177 // 2. Load the hook DLL. |
| 178 dll = ::LoadLibraryW(L"sbox_integration_test_hook_dll.dll"); |
| 179 EXPECT_TRUE(dll); |
| 180 |
| 181 hook_proc = reinterpret_cast<HOOKPROC>(::GetProcAddress(dll, "HookProc")); |
| 182 WasHookCalled = reinterpret_cast<WasHookCalledFunction>( |
| 183 ::GetProcAddress(dll, "WasHookCalled")); |
| 184 EXPECT_TRUE(hook_proc && WasHookCalled); |
| 185 |
| 186 // 3. Try installing the hook (either on our remote target thread, |
| 187 // or globally). |
| 188 DWORD target = 0; |
| 189 if (!global_hook) |
| 190 target = proc_info.dwThreadId; |
| 191 hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll, target); |
| 192 EXPECT_TRUE(hook); |
| 193 |
| 194 // 4. Inject a keyboard event. |
| 195 |
| 196 // Note: that PostThreadMessage and SendMessage APIs will not deliver |
| 197 // a keystroke in such a way that triggers a "legitimate" hook. |
| 198 // Have to use targetless SendInput or keybd_event. The latter is |
| 199 // less code and easier to work with. |
| 200 keybd_event(VkKeyScan(L'A'), 0, 0, 0); |
| 201 std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
| 202 keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0); |
| 203 |
| 204 // Give it a chance... |
| 205 std::this_thread::sleep_for(std::chrono::seconds(1)); |
| 206 |
| 207 // 5. Did our hook get hit? Did we expect it to? |
| 208 if (global_hook) |
| 209 EXPECT_EQ((is_success_test ? TRUE : FALSE), WasHookCalled()); |
| 210 else |
| 211 // ***IMPORTANT: when targeting a specific thread id, the |
| 212 // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE |
| 213 // mitigation does NOT disable the hook API. It ONLY |
| 214 // stops global hooks from running in your process. Hence, |
| 215 // we expect the hook to have hit (TRUE) even in the "failure" |
| 216 // case for a non-global/targetted hook. |
| 217 EXPECT_EQ((is_success_test ? TRUE : TRUE), WasHookCalled()); |
| 218 |
| 219 // 6. Rip it all down. |
| 220 if (hook) |
| 221 EXPECT_TRUE(::UnhookWindowsHookEx(hook)); |
| 222 if (dll) |
| 223 EXPECT_TRUE(::FreeLibrary(dll)); |
| 224 |
| 225 // 7. Trigger shutdown of WinProc. |
| 226 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { |
| 227 // Note: The combination/perfect-storm of a Global Hook, in a |
| 228 // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the |
| 229 // use of the SendInput or keybd_event API to inject a keystroke, |
| 230 // results in the target becoming unresponsive. If any one of these states |
| 231 // are changed, the problem does not occur. |
| 232 // This means the WM_QUIT message is not handled and the call to |
| 233 // WaitForSingleObject times out. Therefore not checking the return val. |
| 234 ::WaitForSingleObject(event, event_max_wait_ms); |
| 235 EXPECT_TRUE(::CloseHandle(event)); |
| 236 } else { |
| 237 // Make sure we don't leave a stray. |
| 238 ::TerminateProcess(proc_info.hProcess, 0); |
| 239 EXPECT_TRUE(false); |
| 240 } |
| 241 EXPECT_TRUE(::CloseHandle(proc_info.hThread)); |
| 242 EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); |
| 243 } |
| 244 |
| 245 //------------------------------------------------------------------------------ |
| 246 // 1. Set up our AppInit Dll in registry settings. (Enable) |
| 247 // 2. Spawn our Windows process (with or without mitigation enabled). |
| 248 // 3. Check if our AppInit Dll is loaded in our Windows process or not. |
| 249 // 4. Signal our Windows process to shutdown. |
| 250 // 5. Restore original reg settings. |
| 251 // |
| 252 // Do NOT use any ASSERTs in this function. Cleanup required. |
| 253 //------------------------------------------------------------------------------ |
| 254 void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) { |
| 255 PROCESS_INFORMATION proc_info = {}; |
| 256 wchar_t* hook_dll = L"sbox_integration_test_hook_dll.dll"; |
| 257 |
| 258 // Get path of current executable. |
| 259 wchar_t path[MAX_PATH]; |
| 260 EXPECT_TRUE(::GetModuleFileNameW(NULL, path, MAX_PATH)); |
| 261 // We just want the directory. |
| 262 wchar_t* last_separator = ::wcsrchr(path, L'\\'); |
| 263 EXPECT_TRUE(last_separator); |
| 264 last_separator++; |
| 265 *last_separator = L'\0'; |
| 266 ::wcsncat(path, hook_dll, (MAX_PATH - ::wcslen(path))); |
| 267 // Prep short-name path to our hook dll, for registry. |
| 268 DWORD length = ::GetShortPathNameW(path, NULL, 0); |
| 269 wchar_t* short_name = new wchar_t[length]; |
| 270 EXPECT_TRUE(::GetShortPathNameW(path, short_name, length)); |
| 271 |
| 272 // 1. Reg setup. |
| 273 wchar_t* app_init_reg_path = |
| 274 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; |
| 275 wchar_t* dlls_value_name = L"AppInit_DLLs"; |
| 276 wchar_t* enabled_value_name = L"LoadAppInit_DLLs"; |
| 277 wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs"; |
| 278 std::wstring orig_dlls; |
| 279 std::wstring new_dlls; |
| 280 DWORD orig_enabled_value = 0; |
| 281 DWORD orig_signing_value = 0; |
| 282 base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path, |
| 283 KEY_QUERY_VALUE | KEY_SET_VALUE); |
| 284 // Backup the existing settings. |
| 285 EXPECT_TRUE(app_init_key.Valid()); |
| 286 EXPECT_TRUE(app_init_key.HasValue(dlls_value_name) && |
| 287 app_init_key.HasValue(enabled_value_name)); |
| 288 EXPECT_EQ(ERROR_SUCCESS, app_init_key.ReadValue(dlls_value_name, &orig_dlls)); |
| 289 EXPECT_EQ(ERROR_SUCCESS, |
| 290 app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)); |
| 291 if (app_init_key.HasValue(signing_value_name)) |
| 292 EXPECT_EQ(ERROR_SUCCESS, app_init_key.ReadValueDW(signing_value_name, |
| 293 &orig_signing_value)); |
| 294 |
| 295 // Set the new settings we want (obviously requires local admin privileges). |
| 296 new_dlls = orig_dlls; |
| 297 if (0 != orig_dlls.compare(L"")) |
| 298 new_dlls.append(L","); |
| 299 new_dlls.append(short_name); |
| 300 delete[] short_name; |
| 301 |
| 302 EXPECT_EQ(ERROR_SUCCESS, |
| 303 app_init_key.WriteValue(dlls_value_name, new_dlls.c_str())); |
| 304 if (app_init_key.HasValue(signing_value_name)) |
| 305 EXPECT_EQ(ERROR_SUCCESS, app_init_key.WriteValue(signing_value_name, |
| 306 static_cast<DWORD>(0))); |
| 307 EXPECT_EQ(ERROR_SUCCESS, |
| 308 app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))); |
| 309 |
| 310 // 2. Spawn WinProc. |
| 311 HANDLE event = ::CreateEventW(NULL, FALSE, FALSE, winproc_event); |
| 312 EXPECT_TRUE(event != NULL && event != INVALID_HANDLE_VALUE); |
| 313 SpawnWinProc(&proc_info, is_success_test, &event); |
| 314 |
| 315 // 3. Check loaded modules in WinProc to see if AppInit dll is loaded. |
| 316 std::vector<HMODULE>(modules); |
| 317 EXPECT_TRUE( |
| 318 base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)); |
| 319 BOOL dll_loaded = FALSE; |
| 320 |
| 321 for (auto module : modules) { |
| 322 wchar_t name[MAX_PATH]; |
| 323 EXPECT_TRUE( |
| 324 ::GetModuleFileNameExW(proc_info.hProcess, module, name, MAX_PATH)); |
| 325 |
| 326 // Compare to our dll name! |
| 327 if (::wcsstr(name, hook_dll)) { |
| 328 // Found it. |
| 329 dll_loaded = TRUE; |
| 330 break; |
| 331 } |
| 332 } |
| 333 |
| 334 // Did we pass the test as expected? |
| 335 EXPECT_EQ((is_success_test ? TRUE : FALSE), dll_loaded); |
| 336 |
| 337 // 4. Trigger shutdown of WinProc. |
| 338 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { |
| 339 ::WaitForSingleObject(event, event_max_wait_ms); |
| 340 EXPECT_TRUE(::CloseHandle(event)); |
| 341 } else { |
| 342 // Make sure we don't leave a stray. |
| 343 ::TerminateProcess(proc_info.hProcess, 0); |
| 344 EXPECT_TRUE(false); |
| 345 } |
| 346 EXPECT_TRUE(::CloseHandle(proc_info.hThread)); |
| 347 EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); |
| 348 |
| 349 // 5. Reg Restore |
| 350 EXPECT_EQ(ERROR_SUCCESS, |
| 351 app_init_key.WriteValue(enabled_value_name, orig_enabled_value)); |
| 352 if (app_init_key.HasValue(signing_value_name)) |
| 353 EXPECT_EQ(ERROR_SUCCESS, |
| 354 app_init_key.WriteValue(signing_value_name, orig_signing_value)); |
| 355 EXPECT_EQ(ERROR_SUCCESS, |
| 356 app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str())); |
| 357 app_init_key.Close(); |
| 358 } |
| 359 |
109 void TestWin10ImageLoadRemote(bool is_success_test) { | 360 void TestWin10ImageLoadRemote(bool is_success_test) { |
110 // ***Insert your manual testing share UNC path here! | 361 // ***Insert your manual testing share UNC path here! |
111 // E.g.: \\\\hostname\\sharename\\calc.exe | 362 // E.g.: \\\\hostname\\sharename\\calc.exe |
112 std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; | 363 std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; |
113 | 364 |
114 sandbox::TestRunner runner; | 365 sandbox::TestRunner runner; |
115 sandbox::TargetPolicy* policy = runner.GetPolicy(); | 366 sandbox::TargetPolicy* policy = runner.GetPolicy(); |
116 | 367 |
117 // Set a policy that would normally allow for process creation. | 368 // Set a policy that would normally allow for process creation. |
118 policy->SetJobLevel(sandbox::JOB_NONE, 0); | 369 policy->SetJobLevel(sandbox::JOB_NONE, 0); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 setup_proc.Terminate(0, false); | 475 setup_proc.Terminate(0, false); |
225 return SBOX_TEST_SUCCEEDED; | 476 return SBOX_TEST_SUCCEEDED; |
226 } | 477 } |
227 // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED". | 478 // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED". |
228 return SBOX_TEST_FAILED; | 479 return SBOX_TEST_FAILED; |
229 } | 480 } |
230 | 481 |
231 //------------------------------------------------------------------------------ | 482 //------------------------------------------------------------------------------ |
232 // Win8 Checks: | 483 // Win8 Checks: |
233 // MITIGATION_DEP(_NO_ATL_THUNK) | 484 // MITIGATION_DEP(_NO_ATL_THUNK) |
234 // MITIGATION_EXTENSION_DLL_DISABLE | |
235 // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only | 485 // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only |
236 // MITIGATION_STRICT_HANDLE_CHECKS | 486 // MITIGATION_STRICT_HANDLE_CHECKS |
237 // >= Win8 | 487 // >= Win8 |
238 //------------------------------------------------------------------------------ | 488 //------------------------------------------------------------------------------ |
239 | 489 |
240 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { | 490 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { |
241 get_process_mitigation_policy = | 491 get_process_mitigation_policy = |
242 reinterpret_cast<GetProcessMitigationPolicyFunction>( | 492 reinterpret_cast<GetProcessMitigationPolicyFunction>( |
243 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), | 493 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), |
244 "GetProcessMitigationPolicy")); | 494 "GetProcessMitigationPolicy")); |
245 if (!get_process_mitigation_policy) | 495 if (!get_process_mitigation_policy) |
246 return SBOX_TEST_NOT_FOUND; | 496 return SBOX_TEST_NOT_FOUND; |
247 | 497 |
248 #if !defined(_WIN64) // DEP is always enabled on 64-bit. | 498 #if !defined(_WIN64) // DEP is always enabled on 64-bit. |
249 if (!CheckWin8DepPolicy()) | 499 if (!CheckWin8DepPolicy()) |
250 return SBOX_TEST_FIRST_ERROR; | 500 return SBOX_TEST_FIRST_ERROR; |
251 #endif | 501 #endif |
252 | 502 |
253 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. | 503 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. |
254 if (!CheckWin8AslrPolicy()) | 504 if (!CheckWin8AslrPolicy()) |
255 return SBOX_TEST_SECOND_ERROR; | 505 return SBOX_TEST_SECOND_ERROR; |
256 #endif | 506 #endif |
257 | 507 |
258 if (!CheckWin8StrictHandlePolicy()) | 508 if (!CheckWin8StrictHandlePolicy()) |
259 return SBOX_TEST_THIRD_ERROR; | 509 return SBOX_TEST_THIRD_ERROR; |
260 | 510 |
261 if (!CheckWin8DllExtensionPolicy()) | |
262 return SBOX_TEST_FIFTH_ERROR; | |
263 | |
264 return SBOX_TEST_SUCCEEDED; | 511 return SBOX_TEST_SUCCEEDED; |
265 } | 512 } |
266 | 513 |
267 TEST(ProcessMitigationsTest, CheckWin8) { | 514 TEST(ProcessMitigationsTest, CheckWin8) { |
268 if (base::win::GetVersion() < base::win::VERSION_WIN8) | 515 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
269 return; | 516 return; |
270 | 517 |
271 TestRunner runner; | 518 TestRunner runner; |
272 sandbox::TargetPolicy* policy = runner.GetPolicy(); | 519 sandbox::TargetPolicy* policy = runner.GetPolicy(); |
273 | 520 |
274 sandbox::MitigationFlags mitigations = MITIGATION_DEP | | 521 sandbox::MitigationFlags mitigations = |
275 MITIGATION_DEP_NO_ATL_THUNK | | 522 MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK; |
276 MITIGATION_EXTENSION_DLL_DISABLE; | |
277 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. | 523 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. |
278 mitigations |= MITIGATION_RELOCATE_IMAGE | | 524 mitigations |= MITIGATION_RELOCATE_IMAGE | |
279 MITIGATION_RELOCATE_IMAGE_REQUIRED; | 525 MITIGATION_RELOCATE_IMAGE_REQUIRED; |
280 #endif | 526 #endif |
281 | 527 |
282 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); | 528 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); |
283 | 529 |
284 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; | 530 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; |
285 | 531 |
286 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); | 532 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 | 647 |
402 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), | 648 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), |
403 SBOX_ALL_OK); | 649 SBOX_ALL_OK); |
404 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, | 650 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, |
405 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), | 651 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), |
406 sandbox::SBOX_ALL_OK); | 652 sandbox::SBOX_ALL_OK); |
407 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); | 653 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); |
408 } | 654 } |
409 | 655 |
410 //------------------------------------------------------------------------------ | 656 //------------------------------------------------------------------------------ |
| 657 // Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE). |
| 658 // >= Win8 |
| 659 //------------------------------------------------------------------------------ |
| 660 |
| 661 wchar_t* extension_point_mutex = L"ChromeExtensionTestMutex"; |
| 662 DWORD mutex_max_wait_ms = 10 * 1000; |
| 663 |
| 664 SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(int argc, |
| 665 wchar_t** argv) { |
| 666 get_process_mitigation_policy = |
| 667 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
| 668 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
| 669 if (!get_process_mitigation_policy) |
| 670 return SBOX_TEST_NOT_FOUND; |
| 671 |
| 672 if (!CheckWin8ExtensionPointPolicy()) |
| 673 return SBOX_TEST_FIRST_ERROR; |
| 674 return SBOX_TEST_SUCCEEDED; |
| 675 } |
| 676 |
| 677 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
| 678 // mitigation enables the setting on a process. |
| 679 TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) { |
| 680 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 681 return; |
| 682 |
| 683 TestRunner runner; |
| 684 sandbox::TargetPolicy* policy = runner.GetPolicy(); |
| 685 |
| 686 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE), |
| 687 SBOX_ALL_OK); |
| 688 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 689 runner.RunTest(L"CheckWin8ExtensionPointSetting")); |
| 690 } |
| 691 |
| 692 // This test validates that we CAN add a "legitimate" global hook on the |
| 693 // sandboxed |
| 694 // proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. |
| 695 // |
| 696 // MANUAL testing only. |
| 697 TEST(ProcessMitigationsTest, |
| 698 MANUAL_CheckWin8ExtensionPoint_GlobalHook_Success) { |
| 699 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 700 return; |
| 701 |
| 702 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 703 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 704 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 705 |
| 706 // (is_success_test, global_hook) |
| 707 TestWin8ExtensionPointHookWrapper(true, true); |
| 708 |
| 709 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 710 EXPECT_TRUE(::CloseHandle(mutex)); |
| 711 } |
| 712 |
| 713 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
| 714 // mitigation prevents a global hook in our WinProc. |
| 715 // |
| 716 // MANUAL testing only. |
| 717 TEST(ProcessMitigationsTest, |
| 718 MANUAL_CheckWin8ExtensionPoint_GlobalHook_Failure) { |
| 719 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 720 return; |
| 721 |
| 722 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 723 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 724 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 725 |
| 726 // (is_success_test, global_hook) |
| 727 TestWin8ExtensionPointHookWrapper(false, true); |
| 728 |
| 729 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 730 EXPECT_TRUE(::CloseHandle(mutex)); |
| 731 } |
| 732 |
| 733 // This test validates that we CAN add a "legitimate" hook on the sandboxed |
| 734 // proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. |
| 735 // |
| 736 // MANUAL testing only. |
| 737 TEST(ProcessMitigationsTest, MANUAL_CheckWin8ExtensionPoint_Hook_Success) { |
| 738 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 739 return; |
| 740 |
| 741 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 742 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 743 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 744 |
| 745 // (is_success_test, global_hook) |
| 746 TestWin8ExtensionPointHookWrapper(true, false); |
| 747 |
| 748 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 749 EXPECT_TRUE(::CloseHandle(mutex)); |
| 750 } |
| 751 |
| 752 // *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent |
| 753 // hooks targetted at a specific thread id. It only prevents |
| 754 // global hooks. So this test does NOT actually expect the hook |
| 755 // to fail (see TestWin8ExtensionPointHookWrapper function) even |
| 756 // with the mitigation on. |
| 757 // |
| 758 // MANUAL testing only. |
| 759 TEST(ProcessMitigationsTest, MANUAL_CheckWin8ExtensionPoint_Hook_Failure) { |
| 760 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 761 return; |
| 762 |
| 763 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 764 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 765 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 766 |
| 767 // (is_success_test, global_hook) |
| 768 TestWin8ExtensionPointHookWrapper(false, false); |
| 769 |
| 770 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 771 EXPECT_TRUE(::CloseHandle(mutex)); |
| 772 } |
| 773 |
| 774 // This test validates that we CAN add an AppInit Dll to a target |
| 775 // WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. |
| 776 // |
| 777 // MANUAL testing only. |
| 778 // Must run this test as admin/elevated. |
| 779 TEST(ProcessMitigationsTest, MANUAL_CheckWin8ExtensionPoint_AppInit_Success) { |
| 780 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 781 return; |
| 782 |
| 783 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 784 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 785 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 786 |
| 787 TestWin8ExtensionPointAppInitWrapper(true); |
| 788 |
| 789 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 790 EXPECT_TRUE(::CloseHandle(mutex)); |
| 791 } |
| 792 |
| 793 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
| 794 // mitigation prevents the loading of any AppInit Dll into our WinProc. |
| 795 // |
| 796 // MANUAL testing only. |
| 797 // Must run this test as admin/elevated. |
| 798 TEST(ProcessMitigationsTest, MANUAL_CheckWin8ExtensionPoint_AppInit_Failure) { |
| 799 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 800 return; |
| 801 |
| 802 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); |
| 803 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
| 804 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); |
| 805 |
| 806 TestWin8ExtensionPointAppInitWrapper(false); |
| 807 |
| 808 EXPECT_TRUE(::ReleaseMutex(mutex)); |
| 809 EXPECT_TRUE(::CloseHandle(mutex)); |
| 810 } |
| 811 |
| 812 //------------------------------------------------------------------------------ |
411 // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) | 813 // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) |
412 // >= Win10 | 814 // >= Win10 |
413 //------------------------------------------------------------------------------ | 815 //------------------------------------------------------------------------------ |
414 | 816 |
415 SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) { | 817 SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) { |
416 get_process_mitigation_policy = | 818 get_process_mitigation_policy = |
417 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( | 819 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
418 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); | 820 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
419 if (!get_process_mitigation_policy) | 821 if (!get_process_mitigation_policy) |
420 return SBOX_TEST_NOT_FOUND; | 822 return SBOX_TEST_NOT_FOUND; |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), | 967 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), |
566 SBOX_ALL_OK); | 968 SBOX_ALL_OK); |
567 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | 969 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
568 runner.RunTest(L"CheckWin10ImageLoadNoRemote")); | 970 runner.RunTest(L"CheckWin10ImageLoadNoRemote")); |
569 } | 971 } |
570 | 972 |
571 // This test validates that we CAN create a new process from | 973 // This test validates that we CAN create a new process from |
572 // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE | 974 // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE |
573 // mitigation is NOT set. | 975 // mitigation is NOT set. |
574 // | 976 // |
575 // DISABLED for automated testing bots. Enable for manual testing. | 977 // MANUAL testing only. |
576 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { | 978 TEST(ProcessMitigationsTest, MANUAL_CheckWin10ImageLoadNoRemoteSuccess) { |
577 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) | 979 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
578 return; | 980 return; |
579 | 981 |
580 TestWin10ImageLoadRemote(true); | 982 TestWin10ImageLoadRemote(true); |
581 } | 983 } |
582 | 984 |
583 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE | 985 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
584 // mitigation prevents creating a new process from a remote | 986 // mitigation prevents creating a new process from a remote |
585 // UNC device. | 987 // UNC device. |
586 // | 988 // |
587 // DISABLED for automated testing bots. Enable for manual testing. | 989 // MANUAL testing only. |
588 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { | 990 TEST(ProcessMitigationsTest, MANUAL_CheckWin10ImageLoadNoRemoteFailure) { |
589 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) | 991 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
590 return; | 992 return; |
591 | 993 |
592 TestWin10ImageLoadRemote(false); | 994 TestWin10ImageLoadRemote(false); |
593 } | 995 } |
594 | 996 |
595 //------------------------------------------------------------------------------ | 997 //------------------------------------------------------------------------------ |
596 // Disable image load when "mandatory low label" (integrity level). | 998 // Disable image load when "mandatory low label" (integrity level). |
597 // (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) | 999 // (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) |
598 // >= Win10_TH2 | 1000 // >= Win10_TH2 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 cmd = cmd.Append(L"calc.exe"); | 1096 cmd = cmd.Append(L"calc.exe"); |
695 | 1097 |
696 std::wstring test_command = L"TestChildProcess "; | 1098 std::wstring test_command = L"TestChildProcess "; |
697 test_command += cmd.value().c_str(); | 1099 test_command += cmd.value().c_str(); |
698 | 1100 |
699 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); | 1101 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); |
700 } | 1102 } |
701 | 1103 |
702 } // namespace sandbox | 1104 } // namespace sandbox |
703 | 1105 |
OLD | NEW |