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