security/sandbox/win/src/service_resolver_unittest.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2012 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.
     5 // This file contains unit tests for ServiceResolverThunk.
     7 #include "base/basictypes.h"
     8 #include "base/memory/scoped_ptr.h"
     9 #include "base/win/windows_version.h"
    10 #include "sandbox/win/src/resolver.h"
    11 #include "sandbox/win/src/sandbox_utils.h"
    12 #include "sandbox/win/src/service_resolver.h"
    13 #include "testing/gtest/include/gtest/gtest.h"
    15 namespace {
    17 // This is the concrete resolver used to perform service-call type functions
    18 // inside ntdll.dll.
    19 template<typename T>
    20 class ResolverThunkTest : public T {
    21  public:
    22   // The service resolver needs a child process to write to.
    23   explicit ResolverThunkTest(bool relaxed)
    24       : T(::GetCurrentProcess(), relaxed) {}
    26   // Sets the interception target to the desired address.
    27   void set_target(void* target) {
    28     fake_target_ = target;
    29   }
    31  protected:
    32   // Overrides Resolver::Init
    33   virtual NTSTATUS Init(const void* target_module,
    34                         const void* interceptor_module,
    35                         const char* target_name,
    36                         const char* interceptor_name,
    37                         const void* interceptor_entry_point,
    38                         void* thunk_storage,
    39                         size_t storage_bytes) {
    40     NTSTATUS ret = STATUS_SUCCESS;
    41     ret = ResolverThunk::Init(target_module, interceptor_module, target_name,
    42                               interceptor_name, interceptor_entry_point,
    43                               thunk_storage, storage_bytes);
    44     EXPECT_EQ(STATUS_SUCCESS, ret);
    46     target_ = fake_target_;
    47     ntdll_base_ = ::GetModuleHandle(L"ntdll.dll");
    48     return ret;
    49   };
    51  private:
    52   // Holds the address of the fake target.
    53   void* fake_target_;
    55   DISALLOW_COPY_AND_ASSIGN(ResolverThunkTest);
    56 };
    58 typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest;
    60 #if !defined(_WIN64)
    61 typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest;
    62 typedef ResolverThunkTest<sandbox::Win8ResolverThunk> Win8ResolverTest;
    63 typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest;
    64 typedef ResolverThunkTest<sandbox::Wow64W8ResolverThunk> Wow64W8ResolverTest;
    65 #endif
    67 const BYTE kJump32 = 0xE9;
    69 void CheckJump(void* source, void* target) {
    70 #pragma pack(push)
    71 #pragma pack(1)
    72   struct Code {
    73     BYTE jump;
    74     ULONG delta;
    75   };
    76 #pragma pack(pop)
    78 #if defined(_WIN64)
    79   FAIL() << "Running 32-bit codepath";
    80 #else
    81   Code* patched = reinterpret_cast<Code*>(source);
    82   EXPECT_EQ(kJump32, patched->jump);
    84   ULONG source_addr = bit_cast<ULONG>(source);
    85   ULONG target_addr = bit_cast<ULONG>(target);
    86   EXPECT_EQ(target_addr + 19 - source_addr, patched->delta);
    87 #endif
    88 }
    90 NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
    91                                 sandbox::ServiceResolverThunk* resolver) {
    92   HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
    93   EXPECT_TRUE(NULL != ntdll_base);
    95   void* target = ::GetProcAddress(ntdll_base, function);
    96   EXPECT_TRUE(NULL != target);
    97   if (NULL == target)
    98     return STATUS_UNSUCCESSFUL;
   100   BYTE service[50];
   101   memcpy(service, target, sizeof(service));
   103   static_cast<WinXpResolverTest*>(resolver)->set_target(service);
   105   // Any pointer will do as an interception_entry_point
   106   void* function_entry = resolver;
   107   size_t thunk_size = resolver->GetThunkSize();
   108   scoped_ptr<char[]> thunk(new char[thunk_size]);
   109   size_t used;
   111   NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL,
   112                                  function_entry, thunk.get(), thunk_size,
   113                                  &used);
   114   if (NT_SUCCESS(ret)) {
   115     EXPECT_EQ(thunk_size, used);
   116     EXPECT_NE(0, memcmp(service, target, sizeof(service)));
   117     EXPECT_NE(kJump32, service[0]);
   119     if (relaxed) {
   120       // It's already patched, let's patch again, and simulate a direct patch.
   121       service[0] = kJump32;
   122       ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry,
   123                             thunk.get(), thunk_size, &used);
   124       CheckJump(service, thunk.get());
   125     }
   126   }
   128   return ret;
   129 }
   131 sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) {
   132 #if defined(_WIN64)
   133   return new WinXpResolverTest(relaxed);
   134 #else
   135   base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
   136   if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
   137     if (os_info->version() >= base::win::VERSION_WIN8)
   138       return new Wow64W8ResolverTest(relaxed);
   139     return new Wow64ResolverTest(relaxed);
   140   }
   142   if (!sandbox::IsXPSP2OrLater())
   143     return new Win2kResolverTest(relaxed);
   145   if (os_info->version() >= base::win::VERSION_WIN8)
   146     return new Win8ResolverTest(relaxed);
   148   return new WinXpResolverTest(relaxed);
   149 #endif
   150 }
   152 NTSTATUS PatchNtdll(const char* function, bool relaxed) {
   153   sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed);
   155   NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver);
   156   delete resolver;
   157   return ret;
   158 }
   160 TEST(ServiceResolverTest, PatchesServices) {
   161   NTSTATUS ret = PatchNtdll("NtClose", false);
   162   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
   164   ret = PatchNtdll("NtCreateFile", false);
   165   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
   166     ::GetLastError();
   168   ret = PatchNtdll("NtCreateMutant", false);
   169   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
   170     ::GetLastError();
   172   ret = PatchNtdll("NtMapViewOfSection", false);
   173   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
   174     ::GetLastError();
   175 }
   177 TEST(ServiceResolverTest, FailsIfNotService) {
   178 #if !defined(_WIN64)
   179   EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false));
   180 #endif
   182   EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false));
   183 }
   185 TEST(ServiceResolverTest, PatchesPatchedServices) {
   186 // We don't support "relaxed mode" for Win64 apps.
   187 #if !defined(_WIN64)
   188   NTSTATUS ret = PatchNtdll("NtClose", true);
   189   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
   191   ret = PatchNtdll("NtCreateFile", true);
   192   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
   193     ::GetLastError();
   195   ret = PatchNtdll("NtCreateMutant", true);
   196   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
   197     ::GetLastError();
   199   ret = PatchNtdll("NtMapViewOfSection", true);
   200   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
   201     ::GetLastError();
   202 #endif
   203 }
   205 TEST(ServiceResolverTest, MultiplePatchedServices) {
   206 // We don't support "relaxed mode" for Win64 apps.
   207 #if !defined(_WIN64)
   208   sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
   209   NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver);
   210   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
   212   ret = PatchNtdllWithResolver("NtCreateFile", true, resolver);
   213   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
   214     ::GetLastError();
   216   ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver);
   217   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
   218     ::GetLastError();
   220   ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver);
   221   EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
   222     ::GetLastError();
   223   delete resolver;
   224 #endif
   225 }
   227 }  // namespace

mercurial