| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/src/service_resolver.h" | 5 #include "sandbox/src/service_resolver.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/scoped_ptr.h" | 8 #include "base/scoped_ptr.h" |
| 9 #include "sandbox/src/pe_image.h" | 9 #include "sandbox/src/pe_image.h" |
| 10 #include "sandbox/src/sandbox_types.h" | 10 #include "sandbox/src/sandbox_types.h" |
| 11 #include "sandbox/src/sandbox_utils.h" | 11 #include "sandbox/src/sandbox_utils.h" |
| 12 | 12 |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 #pragma pack(push, 1) | 15 #pragma pack(push, 1) |
| 16 | 16 |
| 17 const BYTE kMovEax = 0xB8; | 17 const BYTE kMovEax = 0xB8; |
| 18 const BYTE kMovEdx = 0xBA; | 18 const BYTE kMovEdx = 0xBA; |
| 19 const USHORT kCallPtrEdx = 0x12FF; | 19 const USHORT kCallPtrEdx = 0x12FF; |
| 20 const USHORT kCallEdx = 0xD2FF; | 20 const USHORT kCallEdx = 0xD2FF; |
| 21 const BYTE kRet = 0xC2; | 21 const BYTE kRet = 0xC2; |
| 22 const BYTE kNop = 0x90; | 22 const BYTE kNop = 0x90; |
| 23 const USHORT kJmpEdx = 0xE2FF; | 23 const USHORT kJmpEdx = 0xE2FF; |
| 24 const USHORT kXorEcx = 0xC933; | 24 const USHORT kXorEcx = 0xC933; |
| 25 const ULONG kLeaEdx = 0x0424548D; | 25 const ULONG kLeaEdx = 0x0424548D; |
| 26 const ULONG kCallFs1 = 0xC015FF64; | 26 const ULONG kCallFs1 = 0xC015FF64; |
| 27 const ULONG kCallFs2Ret = 0xC2000000; | 27 const USHORT kCallFs2 = 0; |
| 28 const BYTE kCallFs3 = 0; |
| 29 const BYTE kAddEsp1 = 0x83; |
| 30 const USHORT kAddEsp2 = 0x4C4; |
| 28 const BYTE kJmp32 = 0xE9; | 31 const BYTE kJmp32 = 0xE9; |
| 29 | 32 |
| 30 const int kMaxService = 1000; | 33 const int kMaxService = 1000; |
| 31 | 34 |
| 32 // Service code for 32 bit systems. | 35 // Service code for 32 bit systems. |
| 33 // NOTE: on win2003 "call dword ptr [edx]" is "call edx". | 36 // NOTE: on win2003 "call dword ptr [edx]" is "call edx". |
| 34 struct ServiceEntry { | 37 struct ServiceEntry { |
| 35 // this struct contains roughly the following code: | 38 // this struct contains roughly the following code: |
| 36 // mov eax,25h | 39 // 00 mov eax,25h |
| 37 // mov edx,offset SharedUserData!SystemCallStub (7ffe0300) | 40 // 05 mov edx,offset SharedUserData!SystemCallStub (7ffe0300) |
| 38 // call dword ptr [edx] | 41 // 0a call dword ptr [edx] |
| 39 // ret 2Ch | 42 // 0c ret 2Ch |
| 40 // nop | 43 // 0f nop |
| 41 BYTE mov_eax; // = B8 | 44 BYTE mov_eax; // = B8 |
| 42 ULONG service_id; | 45 ULONG service_id; |
| 43 BYTE mov_edx; // = BA | 46 BYTE mov_edx; // = BA |
| 44 ULONG stub; | 47 ULONG stub; |
| 45 USHORT call_ptr_edx; // = FF 12 | 48 USHORT call_ptr_edx; // = FF 12 |
| 46 BYTE ret; // = C2 | 49 BYTE ret; // = C2 |
| 47 USHORT num_params; | 50 USHORT num_params; |
| 48 BYTE nop; | 51 BYTE nop; |
| 52 ULONG pad1; // Extend the structure to be the same size as the |
| 53 ULONG pad2; // 64 version (Wow64Entry) |
| 49 }; | 54 }; |
| 50 | 55 |
| 51 // Service code for a 32 bit process running on a 64 bit os. | 56 // Service code for a 32 bit process running on a 64 bit os. |
| 52 struct Wow64Entry { | 57 struct Wow64Entry { |
| 53 // this struct contains roughly the following code: | 58 // This struct may contain one of two versions of code: |
| 59 // 1. For XP, Vista and 2K3: |
| 54 // 00 b852000000 mov eax, 25h | 60 // 00 b852000000 mov eax, 25h |
| 55 // 05 33c9 xor ecx, ecx | 61 // 05 33c9 xor ecx, ecx |
| 56 // 07 8d542404 lea edx, [esp + 4] | 62 // 07 8d542404 lea edx, [esp + 4] |
| 57 // 0b 64ff15c0000000 call dword ptr fs:[0C0h] | 63 // 0b 64ff15c0000000 call dword ptr fs:[0C0h] |
| 58 // 12 c22c00 ret 2Ch | 64 // 12 c22c00 ret 2Ch |
| 65 // |
| 66 // 2. For Windows 7: |
| 67 // 00 b852000000 mov eax, 25h |
| 68 // 05 33c9 xor ecx, ecx |
| 69 // 07 8d542404 lea edx, [esp + 4] |
| 70 // 0b 64ff15c0000000 call dword ptr fs:[0C0h] |
| 71 // 12 83c404 add esp, 4 |
| 72 // 15 c22c00 ret 2Ch |
| 73 // |
| 74 // So we base the structure on the bigger one: |
| 59 BYTE mov_eax; // = B8 | 75 BYTE mov_eax; // = B8 |
| 60 ULONG service_id; | 76 ULONG service_id; |
| 61 USHORT xor_ecx; // = 33 C9 | 77 USHORT xor_ecx; // = 33 C9 |
| 62 ULONG lea_edx; // = 8D 54 24 04 | 78 ULONG lea_edx; // = 8D 54 24 04 |
| 63 ULONG call_fs1; // = 64 FF 15 C0 | 79 ULONG call_fs1; // = 64 FF 15 C0 |
| 64 ULONG call_fs2_ret; // = 00 00 00 C2 | 80 USHORT call_fs2; // = 00 00 |
| 81 BYTE call_fs3; // = 00 |
| 82 BYTE add_esp1; // = 83 or ret |
| 83 USHORT add_esp2; // = C4 04 or num_params |
| 84 BYTE ret; // = C2 |
| 65 USHORT num_params; | 85 USHORT num_params; |
| 66 }; | 86 }; |
| 67 | 87 |
| 88 // Make sure that relaxed patching works as expected. |
| 89 COMPILE_ASSERT(sizeof(ServiceEntry) == sizeof(Wow64Entry), wrong_service_len); |
| 90 |
| 68 struct ServiceFullThunk { | 91 struct ServiceFullThunk { |
| 69 union { | 92 union { |
| 70 ServiceEntry original; | 93 ServiceEntry original; |
| 71 Wow64Entry wow_64; | 94 Wow64Entry wow_64; |
| 72 }; | 95 }; |
| 73 int internal_thunk; // Dummy member to the beginning of the internal thunk. | 96 int internal_thunk; // Dummy member to the beginning of the internal thunk. |
| 74 }; | 97 }; |
| 75 | 98 |
| 76 #pragma pack(pop) | 99 #pragma pack(pop) |
| 77 | 100 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 DWORD read; | 353 DWORD read; |
| 331 if (!::ReadProcessMemory(process_, target_, &function_code, | 354 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 332 sizeof(function_code), &read)) | 355 sizeof(function_code), &read)) |
| 333 return false; | 356 return false; |
| 334 | 357 |
| 335 if (sizeof(function_code) != read) | 358 if (sizeof(function_code) != read) |
| 336 return false; | 359 return false; |
| 337 | 360 |
| 338 if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || | 361 if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || |
| 339 kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || | 362 kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || |
| 340 kCallFs2Ret != function_code.call_fs2_ret) | 363 kCallFs2 != function_code.call_fs2 || kCallFs3 != function_code.call_fs3) |
| 341 return false; | 364 return false; |
| 342 | 365 |
| 343 // Save the verified code | 366 if ((kAddEsp1 == function_code.add_esp1 && |
| 344 memcpy(local_thunk, &function_code, sizeof(function_code)); | 367 kAddEsp2 == function_code.add_esp2 && |
| 368 kRet == function_code.ret) || kRet == function_code.add_esp1) { |
| 369 // Save the verified code |
| 370 memcpy(local_thunk, &function_code, sizeof(function_code)); |
| 371 return true; |
| 372 } |
| 345 | 373 |
| 346 return true; | 374 return false; |
| 347 } | 375 } |
| 348 | 376 |
| 349 bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { | 377 bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { |
| 350 ServiceEntry function_code; | 378 ServiceEntry function_code; |
| 351 DWORD read; | 379 DWORD read; |
| 352 if (!::ReadProcessMemory(process_, target_, &function_code, | 380 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 353 sizeof(function_code), &read)) | 381 sizeof(function_code), &read)) |
| 354 return false; | 382 return false; |
| 355 | 383 |
| 356 if (sizeof(function_code) != read) | 384 if (sizeof(function_code) != read) |
| 357 return false; | 385 return false; |
| 358 | 386 |
| 359 if (kMovEax != function_code.mov_eax || | 387 if (kMovEax != function_code.mov_eax || |
| 360 function_code.service_id > kMaxService) | 388 function_code.service_id > kMaxService) |
| 361 return false; | 389 return false; |
| 362 | 390 |
| 363 // Save the verified code | 391 // Save the verified code |
| 364 memcpy(local_thunk, &function_code, sizeof(function_code)); | 392 memcpy(local_thunk, &function_code, sizeof(function_code)); |
| 365 | 393 |
| 366 return true; | 394 return true; |
| 367 } | 395 } |
| 368 | 396 |
| 369 } // namespace sandbox | 397 } // namespace sandbox |
| 370 | 398 |
| OLD | NEW |