summaryrefslogtreecommitdiffstats
path: root/sandbox/wow_helper
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 22:41:28 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 22:41:28 +0000
commita814a8d55429605fe6d7045045cd25b6bf624580 (patch)
tree58fcd994d4ce41ef021f6406a6fac32d9ca2d265 /sandbox/wow_helper
parente6c9e14e0dfec2bb156a1f7a107cda3ebee8d392 (diff)
downloadchromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.zip
chromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.tar.gz
chromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.tar.bz2
Add sandbox to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/wow_helper')
-rw-r--r--sandbox/wow_helper/service64_resolver.cc371
-rw-r--r--sandbox/wow_helper/service64_resolver.h97
-rw-r--r--sandbox/wow_helper/target_code.cc59
-rw-r--r--sandbox/wow_helper/target_code.h66
-rw-r--r--sandbox/wow_helper/wow_helper.cc152
-rw-r--r--sandbox/wow_helper/wow_helper.exebin0 -> 99328 bytes
-rw-r--r--sandbox/wow_helper/wow_helper.pdbbin0 -> 2141184 bytes
-rw-r--r--sandbox/wow_helper/wow_helper.vcproj231
8 files changed, 976 insertions, 0 deletions
diff --git a/sandbox/wow_helper/service64_resolver.cc b/sandbox/wow_helper/service64_resolver.cc
new file mode 100644
index 0000000..6718149
--- /dev/null
+++ b/sandbox/wow_helper/service64_resolver.cc
@@ -0,0 +1,371 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "sandbox/wow_helper/service64_resolver.h"
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "sandbox/wow_helper/target_code.h"
+
+namespace {
+#pragma pack(push, 1)
+
+const BYTE kMovEax = 0xB8;
+const BYTE kMovEdx = 0xBA;
+const USHORT kCallPtrEdx = 0x12FF;
+const BYTE kRet = 0xC2;
+const BYTE kNop = 0x90;
+const USHORT kJmpEdx = 0xE2FF;
+const USHORT kXorEcx = 0xC933;
+const ULONG kLeaEdx = 0x0424548D;
+const ULONG kCallFs1 = 0xC015FF64;
+const ULONG kCallFs2Ret = 0xC2000000;
+const BYTE kPopEdx = 0x5A;
+const BYTE kPushEdx = 0x52;
+const BYTE kPush32 = 0x68;
+
+const ULONG kMmovR10EcxMovEax = 0xB8D18B4C;
+const USHORT kSyscall = 0x050F;
+const BYTE kRetNp = 0xC3;
+const BYTE kPad = 0x66;
+const USHORT kNop16 = 0x9066;
+const BYTE kRelJmp = 0xE9;
+
+const ULONG kXorRaxMovEax = 0xB8C03148;
+const ULONG kSaveRcx = 0x10488948;
+const ULONG kMovRcxRaxJmp = 0xE9C88B48;
+
+// Service code for 64 bit systems.
+struct ServiceEntry {
+ // this struct contains roughly the following code:
+ // mov r10,rcx
+ // mov eax,52h
+ // syscall
+ // ret
+ // xchg ax,ax
+ // xchg ax,ax
+
+ ULONG mov_r10_ecx_mov_eax; // = 4C 8B D1 B8
+ ULONG service_id;
+ USHORT syscall; // = 0F 05
+ BYTE ret; // = C3
+ BYTE pad; // = 66
+ USHORT xchg_ax_ax1; // = 66 90
+ USHORT xchg_ax_ax2; // = 66 90
+};
+
+struct Redirected {
+ // this struct contains roughly the following code:
+ // jmp relative_32
+ // xchg ax,ax // 3 byte nop
+
+ Redirected() {
+ jmp = kRelJmp;
+ relative = 0;
+ pad = kPad;
+ xchg_ax_ax = kNop16;
+ };
+ BYTE jmp; // = E9
+ ULONG relative;
+ BYTE pad; // = 66
+ USHORT xchg_ax_ax; // = 66 90
+};
+
+struct InternalThunk {
+ // this struct contains roughly the following code:
+ // xor rax,rax
+ // mov eax, 0x00080000 // Thunk storage.
+ // mov [rax]PatchInfo.service, rcx // Save first argument.
+ // mov rcx, rax
+ // jmp relative_to_interceptor
+
+ InternalThunk() {
+ xor_rax_mov_eax = kXorRaxMovEax;
+ patch_info = 0;
+ save_rcx = kSaveRcx;
+ mov_rcx_rax_jmp = kMovRcxRaxJmp;
+ relative = 0;
+ };
+ ULONG xor_rax_mov_eax; // = 48 31 C0 B8
+ ULONG patch_info;
+ ULONG save_rcx; // = 48 89 48 10
+ ULONG mov_rcx_rax_jmp; // = 48 8b c8 e9
+ ULONG relative;
+};
+
+struct ServiceFullThunk {
+ sandbox::PatchInfo patch_info;
+ ServiceEntry original;
+ InternalThunk internal_thunk;
+};
+
+#pragma pack(pop)
+
+// Simple utility function to write to a buffer on the child, if the memery has
+// write protection attributes.
+// Arguments:
+// child_process (in): process to write to.
+// address (out): memory position on the child to write to.
+// buffer (in): local buffer with the data to write .
+// length (in): number of bytes to write.
+// Returns true on success.
+bool WriteProtectedChildMemory(HANDLE child_process,
+ void* address,
+ const void* buffer,
+ size_t length) {
+ // first, remove the protections
+ DWORD old_protection;
+ if (!::VirtualProtectEx(child_process, address, length,
+ PAGE_WRITECOPY, &old_protection))
+ return false;
+
+ SIZE_T written;
+ bool ok = ::WriteProcessMemory(child_process, address, buffer, length,
+ &written) && (length == written);
+
+ // always attempt to restore the original protection
+ if (!::VirtualProtectEx(child_process, address, length,
+ old_protection, &old_protection))
+ return false;
+
+ return ok;
+}
+
+// Get pointers to the functions that we need from ntdll.dll.
+NTSTATUS ResolveNtdll(sandbox::PatchInfo* patch_info) {
+ wchar_t* ntdll_name = L"ntdll.dll";
+ HMODULE ntdll = ::GetModuleHandle(ntdll_name);
+ if (!ntdll)
+ return STATUS_PROCEDURE_NOT_FOUND;
+
+ void* signal = ::GetProcAddress(ntdll, "NtSignalAndWaitForSingleObject");
+ if (!signal)
+ return STATUS_PROCEDURE_NOT_FOUND;
+
+ patch_info->signal_and_wait =
+ reinterpret_cast<NtSignalAndWaitForSingleObjectFunction>(signal);
+
+ return STATUS_SUCCESS;
+}
+
+}; // namespace
+
+namespace sandbox {
+
+NTSTATUS ResolverThunk::Init(const void* target_module,
+ const void* interceptor_module,
+ const char* target_name,
+ const char* interceptor_name,
+ const void* interceptor_entry_point,
+ void* thunk_storage,
+ size_t storage_bytes) {
+ if (NULL == thunk_storage || 0 == storage_bytes ||
+ NULL == target_module || NULL == target_name)
+ return STATUS_INVALID_PARAMETER;
+
+ if (storage_bytes < GetThunkSize())
+ return STATUS_BUFFER_TOO_SMALL;
+
+ NTSTATUS ret = STATUS_SUCCESS;
+ if (NULL == interceptor_entry_point) {
+ ret = ResolveInterceptor(interceptor_module, interceptor_name,
+ &interceptor_entry_point);
+ if (!NT_SUCCESS(ret))
+ return ret;
+ }
+
+ ret = ResolveTarget(target_module, target_name, &target_);
+ if (!NT_SUCCESS(ret))
+ return ret;
+
+ interceptor_ = interceptor_entry_point;
+
+ return ret;
+}
+
+NTSTATUS ResolverThunk::ResolveInterceptor(const void* interceptor_module,
+ const char* interceptor_name,
+ const void** address) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS ResolverThunk::ResolveTarget(const void* module,
+ const char* function_name,
+ void** address) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS Service64ResolverThunk::Setup(const void* target_module,
+ const void* interceptor_module,
+ const char* target_name,
+ const char* interceptor_name,
+ const void* interceptor_entry_point,
+ void* thunk_storage,
+ size_t storage_bytes,
+ size_t* storage_used) {
+ NTSTATUS ret = Init(target_module, interceptor_module, target_name,
+ interceptor_name, interceptor_entry_point,
+ thunk_storage, storage_bytes);
+ if (!NT_SUCCESS(ret))
+ return ret;
+
+ size_t thunk_bytes = GetThunkSize();
+ scoped_ptr<char> thunk_buffer(new char[thunk_bytes]);
+ ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(
+ thunk_buffer.get());
+
+ if (!IsFunctionAService(&thunk->original))
+ return STATUS_UNSUCCESSFUL;
+
+ ret = PerformPatch(thunk, thunk_storage);
+
+ if (NULL != storage_used)
+ *storage_used = thunk_bytes;
+
+ return ret;
+}
+
+NTSTATUS Service64ResolverThunk::ResolveInterceptor(
+ const void* interceptor_module,
+ const char* interceptor_name,
+ const void** address) {
+ // After all, we are using a locally mapped version of the exe, so the
+ // action is the same as for a target function.
+ return ResolveTarget(interceptor_module, interceptor_name,
+ const_cast<void**>(address));
+}
+
+// In this case all the work is done from the parent, so resolve is
+// just a simple GetProcAddress.
+NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module,
+ const char* function_name,
+ void** address) {
+ DCHECK(address);
+ if (NULL == module)
+ return STATUS_UNSUCCESSFUL;
+
+ *address = ::GetProcAddress(bit_cast<HMODULE>(module), function_name);
+
+ if (NULL == *address)
+ return STATUS_UNSUCCESSFUL;
+
+ return STATUS_SUCCESS;
+}
+
+size_t Service64ResolverThunk::GetThunkSize() const {
+ return sizeof(ServiceFullThunk);
+}
+
+bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const {
+ ServiceEntry function_code;
+ SIZE_T read;
+ if (!::ReadProcessMemory(process_, target_, &function_code,
+ sizeof(function_code), &read))
+ return false;
+
+ if (sizeof(function_code) != read)
+ return false;
+
+ if (kMmovR10EcxMovEax != function_code.mov_r10_ecx_mov_eax ||
+ kSyscall != function_code.syscall || kRetNp != function_code.ret ||
+ kPad != function_code.pad || kNop16 != function_code.xchg_ax_ax1 ||
+ kNop16 != function_code.xchg_ax_ax1)
+ return false;
+
+ // Save the verified code
+ memcpy(local_thunk, &function_code, sizeof(function_code));
+
+ return true;
+}
+
+NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk,
+ void* remote_thunk) {
+ ServiceFullThunk* full_local_thunk = reinterpret_cast<ServiceFullThunk*>(
+ local_thunk);
+ ServiceFullThunk* full_remote_thunk = reinterpret_cast<ServiceFullThunk*>(
+ remote_thunk);
+
+ // If the source or target are above 4GB we cannot do this relative jump.
+ if (reinterpret_cast<ULONG_PTR>(full_remote_thunk) >
+ static_cast<ULONG_PTR>(ULONG_MAX))
+ return STATUS_CONFLICTING_ADDRESSES;
+
+ if (reinterpret_cast<ULONG_PTR>(target_) > static_cast<ULONG_PTR>(ULONG_MAX))
+ return STATUS_CONFLICTING_ADDRESSES;
+
+ // Patch the original code.
+ Redirected local_service;
+ Redirected* remote_service = reinterpret_cast<Redirected*>(target_);
+ ULONG_PTR diff = reinterpret_cast<BYTE*>(&full_remote_thunk->internal_thunk) -
+ &remote_service->pad;
+ local_service.relative = static_cast<ULONG>(diff);
+
+ // Setup the PatchInfo structure.
+ SIZE_T actual;
+ if (!::ReadProcessMemory(process_, remote_thunk, local_thunk,
+ sizeof(PatchInfo), &actual))
+ return STATUS_UNSUCCESSFUL;
+ if (sizeof(PatchInfo) != actual)
+ return STATUS_UNSUCCESSFUL;
+
+ full_local_thunk->patch_info.orig_MapViewOfSection = reinterpret_cast<
+ NtMapViewOfSectionFunction>(&full_remote_thunk->original);
+ full_local_thunk->patch_info.patch_location = target_;
+ NTSTATUS ret = ResolveNtdll(&full_local_thunk->patch_info);
+ if (!NT_SUCCESS(ret))
+ return ret;
+
+ // Setup the thunk. The jump out is performed from right after the end of the
+ // thunk (full_remote_thunk + 1).
+ InternalThunk my_thunk;
+ ULONG_PTR patch_info = reinterpret_cast<ULONG_PTR>(remote_thunk);
+ my_thunk.patch_info = static_cast<ULONG>(patch_info);
+ diff = reinterpret_cast<const BYTE*>(interceptor_) -
+ reinterpret_cast<BYTE*>(full_remote_thunk + 1);
+ my_thunk.relative = static_cast<ULONG>(diff);
+
+ memcpy(&full_local_thunk->internal_thunk, &my_thunk, sizeof(my_thunk));
+
+ // copy the local thunk buffer to the child
+ if (!::WriteProcessMemory(process_, remote_thunk, local_thunk,
+ sizeof(ServiceFullThunk), &actual))
+ return STATUS_UNSUCCESSFUL;
+
+ if (sizeof(ServiceFullThunk) != actual)
+ return STATUS_UNSUCCESSFUL;
+
+ // and now change the function to intercept, on the child
+ if (!::WriteProtectedChildMemory(process_, target_, &local_service,
+ sizeof(local_service)))
+ return STATUS_UNSUCCESSFUL;
+
+ return STATUS_SUCCESS;
+}
+
+} // namespace sandbox
diff --git a/sandbox/wow_helper/service64_resolver.h b/sandbox/wow_helper/service64_resolver.h
new file mode 100644
index 0000000..9d20bed
--- /dev/null
+++ b/sandbox/wow_helper/service64_resolver.h
@@ -0,0 +1,97 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__
+#define SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__
+
+#include "sandbox/src/nt_internals.h"
+#include "sandbox/src/resolver.h"
+
+namespace sandbox {
+
+// This is the concrete resolver used to perform service-call type functions
+// inside ntdll.dll (64-bit).
+class Service64ResolverThunk : public ResolverThunk {
+ public:
+ // The service resolver needs a child process to write to.
+ explicit Service64ResolverThunk(HANDLE process)
+ : process_(process), ntdll_base_(NULL) {}
+ virtual ~Service64ResolverThunk() {}
+
+ // Implementation of Resolver::Setup.
+ virtual NTSTATUS Setup(const void* target_module,
+ const void* interceptor_module,
+ const char* target_name,
+ const char* interceptor_name,
+ const void* interceptor_entry_point,
+ void* thunk_storage,
+ size_t storage_bytes,
+ size_t* storage_used);
+
+ // Implementation of Resolver::ResolveInterceptor.
+ virtual NTSTATUS ResolveInterceptor(const void* module,
+ const char* function_name,
+ const void** address);
+
+ // Implementation of Resolver::ResolveTarget.
+ virtual NTSTATUS ResolveTarget(const void* module,
+ const char* function_name,
+ void** address);
+
+ // Implementation of Resolver::GetThunkSize.
+ virtual size_t GetThunkSize() const;
+
+ protected:
+ // The unit test will use this member to allow local patch on a buffer.
+ HMODULE ntdll_base_;
+
+ // Handle of the child process.
+ HANDLE process_;
+
+ private:
+ // Returns true if the code pointer by target_ corresponds to the expected
+ // type of function. Saves that code on the first part of the thunk pointed
+ // by local_thunk (should be directly accessible from the parent).
+ virtual bool IsFunctionAService(void* local_thunk) const;
+
+ // Performs the actual patch of target_.
+ // local_thunk must be already fully initialized, and the first part must
+ // contain the original code. The real type of this buffer is ServiceFullThunk
+ // (yes, private). remote_thunk (real type ServiceFullThunk), must be
+ // allocated on the child, and will contain the thunk data, after this call.
+ // Returns the apropriate status code.
+ virtual NTSTATUS PerformPatch(void* local_thunk, void* remote_thunk);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Service64ResolverThunk);
+};
+
+} // namespace sandbox
+
+
+#endif // SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__
diff --git a/sandbox/wow_helper/target_code.cc b/sandbox/wow_helper/target_code.cc
new file mode 100644
index 0000000..1ef1582
--- /dev/null
+++ b/sandbox/wow_helper/target_code.cc
@@ -0,0 +1,59 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "sandbox/wow_helper/target_code.h"
+
+namespace sandbox {
+
+// Hooks NtMapViewOfSection to detect the load of dlls.
+NTSTATUS WINAPI TargetNtMapViewOfSection(
+ PatchInfo *patch_info, HANDLE process, PVOID *base, ULONG_PTR zero_bits,
+ SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
+ SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) {
+ NTSTATUS ret = patch_info->orig_MapViewOfSection(patch_info->section, process,
+ base, zero_bits, commit_size,
+ offset, view_size, inherit,
+ allocation_type, protect);
+
+ LARGE_INTEGER timeout;
+ timeout.QuadPart = -(5 * 10000000); // 5 seconds.
+
+ // The wait is alertable.
+ patch_info->signal_and_wait(patch_info->dll_load, patch_info->continue_load,
+ TRUE, &timeout);
+
+ return ret;
+}
+
+// Marks the end of the code to copy to the target process.
+NTSTATUS WINAPI TargetEnd() {
+ return STATUS_SUCCESS;
+}
+
+} // namespace sandbox
diff --git a/sandbox/wow_helper/target_code.h b/sandbox/wow_helper/target_code.h
new file mode 100644
index 0000000..9ae9089
--- /dev/null
+++ b/sandbox/wow_helper/target_code.h
@@ -0,0 +1,66 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SANDBOX_WOW_HELPER_TARGET_CODE_H__
+#define SANDBOX_WOW_HELPER_TARGET_CODE_H__
+
+#include "sandbox/src/nt_internals.h"
+
+namespace sandbox {
+
+extern "C" {
+
+// Holds the information needed for the interception of NtMapViewOfSection.
+// Changes of this structure must be synchronized with changes of PatchInfo32
+// on sandbox/src/wow64.cc.
+struct PatchInfo {
+ HANDLE dll_load; // Event to signal the broker.
+ HANDLE continue_load; // Event to wait for the broker.
+ HANDLE section; // First argument of the call.
+ NtMapViewOfSectionFunction orig_MapViewOfSection;
+ NtSignalAndWaitForSingleObjectFunction signal_and_wait;
+ void* patch_location;
+};
+
+// Interception of NtMapViewOfSection on the child process.
+// It should never be called directly. This function provides the means to
+// detect dlls being loaded, so we can patch them if needed.
+NTSTATUS WINAPI TargetNtMapViewOfSection(
+ PatchInfo* patch_info, HANDLE process, PVOID* base, ULONG_PTR zero_bits,
+ SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
+ SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect);
+
+// Marker of the end of TargetNtMapViewOfSection.
+NTSTATUS WINAPI TargetEnd();
+
+} // extern "C"
+
+} // namespace sandbox
+
+#endif // SANDBOX_WOW_HELPER_TARGET_CODE_H__
diff --git a/sandbox/wow_helper/wow_helper.cc b/sandbox/wow_helper/wow_helper.cc
new file mode 100644
index 0000000..9e8ae09f
--- /dev/null
+++ b/sandbox/wow_helper/wow_helper.cc
@@ -0,0 +1,152 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Wow_helper.exe is a simple Win32 64-bit executable designed to help to
+// sandbox a 32 bit application running on a 64 bit OS. The basic idea is to
+// perform a 64 bit interception of the target process and notify the 32-bit
+// broker process whenever a DLL is being loaded. This allows the broker to
+// setup the interceptions (32-bit) properly on the target.
+
+#include <windows.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "sandbox/wow_helper/service64_resolver.h"
+#include "sandbox/wow_helper/target_code.h"
+
+namespace {
+
+// Grabbed from chrome/common/string_util.h
+template <class char_type>
+inline char_type* WriteInto(
+ std::basic_string<char_type, std::char_traits<char_type>,
+ std::allocator<char_type> >* str,
+ size_t length_including_null) {
+ str->reserve(length_including_null);
+ str->resize(length_including_null - 1);
+ return &((*str)[0]);
+}
+
+// Grabbed from chrome/common/string_util.cc
+std::string WideToMultiByte(const std::wstring& wide, UINT code_page) {
+ if (wide.length() == 0)
+ return std::string();
+
+ // compute the length of the buffer we'll need
+ int charcount = WideCharToMultiByte(code_page, 0, wide.c_str(), -1,
+ NULL, 0, NULL, NULL);
+ if (charcount == 0)
+ return std::string();
+
+ // convert
+ std::string mb;
+ WideCharToMultiByte(code_page, 0, wide.c_str(), -1,
+ WriteInto(&mb, charcount), charcount, NULL, NULL);
+
+ return mb;
+}
+
+// Grabbed from chrome/common/string_util.cc
+std::string WideToUTF8(const std::wstring& wide) {
+ return WideToMultiByte(wide, CP_UTF8);
+}
+
+} // namespace
+
+namespace sandbox {
+
+// Performs the interception of NtMapViewOfSection on the 64-bit version of
+// ntdll.dll. 'thunk' is the buffer on the address space of process 'child',
+// that will be used to store the information about the patch.
+int PatchNtdll(HANDLE child, void* thunk, size_t thunk_bytes) {
+ wchar_t* ntdll_name = L"ntdll.dll";
+ HMODULE ntdll_base = ::GetModuleHandle(ntdll_name);
+ if (!ntdll_base)
+ return 100;
+
+ Service64ResolverThunk resolver(child);
+ size_t used = resolver.GetThunkSize();
+ char* code = reinterpret_cast<char*>(thunk) + used;
+ NTSTATUS ret = resolver.Setup(ntdll_base, NULL, "NtMapViewOfSection", NULL,
+ code, thunk, thunk_bytes, NULL);
+ if (!NT_SUCCESS(ret))
+ return 101;
+
+ size_t size = reinterpret_cast<char*>(&TargetEnd) -
+ reinterpret_cast<char*>(&TargetNtMapViewOfSection);
+
+ if (size + used > thunk_bytes)
+ return 102;
+
+ SIZE_T written;
+ if (!::WriteProcessMemory(child, code, &TargetNtMapViewOfSection, size,
+ &written))
+ return 103;
+
+ if (size != written)
+ return 104;
+
+ return 0;
+}
+
+} // namespace sandbox
+
+// We must receive two arguments: the process id of the target to intercept and
+// the address of a page of memory on that process that will be used for the
+// interception. We receive the address because the broker will cleanup the
+// patch when the work is performed.
+//
+// It should be noted that we don't wait until the real work is done; this
+// program quits as soon as the 64-bit interception is performed.
+int wWinMain(HINSTANCE, HINSTANCE, wchar_t* command_line, int) {
+ COMPILE_ASSERT(sizeof(void*) > sizeof(DWORD), unsupported_32_bits);
+ if (!command_line)
+ return 1;
+
+ wchar_t* next;
+ DWORD process_id = wcstoul(command_line, &next, 0);
+ if (!process_id)
+ return 2;
+
+ DWORD access = PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE;
+ HANDLE child = ::OpenProcess(access, FALSE, process_id);
+ DCHECK(child);
+ if (!child)
+ return 3;
+
+ DWORD buffer = wcstoul(next, NULL, 0);
+ if (!buffer)
+ return 4;
+
+ void* thunk = reinterpret_cast<void*>(static_cast<ULONG_PTR>(buffer));
+
+ const size_t kPageSize = 4096;
+ return sandbox::PatchNtdll(child, thunk, kPageSize);
+}
diff --git a/sandbox/wow_helper/wow_helper.exe b/sandbox/wow_helper/wow_helper.exe
new file mode 100644
index 0000000..163270a
--- /dev/null
+++ b/sandbox/wow_helper/wow_helper.exe
Binary files differ
diff --git a/sandbox/wow_helper/wow_helper.pdb b/sandbox/wow_helper/wow_helper.pdb
new file mode 100644
index 0000000..a0d7d48
--- /dev/null
+++ b/sandbox/wow_helper/wow_helper.pdb
Binary files differ
diff --git a/sandbox/wow_helper/wow_helper.vcproj b/sandbox/wow_helper/wow_helper.vcproj
new file mode 100644
index 0000000..3fef097
--- /dev/null
+++ b/sandbox/wow_helper/wow_helper.vcproj
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="wow_helper"
+ ProjectGUID="{BCF3A457-39F1-4DAA-9A65-93CFCD559036}"
+ RootNamespace="wow_helper"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(ProjectDir)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)..;$(SolutionDir)..\third_party\platformsdk_vista_6_0\files\Include;$(SolutionDir)..\third_party\platformsdk_vista_6_0\files\VC\INCLUDE;$(VSInstallDir)\VC\atlmfc\include"
+ PreprocessorDefinitions="_WIN32_WINNT=0x0501;WINVER=0x0501;WIN32;_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="1"
+ BufferSecurityCheck="false"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(ProjectDir)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)..;$(SolutionDir)..\third_party\platformsdk_vista_6_0\files\Include;$(SolutionDir)..\third_party\platformsdk_vista_6_0\files\VC\INCLUDE;$(VSInstallDir)\VC\atlmfc\include"
+ PreprocessorDefinitions="_WIN32_WINNT=0x0501;WINVER=0x0501;WIN32;NDEBUG"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="base"
+ >
+ <File
+ RelativePath="..\..\base\logging.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\base\logging.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\base\scoped_ptr.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="sandbox"
+ >
+ <File
+ RelativePath="..\src\nt_internals.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\resolver.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\service64_resolver.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\service64_resolver.h"
+ >
+ </File>
+ <File
+ RelativePath=".\target_code.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\target_code.h"
+ >
+ </File>
+ <File
+ RelativePath=".\wow_helper.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>