Home | History | Annotate | Download | only in wow_helper
      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 
     18 namespace 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.
     23 int 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.
     63 int 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