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