diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-25 20:00:06 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-25 20:00:06 +0000 |
commit | 2b98e225b48f97766d42e630bf78bd489ecc9f5c (patch) | |
tree | 4b287d59d2ac8876b260f6aad621d96468057b40 | |
parent | 574fde8a446ef302afaf92e9ab1586855c657777 (diff) | |
download | chromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.zip chromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.tar.gz chromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.tar.bz2 |
Sandbox: Make sure that we reset relative_jump_ before
performing every patch.
BUG=69952
TEST=sbox_unittests
Review URL: http://codereview.chromium.org/6528033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76089 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | sandbox/src/resolver.h | 2 | ||||
-rw-r--r-- | sandbox/src/service_resolver_32.cc | 1 | ||||
-rw-r--r-- | sandbox/src/service_resolver_unittest.cc | 83 |
3 files changed, 73 insertions, 13 deletions
diff --git a/sandbox/src/resolver.h b/sandbox/src/resolver.h index 0ee3e9a..7ec0bf5 100644 --- a/sandbox/src/resolver.h +++ b/sandbox/src/resolver.h @@ -41,6 +41,8 @@ class ResolverThunk { // // In general, the idea is to allocate a single big buffer for all // interceptions on the same dll, and call Setup n times. + // WARNING: This means that any data member that is specific to a single + // interception must be reset within this method. virtual NTSTATUS Setup(const void* target_module, const void* interceptor_module, const char* target_name, diff --git a/sandbox/src/service_resolver_32.cc b/sandbox/src/service_resolver_32.cc index 01c2f0b..c731607 100644 --- a/sandbox/src/service_resolver_32.cc +++ b/sandbox/src/service_resolver_32.cc @@ -113,6 +113,7 @@ NTSTATUS ServiceResolverThunk::Setup(const void* target_module, if (!NT_SUCCESS(ret)) return ret; + relative_jump_ = 0; size_t thunk_bytes = GetThunkSize(); scoped_array<char> thunk_buffer(new char[thunk_bytes]); ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>( diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc index 1756017..793d4a1 100644 --- a/sandbox/src/service_resolver_unittest.cc +++ b/sandbox/src/service_resolver_unittest.cc @@ -59,7 +59,27 @@ typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest; typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest; typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest; -NTSTATUS PatchNtdll(const char* function, bool relaxed) { +const BYTE kJump32 = 0xE9; + +void CheckJump(void* source, void* target) { +#pragma pack(push) +#pragma pack(1) + struct Code { + BYTE jump; + ULONG delta; + }; +#pragma pack(pop) + + 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); +} + +NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed, + sandbox::ServiceResolverThunk* resolver) { HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll"); EXPECT_TRUE(NULL != ntdll_base); @@ -68,17 +88,8 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) { if (NULL == target) return STATUS_UNSUCCESSFUL; - char service[50]; + BYTE service[50]; memcpy(service, target, sizeof(service)); - sandbox::Wow64 WowHelper(NULL, ntdll_base); - - sandbox::ServiceResolverThunk* resolver; - if (WowHelper.IsWow64()) - resolver = new Wow64ResolverTest(relaxed); - else if (!sandbox::IsXPSP2OrLater()) - resolver = new Win2kResolverTest(relaxed); - else - resolver = new WinXpResolverTest(relaxed); static_cast<WinXpResolverTest*>(resolver)->set_target(service); @@ -94,16 +105,40 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) { if (NT_SUCCESS(ret)) { EXPECT_EQ(thunk_size, used); EXPECT_NE(0, memcmp(service, target, sizeof(service))); + EXPECT_NE(kJump32, service[0]); if (relaxed) { - // It's already patched, let's patch again. + // It's already patched, let's patch again, and simulate a direct patch. + service[0] = kJump32; ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry, thunk.get(), thunk_size, &used); + CheckJump(service, thunk.get()); } } - delete resolver; + return ret; +} + +sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) { + HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll"); + EXPECT_TRUE(NULL != ntdll_base); + sandbox::Wow64 WowHelper(NULL, ntdll_base); + + sandbox::ServiceResolverThunk* resolver; + if (WowHelper.IsWow64()) + resolver = new Wow64ResolverTest(relaxed); + else if (!sandbox::IsXPSP2OrLater()) + resolver = new Win2kResolverTest(relaxed); + else + resolver = new WinXpResolverTest(relaxed); + return resolver; +} +NTSTATUS PatchNtdll(const char* function, bool relaxed) { + sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed); + + NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver); + delete resolver; return ret; } @@ -152,4 +187,26 @@ TEST(ServiceResolverTest, PatchesPatchedServices) { #endif } +TEST(ServiceResolverTest, MultiplePatchedServices) { +// We don't support "relaxed mode" for Win64 apps. +#if !defined(_WIN64) + sandbox::ServiceResolverThunk* resolver = GetTestResolver(true); + NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver); + EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError(); + + ret = PatchNtdllWithResolver("NtCreateFile", true, resolver); + EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " << + ::GetLastError(); + + ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver); + EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " << + ::GetLastError(); + + ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver); + EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " << + ::GetLastError(); + delete resolver; +#endif +} + } // namespace |