15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/service_resolver.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/win_utils.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma pack(push, 1) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kMovEax = 0xB8; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kMovEdx = 0xBA; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kMovEdxEsp = 0xD48B; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kCallPtrEdx = 0x12FF; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kCallEdx = 0xD2FF; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kCallEip = 0xE8; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kRet = 0xC2; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kRet2 = 0xC3; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kNop = 0x90; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kJmpEdx = 0xE2FF; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kXorEcx = 0xC933; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG kLeaEdx = 0x0424548D; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG kCallFs1 = 0xC015FF64; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kCallFs2 = 0; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kCallFs3 = 0; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kAddEsp1 = 0x83; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kAddEsp2 = 0x4C4; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kJmp32 = 0xE9; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kSysenter = 0x340F; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxService = 1000; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for 32 bit systems. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: on win2003 "call dword ptr [edx]" is "call edx". 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceEntry { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This struct contains roughly the following code: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 00 mov eax,25h 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 05 mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0a call dword ptr [edx] 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0c ret 2Ch 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0f nop 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE mov_eax; // = B8 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG service_id; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE mov_edx; // = BA 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG stub; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT call_ptr_edx; // = FF 12 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE ret; // = C2 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT num_params; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE nop; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for 32 bit Windows 8. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceEntryW8 { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This struct contains the following code: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 00 b825000000 mov eax,25h 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 05 e803000000 call eip+3 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0a c22c00 ret 2Ch 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0d 8bd4 mov edx,esp 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0f 0f34 sysenter 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 11 c3 ret 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 12 8bff mov edi,edi 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE mov_eax; // = B8 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG service_id; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE call_eip; // = E8 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG call_offset; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE ret_p; // = C2 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT num_params; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT mov_edx_esp; // = BD D4 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT sysenter; // = 0F 34 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE ret; // = C3 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT nop; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for a 32 bit process running on a 64 bit os. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Wow64Entry { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This struct may contain one of two versions of code: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. For XP, Vista and 2K3: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 00 b825000000 mov eax, 25h 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 05 33c9 xor ecx, ecx 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 07 8d542404 lea edx, [esp + 4] 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0b 64ff15c0000000 call dword ptr fs:[0C0h] 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 12 c22c00 ret 2Ch 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. For Windows 7: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 00 b825000000 mov eax, 25h 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 05 33c9 xor ecx, ecx 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 07 8d542404 lea edx, [esp + 4] 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0b 64ff15c0000000 call dword ptr fs:[0C0h] 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 12 83c404 add esp, 4 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 15 c22c00 ret 2Ch 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So we base the structure on the bigger one: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE mov_eax; // = B8 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG service_id; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT xor_ecx; // = 33 C9 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG lea_edx; // = 8D 54 24 04 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG call_fs1; // = 64 FF 15 C0 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT call_fs2; // = 00 00 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE call_fs3; // = 00 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE add_esp1; // = 83 or ret 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT add_esp2; // = C4 04 or num_params 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE ret; // = C2 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT num_params; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for a 32 bit process running on 64 bit Windows 8. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Wow64EntryW8 { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 00 b825000000 mov eax, 25h 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 05 64ff15c0000000 call dword ptr fs:[0C0h] 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0b c22c00 ret 2Ch 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0f 90 nop 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE mov_eax; // = B8 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG service_id; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG call_fs1; // = 64 FF 15 C0 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT call_fs2; // = 00 00 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE call_fs3; // = 00 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE ret; // = C2 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USHORT num_params; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE nop; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that relaxed patching works as expected. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMinServiceSize = offsetof(ServiceEntry, ret); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(ServiceEntryW8) >= kMinServiceSize, wrong_service_len); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(Wow64Entry) >= kMinServiceSize, wrong_service_len); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(Wow64EntryW8) >= kMinServiceSize, wrong_service_len); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceFullThunk { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) union { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntry original; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntryW8 original_w8; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Wow64Entry wow_64; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Wow64EntryW8 wow_64_w8; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int internal_thunk; // Dummy member to the beginning of the internal thunk. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma pack(pop) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS ServiceResolverThunk::Setup(const void* target_module, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* interceptor_module, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* target_name, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* interceptor_name, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* interceptor_entry_point, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* thunk_storage, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t storage_bytes, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* storage_used) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NTSTATUS ret = Init(target_module, interceptor_module, target_name, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interceptor_name, interceptor_entry_point, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk_storage, storage_bytes); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!NT_SUCCESS(ret)) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relative_jump_ = 0; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t thunk_bytes = GetThunkSize(); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<char[]> thunk_buffer(new char[thunk_bytes]); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>( 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk_buffer.get()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsFunctionAService(&thunk->original) && 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!relaxed_ || !SaveOriginalFunction(&thunk->original, thunk_storage))) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_UNSUCCESSFUL; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = PerformPatch(thunk, thunk_storage); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != storage_used) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *storage_used = thunk_bytes; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ServiceResolverThunk::GetThunkSize() const { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return offsetof(ServiceFullThunk, internal_thunk) + GetInternalThunkSize(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module, 18323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const char* target_name, 18423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BYTE* thunk_storage, 18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t storage_bytes, 18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t* storage_used) { 18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) NTSTATUS ret = ResolveTarget(target_module, target_name, &target_); 18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!NT_SUCCESS(ret)) 18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return ret; 19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t thunk_bytes = GetThunkSize(); 19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (storage_bytes < thunk_bytes) 19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return STATUS_UNSUCCESSFUL; 19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(thunk_storage); 19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!IsFunctionAService(&thunk->original) && 19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (!relaxed_ || !SaveOriginalFunction(&thunk->original, thunk_storage))) { 19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return STATUS_UNSUCCESSFUL; 20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (NULL != storage_used) 20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *storage_used = thunk_bytes; 20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return ret; 20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntry function_code; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T read; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, target_, &function_code, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(function_code), &read)) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(function_code) != read) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kMovEax != function_code.mov_eax || 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMovEdx != function_code.mov_edx || 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kCallPtrEdx != function_code.call_ptr_edx && 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCallEdx != function_code.call_ptr_edx) || 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kRet != function_code.ret) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the system call pointer if we don't already have it. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kCallEdx != function_code.call_ptr_edx) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ki_system_call; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bit_cast<const void*>(function_code.stub), 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ki_system_call, sizeof(ki_system_call), &read)) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(ki_system_call) != read) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE module_1, module_2; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last check, call_stub should point to a KiXXSystemCall function on ntdll 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bit_cast<const wchar_t*>(ki_system_call), &module_1)) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != ntdll_base_) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This path is only taken when running the unit tests. We want to be 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // able to patch a buffer in memory, so target_ is not inside ntdll. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) module_2 = ntdll_base_; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const wchar_t*>(target_), 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &module_2)) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (module_1 != module_2) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the verified code 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(local_thunk, &function_code, sizeof(function_code)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* remote_thunk) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntry intercepted_code; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_write = sizeof(intercepted_code); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceFullThunk *full_local_thunk = reinterpret_cast<ServiceFullThunk*>( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_thunk); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceFullThunk *full_remote_thunk = reinterpret_cast<ServiceFullThunk*>( 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_thunk); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // patch the original code 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&intercepted_code, &full_local_thunk->original, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(intercepted_code)); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.mov_eax = kMovEax; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.service_id = full_local_thunk->original.service_id; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.mov_edx = kMovEdx; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.stub = bit_cast<ULONG>(&full_remote_thunk->internal_thunk); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.call_ptr_edx = kJmpEdx; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write = kMinServiceSize; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (relative_jump_) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.mov_eax = kJmp32; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intercepted_code.service_id = relative_jump_; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write = offsetof(ServiceEntry, mov_edx); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // setup the thunk 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetInternalThunk(&full_local_thunk->internal_thunk, GetInternalThunkSize(), 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_thunk, interceptor_); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t thunk_size = GetThunkSize(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // copy the local thunk buffer to the child 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T written; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk_size, &written)) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_UNSUCCESSFUL; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thunk_size != written) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_UNSUCCESSFUL; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and now change the function to intercept, on the child 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != ntdll_base_) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // running a unit test 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::WriteProcessMemory(process_, target_, &intercepted_code, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write, &written)) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_UNSUCCESSFUL; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WriteProtectedChildMemory(process_, target_, &intercepted_code, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_write)) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_UNSUCCESSFUL; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STATUS_SUCCESS; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceResolverThunk::SaveOriginalFunction(void* local_thunk, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* remote_thunk) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntry function_code; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T read; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, target_, &function_code, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(function_code), &read)) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(function_code) != read) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kJmp32 == function_code.mov_eax) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Plain old entry point patch. The relative jump address follows it. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG relative = function_code.service_id; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, fix our copy of their patch. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relative += bit_cast<ULONG>(target_) - bit_cast<ULONG>(remote_thunk); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_code.service_id = relative; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And now, remember how to re-patch it. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceFullThunk *full_thunk = 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ServiceFullThunk*>(remote_thunk); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ULONG kJmp32Size = 5; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relative_jump_ = bit_cast<ULONG>(&full_thunk->internal_thunk) - 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bit_cast<ULONG>(target_) - kJmp32Size; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the verified code 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(local_thunk, &function_code, sizeof(function_code)); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Wow64Entry function_code; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T read; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, target_, &function_code, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(function_code), &read)) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(function_code) != read) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCallFs2 != function_code.call_fs2 || kCallFs3 != function_code.call_fs3) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((kAddEsp1 == function_code.add_esp1 && 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAddEsp2 == function_code.add_esp2 && 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kRet == function_code.ret) || kRet == function_code.add_esp1) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the verified code 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(local_thunk, &function_code, sizeof(function_code)); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Wow64W8ResolverThunk::IsFunctionAService(void* local_thunk) const { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Wow64EntryW8 function_code; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T read; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, target_, &function_code, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(function_code), &read)) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(function_code) != read) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kMovEax != function_code.mov_eax || kCallFs1 != function_code.call_fs1 || 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCallFs2 != function_code.call_fs2 || 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCallFs3 != function_code.call_fs3 || kRet != function_code.ret) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the verified code 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(local_thunk, &function_code, sizeof(function_code)); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Win8ResolverThunk::IsFunctionAService(void* local_thunk) const { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceEntryW8 function_code; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T read; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ReadProcessMemory(process_, target_, &function_code, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(function_code), &read)) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sizeof(function_code) != read) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kMovEax != function_code.mov_eax || kCallEip != function_code.call_eip || 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_code.call_offset != 3 || kRet != function_code.ret_p || 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMovEdxEsp != function_code.mov_edx_esp || 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSysenter != function_code.sysenter || kRet2 != function_code.ret) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the verified code 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(local_thunk, &function_code, sizeof(function_code)); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace sandbox 427