OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome_elf/blacklist/blacklist.h" | 5 #include "chrome_elf/blacklist/blacklist.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "chrome_elf/blacklist/blacklist_interceptions.h" | 10 #include "chrome_elf/blacklist/blacklist_interceptions.h" |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 sizeof(blacklist_state)); | 155 sizeof(blacklist_state)); |
156 ::RegCloseKey(*key); | 156 ::RegCloseKey(*key); |
157 key = NULL; | 157 key = NULL; |
158 } | 158 } |
159 } | 159 } |
160 | 160 |
161 } // namespace | 161 } // namespace |
162 | 162 |
163 namespace blacklist { | 163 namespace blacklist { |
164 | 164 |
| 165 #if defined(_WIN64) |
| 166 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. |
| 167 #pragma section(".oldntmap",write,read) |
| 168 __declspec(allocate(".oldntmap")) |
| 169 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; |
| 170 #endif |
| 171 |
165 bool LeaveSetupBeacon() { | 172 bool LeaveSetupBeacon() { |
166 HKEY key = NULL; | 173 HKEY key = NULL; |
167 DWORD disposition = 0; | 174 DWORD disposition = 0; |
168 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, | 175 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, |
169 kRegistryBeaconPath, | 176 kRegistryBeaconPath, |
170 0, | 177 0, |
171 NULL, | 178 NULL, |
172 REG_OPTION_NON_VOLATILE, | 179 REG_OPTION_NON_VOLATILE, |
173 KEY_QUERY_VALUE | KEY_SET_VALUE, | 180 KEY_QUERY_VALUE | KEY_SET_VALUE, |
174 NULL, | 181 NULL, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 delete[] g_troublesome_dlls[i]; | 293 delete[] g_troublesome_dlls[i]; |
287 g_troublesome_dlls[i] = g_troublesome_dlls[blacklist_size - 1]; | 294 g_troublesome_dlls[i] = g_troublesome_dlls[blacklist_size - 1]; |
288 g_troublesome_dlls[blacklist_size - 1] = NULL; | 295 g_troublesome_dlls[blacklist_size - 1] = NULL; |
289 return true; | 296 return true; |
290 } | 297 } |
291 } | 298 } |
292 return false; | 299 return false; |
293 } | 300 } |
294 | 301 |
295 bool Initialize(bool force) { | 302 bool Initialize(bool force) { |
296 #if defined(_WIN64) | |
297 // TODO(robertshield): Implement 64-bit support by providing 64-bit | |
298 // interceptors. | |
299 return false; | |
300 #endif | |
301 | |
302 // Check to see that we found the functions we need in ntdll. | 303 // Check to see that we found the functions we need in ntdll. |
303 if (!InitializeInterceptImports()) | 304 if (!InitializeInterceptImports()) |
304 return false; | 305 return false; |
305 | 306 |
306 // Check to see if this is a non-browser process, abort if so. | 307 // Check to see if this is a non-browser process, abort if so. |
307 if (IsNonBrowserProcess()) | 308 if (IsNonBrowserProcess()) |
308 return false; | 309 return false; |
309 | 310 |
310 // Check to see if a beacon is present, abort if so. | 311 // Check to see if a beacon is present, abort if so. |
311 if (!force && !LeaveSetupBeacon()) | 312 if (!force && !LeaveSetupBeacon()) |
(...skipping 28 matching lines...) Expand all Loading... |
340 kBeaconState, | 341 kBeaconState, |
341 0, | 342 0, |
342 REG_DWORD, | 343 REG_DWORD, |
343 reinterpret_cast<LPBYTE>(&blacklist_state), | 344 reinterpret_cast<LPBYTE>(&blacklist_state), |
344 sizeof(blacklist_state)); | 345 sizeof(blacklist_state)); |
345 } else { | 346 } else { |
346 key = NULL; | 347 key = NULL; |
347 } | 348 } |
348 | 349 |
349 // Create a thunk via the appropriate ServiceResolver instance. | 350 // Create a thunk via the appropriate ServiceResolver instance. |
350 sandbox::ServiceResolverThunk* thunk; | 351 sandbox::ServiceResolverThunk* thunk = NULL; |
351 #if defined(_WIN64) | 352 #if defined(_WIN64) |
352 // TODO(robertshield): Use the appropriate thunk for 64-bit support | 353 // Because Windows 8 and 8.1 have different stubs in 64-bit, |
353 // when said support is implemented. | 354 // ServiceResolverThunk can handle all the formats in 64-bit (instead only |
| 355 // handling 1 like it does in 32-bit versions). |
| 356 thunk = new sandbox::ServiceResolverThunk(current_process, kRelaxed); |
354 #else | 357 #else |
355 if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { | 358 if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { |
356 if (os_info.version() >= VERSION_WIN8) | 359 if (os_info.version() >= VERSION_WIN8) |
357 thunk = new sandbox::Wow64W8ResolverThunk(current_process, kRelaxed); | 360 thunk = new sandbox::Wow64W8ResolverThunk(current_process, kRelaxed); |
358 else | 361 else |
359 thunk = new sandbox::Wow64ResolverThunk(current_process, kRelaxed); | 362 thunk = new sandbox::Wow64ResolverThunk(current_process, kRelaxed); |
360 } else if (os_info.version() >= VERSION_WIN8) { | 363 } else if (os_info.version() >= VERSION_WIN8) { |
361 thunk = new sandbox::Win8ResolverThunk(current_process, kRelaxed); | 364 thunk = new sandbox::Win8ResolverThunk(current_process, kRelaxed); |
362 } else { | 365 } else { |
363 thunk = new sandbox::ServiceResolverThunk(current_process, kRelaxed); | 366 thunk = new sandbox::ServiceResolverThunk(current_process, kRelaxed); |
364 } | 367 } |
365 #endif | 368 #endif |
366 | 369 |
367 BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage); | 370 BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage); |
368 | 371 |
369 // Mark the thunk storage as readable and writeable, since we | 372 // Mark the thunk storage as readable and writeable, since we |
370 // ready to write to it. | 373 // ready to write to it. |
371 DWORD old_protect = 0; | 374 DWORD old_protect = 0; |
372 if (!VirtualProtect(&g_thunk_storage, | 375 if (!VirtualProtect(&g_thunk_storage, |
373 sizeof(g_thunk_storage), | 376 sizeof(g_thunk_storage), |
374 PAGE_EXECUTE_READWRITE, | 377 PAGE_EXECUTE_READWRITE, |
375 &old_protect)) { | 378 &old_protect)) { |
376 RecordSuccessfulThunkSetup(&key); | 379 RecordSuccessfulThunkSetup(&key); |
377 return false; | 380 return false; |
378 } | 381 } |
379 | 382 |
380 thunk->AllowLocalPatches(); | 383 thunk->AllowLocalPatches(); |
381 | 384 |
382 // Get ntdll base, target name, interceptor address, | 385 // We declare this early so it can be used in the 64-bit block below and |
| 386 // still work on 32-bit build when referenced at the end of the function. |
| 387 BOOL page_executable = false; |
| 388 |
| 389 // Replace the default NtMapViewOfSection with our patched version. |
| 390 #if defined(_WIN64) |
| 391 NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), |
| 392 reinterpret_cast<void*>(&__ImageBase), |
| 393 "NtMapViewOfSection", |
| 394 NULL, |
| 395 &blacklist::BlNtMapViewOfSection64, |
| 396 thunk_storage, |
| 397 sizeof(sandbox::ThunkData), |
| 398 NULL); |
| 399 |
| 400 // Keep a pointer to the original code, we don't have enough space to |
| 401 // add it directly to the call. |
| 402 g_nt_map_view_of_section_func = reinterpret_cast<NtMapViewOfSectionFunction>( |
| 403 thunk_storage); |
| 404 |
| 405 // Ensure that the pointer to the old function can't be changed. |
| 406 page_executable = VirtualProtect(&g_nt_map_view_of_section_func, |
| 407 sizeof(g_nt_map_view_of_section_func), |
| 408 PAGE_EXECUTE_READ, |
| 409 &old_protect); |
| 410 #else |
383 NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), | 411 NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), |
384 reinterpret_cast<void*>(&__ImageBase), | 412 reinterpret_cast<void*>(&__ImageBase), |
385 "NtMapViewOfSection", | 413 "NtMapViewOfSection", |
386 NULL, | 414 NULL, |
387 &blacklist::BlNtMapViewOfSection, | 415 &blacklist::BlNtMapViewOfSection, |
388 thunk_storage, | 416 thunk_storage, |
389 sizeof(sandbox::ThunkData), | 417 sizeof(sandbox::ThunkData), |
390 NULL); | 418 NULL); |
391 | 419 #endif |
392 delete thunk; | 420 delete thunk; |
393 | 421 |
394 // Mark the thunk storage as executable and prevent any future writes to it. | 422 // Mark the thunk storage as executable and prevent any future writes to it. |
395 BOOL page_executable = VirtualProtect(&g_thunk_storage, | 423 page_executable = page_executable && VirtualProtect(&g_thunk_storage, |
396 sizeof(g_thunk_storage), | 424 sizeof(g_thunk_storage), |
397 PAGE_EXECUTE_READ, | 425 PAGE_EXECUTE_READ, |
398 &old_protect); | 426 &old_protect); |
399 | 427 |
400 RecordSuccessfulThunkSetup(&key); | 428 RecordSuccessfulThunkSetup(&key); |
401 | 429 |
402 return NT_SUCCESS(ret) && page_executable; | 430 return NT_SUCCESS(ret) && page_executable; |
403 } | 431 } |
404 | 432 |
405 } // namespace blacklist | 433 } // namespace blacklist |
OLD | NEW |