summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-17 22:35:31 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-17 22:35:31 +0000
commita71ca488b1b2e666a3faad68e8fa71fa1554f0a9 (patch)
tree8e13ec487ee9c3a193f3a22a1253f5d342d9fb4c /sandbox
parent3b36c1b893df91a00eec8ee98f01765c4097ca68 (diff)
downloadchromium_src-a71ca488b1b2e666a3faad68e8fa71fa1554f0a9.zip
chromium_src-a71ca488b1b2e666a3faad68e8fa71fa1554f0a9.tar.gz
chromium_src-a71ca488b1b2e666a3faad68e8fa71fa1554f0a9.tar.bz2
Sandbox: Add support for interceptions on Windows 8.
BUG=123068 TEST=sbox_unittests, sbox_integration_tests Review URL: https://chromiumcodereview.appspot.com/10021033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132680 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/src/interception.cc22
-rw-r--r--sandbox/src/service_resolver.h32
-rw-r--r--sandbox/src/service_resolver_32.cc111
-rw-r--r--sandbox/src/service_resolver_unittest.cc29
4 files changed, 169 insertions, 25 deletions
diff --git a/sandbox/src/interception.cc b/sandbox/src/interception.cc
index b66fddd..a873f4a 100644
--- a/sandbox/src/interception.cc
+++ b/sandbox/src/interception.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -438,13 +438,23 @@ bool InterceptionManager::PatchClientFunctions(DllInterceptionData* thunks,
#endif
ServiceResolverThunk* thunk;
- if (base::win::OSInfo::GetInstance()->wow64_status() ==
- base::win::OSInfo::WOW64_ENABLED)
- thunk = new Wow64ResolverThunk(child_->Process(), relaxed_);
- else if (!IsXPSP2OrLater())
+#if defined(_WIN64)
+ thunk = new ServiceResolverThunk(child_->Process(), relaxed_);
+#else
+ base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
+ if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
+ if (os_info->version() >= base::win::VERSION_WIN8)
+ thunk = new Wow64W8ResolverThunk(child_->Process(), relaxed_);
+ else
+ thunk = new Wow64ResolverThunk(child_->Process(), relaxed_);
+ } else if (!IsXPSP2OrLater()) {
thunk = new Win2kResolverThunk(child_->Process(), relaxed_);
- else
+ } else if (os_info->version() >= base::win::VERSION_WIN8) {
+ thunk = new Win8ResolverThunk(child_->Process(), relaxed_);
+ } else {
thunk = new ServiceResolverThunk(child_->Process(), relaxed_);
+ }
+#endif
std::list<InterceptionData>::iterator it = interceptions_.begin();
for (; it != interceptions_.end(); ++it) {
diff --git a/sandbox/src/service_resolver.h b/sandbox/src/service_resolver.h
index 469080a..99eadb6 100644
--- a/sandbox/src/service_resolver.h
+++ b/sandbox/src/service_resolver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -96,6 +96,21 @@ class Wow64ResolverThunk : public ServiceResolverThunk {
};
// This is the concrete resolver used to perform service-call type functions
+// inside ntdll.dll on WOW64 for Windows 8.
+class Wow64W8ResolverThunk : public ServiceResolverThunk {
+ public:
+ // The service resolver needs a child process to write to.
+ Wow64W8ResolverThunk(HANDLE process, bool relaxed)
+ : ServiceResolverThunk(process, relaxed) {}
+ virtual ~Wow64W8ResolverThunk() {}
+
+ private:
+ virtual bool IsFunctionAService(void* local_thunk) const;
+
+ DISALLOW_COPY_AND_ASSIGN(Wow64W8ResolverThunk);
+};
+
+// This is the concrete resolver used to perform service-call type functions
// inside ntdll.dll on Windows 2000 and XP pre SP2.
class Win2kResolverThunk : public ServiceResolverThunk {
public:
@@ -112,6 +127,21 @@ class Win2kResolverThunk : public ServiceResolverThunk {
DISALLOW_COPY_AND_ASSIGN(Win2kResolverThunk);
};
+// This is the concrete resolver used to perform service-call type functions
+// inside ntdll.dll on Windows 8.
+class Win8ResolverThunk : public ServiceResolverThunk {
+ public:
+ // The service resolver needs a child process to write to.
+ Win8ResolverThunk(HANDLE process, bool relaxed)
+ : ServiceResolverThunk(process, relaxed) {}
+ virtual ~Win8ResolverThunk() {}
+
+ private:
+ virtual bool IsFunctionAService(void* local_thunk) const;
+
+ DISALLOW_COPY_AND_ASSIGN(Win8ResolverThunk);
+};
+
} // namespace sandbox
diff --git a/sandbox/src/service_resolver_32.cc b/sandbox/src/service_resolver_32.cc
index ffe4d15..2f5597b 100644
--- a/sandbox/src/service_resolver_32.cc
+++ b/sandbox/src/service_resolver_32.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,9 +13,12 @@ namespace {
const BYTE kMovEax = 0xB8;
const BYTE kMovEdx = 0xBA;
+const USHORT kMovEdxEsp = 0xD48B;
const USHORT kCallPtrEdx = 0x12FF;
const USHORT kCallEdx = 0xD2FF;
+const BYTE kCallEip = 0xE8;
const BYTE kRet = 0xC2;
+const BYTE kRet2 = 0xC3;
const BYTE kNop = 0x90;
const USHORT kJmpEdx = 0xE2FF;
const USHORT kXorEcx = 0xC933;
@@ -26,13 +29,14 @@ const BYTE kCallFs3 = 0;
const BYTE kAddEsp1 = 0x83;
const USHORT kAddEsp2 = 0x4C4;
const BYTE kJmp32 = 0xE9;
+const USHORT kSysenter = 0x340F;
const int kMaxService = 1000;
// Service code for 32 bit systems.
// NOTE: on win2003 "call dword ptr [edx]" is "call edx".
struct ServiceEntry {
- // this struct contains roughly the following code:
+ // This struct contains roughly the following code:
// 00 mov eax,25h
// 05 mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
// 0a call dword ptr [edx]
@@ -46,22 +50,42 @@ struct ServiceEntry {
BYTE ret; // = C2
USHORT num_params;
BYTE nop;
- ULONG pad1; // Extend the structure to be the same size as the
- ULONG pad2; // 64 version (Wow64Entry)
+};
+
+// Service code for 32 bit Windows 8.
+struct ServiceEntryW8 {
+ // This struct contains the following code:
+ // 00 b825000000 mov eax,25h
+ // 05 e803000000 call eip+3
+ // 0a c22c00 ret 2Ch
+ // 0d 8bd4 mov edx,esp
+ // 0f 0f34 sysenter
+ // 11 c3 ret
+ // 12 8bff mov edi,edi
+ BYTE mov_eax; // = B8
+ ULONG service_id;
+ BYTE call_eip; // = E8
+ ULONG call_offset;
+ BYTE ret_p; // = C2
+ USHORT num_params;
+ USHORT mov_edx_esp; // = BD D4
+ USHORT sysenter; // = 0F 34
+ BYTE ret; // = C3
+ USHORT nop;
};
// Service code for a 32 bit process running on a 64 bit os.
struct Wow64Entry {
// This struct may contain one of two versions of code:
// 1. For XP, Vista and 2K3:
- // 00 b852000000 mov eax, 25h
+ // 00 b825000000 mov eax, 25h
// 05 33c9 xor ecx, ecx
// 07 8d542404 lea edx, [esp + 4]
// 0b 64ff15c0000000 call dword ptr fs:[0C0h]
// 12 c22c00 ret 2Ch
//
// 2. For Windows 7:
- // 00 b852000000 mov eax, 25h
+ // 00 b825000000 mov eax, 25h
// 05 33c9 xor ecx, ecx
// 07 8d542404 lea edx, [esp + 4]
// 0b 64ff15c0000000 call dword ptr fs:[0C0h]
@@ -82,13 +106,34 @@ struct Wow64Entry {
USHORT num_params;
};
+// Service code for a 32 bit process running on 64 bit Windows 8.
+struct Wow64EntryW8 {
+ // 00 b825000000 mov eax, 25h
+ // 05 64ff15c0000000 call dword ptr fs:[0C0h]
+ // 0b c22c00 ret 2Ch
+ // 0f 90 nop
+ BYTE mov_eax; // = B8
+ ULONG service_id;
+ ULONG call_fs1; // = 64 FF 15 C0
+ USHORT call_fs2; // = 00 00
+ BYTE call_fs3; // = 00
+ BYTE ret; // = C2
+ USHORT num_params;
+ BYTE nop;
+};
+
// Make sure that relaxed patching works as expected.
-COMPILE_ASSERT(sizeof(ServiceEntry) == sizeof(Wow64Entry), wrong_service_len);
+const size_t kMinServiceSize = offsetof(ServiceEntry, ret);
+COMPILE_ASSERT(sizeof(ServiceEntryW8) >= kMinServiceSize, wrong_service_len);
+COMPILE_ASSERT(sizeof(Wow64Entry) >= kMinServiceSize, wrong_service_len);
+COMPILE_ASSERT(sizeof(Wow64EntryW8) >= kMinServiceSize, wrong_service_len);
struct ServiceFullThunk {
union {
ServiceEntry original;
+ ServiceEntryW8 original_w8;
Wow64Entry wow_64;
+ Wow64EntryW8 wow_64_w8;
};
int internal_thunk; // Dummy member to the beginning of the internal thunk.
};
@@ -212,13 +257,7 @@ NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk,
intercepted_code.mov_edx = kMovEdx;
intercepted_code.stub = bit_cast<ULONG>(&full_remote_thunk->internal_thunk);
intercepted_code.call_ptr_edx = kJmpEdx;
- if (!win2k_) {
- intercepted_code.ret = kRet;
- intercepted_code.num_params = full_local_thunk->original.num_params;
- intercepted_code.nop = kNop;
- } else {
- bytes_to_write = offsetof(ServiceEntry, ret);
- }
+ bytes_to_write = kMinServiceSize;
if (relative_jump_) {
intercepted_code.mov_eax = kJmp32;
@@ -318,6 +357,27 @@ bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const {
return false;
}
+bool Wow64W8ResolverThunk::IsFunctionAService(void* local_thunk) const {
+ Wow64EntryW8 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 (kMovEax != function_code.mov_eax || kCallFs1 != function_code.call_fs1 ||
+ kCallFs2 != function_code.call_fs2 ||
+ kCallFs3 != function_code.call_fs3 || kRet != function_code.ret) {
+ return false;
+ }
+
+ // Save the verified code
+ memcpy(local_thunk, &function_code, sizeof(function_code));
+ return true;
+}
+
bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const {
ServiceEntry function_code;
SIZE_T read;
@@ -338,4 +398,27 @@ bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const {
return true;
}
+bool Win8ResolverThunk::IsFunctionAService(void* local_thunk) const {
+ ServiceEntryW8 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 (kMovEax != function_code.mov_eax || kCallEip != function_code.call_eip ||
+ function_code.call_offset != 3 || kRet != function_code.ret_p ||
+ kMovEdxEsp != function_code.mov_edx_esp ||
+ kSysenter != function_code.sysenter || kRet2 != function_code.ret) {
+ return false;
+ }
+
+ // Save the verified code
+ memcpy(local_thunk, &function_code, sizeof(function_code));
+
+ return true;
+}
+
} // namespace sandbox
diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc
index 36ad1d0f..fc85c86 100644
--- a/sandbox/src/service_resolver_unittest.cc
+++ b/sandbox/src/service_resolver_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -55,9 +55,14 @@ class ResolverThunkTest : public T {
DISALLOW_COPY_AND_ASSIGN(ResolverThunkTest);
};
-typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest;
typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest;
+
+#if !defined(_WIN64)
+typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest;
+typedef ResolverThunkTest<sandbox::Win8ResolverThunk> Win8ResolverTest;
typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest;
+typedef ResolverThunkTest<sandbox::Wow64W8ResolverThunk> Wow64W8ResolverTest;
+#endif
const BYTE kJump32 = 0xE9;
@@ -70,12 +75,16 @@ void CheckJump(void* source, void* target) {
};
#pragma pack(pop)
+#if defined(_WIN64)
+ FAIL() << "Running 32-bit codepath";
+#else
Code* patched = reinterpret_cast<Code*>(source);
EXPECT_EQ(kJump32, patched->jump);
ULONG source_addr = bit_cast<ULONG>(source);
ULONG target_addr = bit_cast<ULONG>(target);
EXPECT_EQ(target_addr + 19 - source_addr, patched->delta);
+#endif
}
NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
@@ -120,12 +129,24 @@ NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
}
sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) {
- if (base::win::OSInfo::GetInstance()->wow64_status() ==
- base::win::OSInfo::WOW64_ENABLED)
+#if defined(_WIN64)
+ return new WinXpResolverTest(relaxed);
+#else
+ base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
+ if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
+ if (os_info->version() >= base::win::VERSION_WIN8)
+ return new Wow64W8ResolverTest(relaxed);
return new Wow64ResolverTest(relaxed);
+ }
+
if (!sandbox::IsXPSP2OrLater())
return new Win2kResolverTest(relaxed);
+
+ if (os_info->version() >= base::win::VERSION_WIN8)
+ return new Win8ResolverTest(relaxed);
+
return new WinXpResolverTest(relaxed);
+#endif
}
NTSTATUS PatchNtdll(const char* function, bool relaxed) {