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 3// found in the LICENSE file. 4 5// Wow_helper.exe is a simple Win32 64-bit executable designed to help to 6// sandbox a 32 bit application running on a 64 bit OS. The basic idea is to 7// perform a 64 bit interception of the target process and notify the 32-bit 8// broker process whenever a DLL is being loaded. This allows the broker to 9// setup the interceptions (32-bit) properly on the target. 10 11#include <windows.h> 12 13#include <string> 14 15#include "sandbox/win/wow_helper/service64_resolver.h" 16#include "sandbox/win/wow_helper/target_code.h" 17 18namespace sandbox { 19 20// Performs the interception of NtMapViewOfSection on the 64-bit version of 21// ntdll.dll. 'thunk' is the buffer on the address space of process 'child', 22// that will be used to store the information about the patch. 23int PatchNtdll(HANDLE child, void* thunk, size_t thunk_bytes) { 24 wchar_t* ntdll_name = L"ntdll.dll"; 25 HMODULE ntdll_base = ::GetModuleHandle(ntdll_name); 26 if (!ntdll_base) 27 return 100; 28 29 Service64ResolverThunk resolver(child); 30 size_t used = resolver.GetThunkSize(); 31 char* code = reinterpret_cast<char*>(thunk) + used; 32 NTSTATUS ret = resolver.Setup(ntdll_base, NULL, "NtMapViewOfSection", NULL, 33 code, thunk, thunk_bytes, NULL); 34 if (!NT_SUCCESS(ret)) 35 return 101; 36 37 size_t size = reinterpret_cast<char*>(&TargetEnd) - 38 reinterpret_cast<char*>(&TargetNtMapViewOfSection); 39 40 if (size + used > thunk_bytes) 41 return 102; 42 43 SIZE_T written; 44 if (!::WriteProcessMemory(child, code, &TargetNtMapViewOfSection, size, 45 &written)) 46 return 103; 47 48 if (size != written) 49 return 104; 50 51 return 0; 52} 53 54} // namespace sandbox 55 56// We must receive two arguments: the process id of the target to intercept and 57// the address of a page of memory on that process that will be used for the 58// interception. We receive the address because the broker will cleanup the 59// patch when the work is performed. 60// 61// It should be noted that we don't wait until the real work is done; this 62// program quits as soon as the 64-bit interception is performed. 63int wWinMain(HINSTANCE, HINSTANCE, wchar_t* command_line, int) { 64 COMPILE_ASSERT(sizeof(void*) > sizeof(DWORD), unsupported_32_bits); 65 if (!command_line) 66 return 1; 67 68 wchar_t* next; 69 DWORD process_id = wcstoul(command_line, &next, 0); 70 if (!process_id) 71 return 2; 72 73 DWORD access = PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE; 74 HANDLE child = ::OpenProcess(access, FALSE, process_id); 75 if (!child) 76 return 3; 77 78 DWORD buffer = wcstoul(next, NULL, 0); 79 if (!buffer) 80 return 4; 81 82 void* thunk = reinterpret_cast<void*>(static_cast<ULONG_PTR>(buffer)); 83 84 const size_t kPageSize = 4096; 85 return sandbox::PatchNtdll(child, thunk, kPageSize); 86} 87