diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-01 23:42:58 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-01 23:42:58 +0000 |
commit | ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661 (patch) | |
tree | e98d94950f14f9230691b354e1da7d784d281ae0 /sandbox/src | |
parent | 0043ca1beb5d67cccfbd4290ce170e36ffeaff11 (diff) | |
download | chromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.zip chromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.tar.gz chromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.tar.bz2 |
Sandbox: Add the 64-bit service resolver and a few
extra bits of infrastructure.
BUG=27218
TEST=none
Review URL: http://codereview.chromium.org/558032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37764 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/src')
-rw-r--r-- | sandbox/src/interceptors.h | 27 | ||||
-rw-r--r-- | sandbox/src/interceptors_64.cc | 64 | ||||
-rw-r--r-- | sandbox/src/interceptors_64.h | 54 | ||||
-rw-r--r-- | sandbox/src/resolver_64.cc | 106 | ||||
-rw-r--r-- | sandbox/src/service_resolver_64.cc | 209 | ||||
-rw-r--r-- | sandbox/src/service_resolver_unittest.cc | 15 |
6 files changed, 319 insertions, 156 deletions
diff --git a/sandbox/src/interceptors.h b/sandbox/src/interceptors.h new file mode 100644 index 0000000..7064e07 --- /dev/null +++ b/sandbox/src/interceptors.h @@ -0,0 +1,27 @@ +// Copyright (c) 2010 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. + +#ifndef SANDBOX_SRC_INTERCEPTORS_H_ +#define SANDBOX_SRC_INTERCEPTORS_H_ + +#if defined(_WIN64) +#include "sandbox/src/interceptors_64.h" +#endif + +namespace sandbox { + +enum InterceptorId { + MAP_VIEW_OF_SECTION_ID = 0, + UNMAP_VIEW_OF_SECTION_ID, + SET_INFORMATION_THREAD_ID, + OPEN_THREAD_TOKEN_ID, + OPEN_THREAD_TOKEN_EX_ID, + MAX_ID +}; + +typedef void* OriginalFunctions[MAX_ID]; + +} // namespace sandbox + +#endif // SANDBOX_SRC_INTERCEPTORS_H_ diff --git a/sandbox/src/interceptors_64.cc b/sandbox/src/interceptors_64.cc new file mode 100644 index 0000000..77c35b8 --- /dev/null +++ b/sandbox/src/interceptors_64.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2010 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. + +#include "sandbox/src/interceptors_64.h" + +#include "sandbox/src/interceptors.h" +#include "sandbox/src/policy_target.h" +#include "sandbox/src/sandbox_nt_types.h" +#include "sandbox/src/sandbox_types.h" +#include "sandbox/src/target_interceptions.h" + +namespace sandbox { + +SANDBOX_INTERCEPT NtExports g_nt; +SANDBOX_INTERCEPT OriginalFunctions g_originals; + +NTSTATUS WINAPI TargetNtMapViewOfSection64( + HANDLE section, 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) { + NtMapViewOfSectionFunction orig_fn = reinterpret_cast< + NtMapViewOfSectionFunction>(g_originals[MAP_VIEW_OF_SECTION_ID]); + + return TargetNtMapViewOfSection(orig_fn, section, process, base, zero_bits, + commit_size, offset, view_size, inherit, + allocation_type, protect); +} + +NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, PVOID base) { + NtUnmapViewOfSectionFunction orig_fn = reinterpret_cast< + NtUnmapViewOfSectionFunction>(g_originals[UNMAP_VIEW_OF_SECTION_ID]); + return TargetNtUnmapViewOfSection(orig_fn, process, base); +} + +NTSTATUS WINAPI TargetNtSetInformationThread64( + HANDLE thread, THREAD_INFORMATION_CLASS thread_info_class, + PVOID thread_information, ULONG thread_information_bytes) { + NtSetInformationThreadFunction orig_fn = reinterpret_cast< + NtSetInformationThreadFunction>(g_originals[SET_INFORMATION_THREAD_ID]); + return TargetNtSetInformationThread(orig_fn, thread, thread_info_class, + thread_information, + thread_information_bytes); +} + +NTSTATUS WINAPI TargetNtOpenThreadToken64( + HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, + PHANDLE token) { + NtOpenThreadTokenFunction orig_fn = reinterpret_cast< + NtOpenThreadTokenFunction>(g_originals[OPEN_THREAD_TOKEN_ID]); + return TargetNtOpenThreadToken(orig_fn, thread, desired_access, open_as_self, + token); +} + +NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( + HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, + ULONG handle_attributes, PHANDLE token) { + NtOpenThreadTokenExFunction orig_fn = reinterpret_cast< + NtOpenThreadTokenExFunction>(g_originals[OPEN_THREAD_TOKEN_EX_ID]); + return TargetNtOpenThreadTokenEx(orig_fn, thread, desired_access, + open_as_self, handle_attributes, token); +} + +} // namespace sandbox diff --git a/sandbox/src/interceptors_64.h b/sandbox/src/interceptors_64.h new file mode 100644 index 0000000..8be5af4 --- /dev/null +++ b/sandbox/src/interceptors_64.h @@ -0,0 +1,54 @@ +// Copyright (c) 2010 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. + +#include "sandbox/src/nt_internals.h" +#include "sandbox/src/sandbox_types.h" + +#ifndef SANDBOX_SRC_INTERCEPTORS_64_H_ +#define SANDBOX_SRC_INTERCEPTORS_64_H_ + +namespace sandbox { + +extern "C" { + +// 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. +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtMapViewOfSection64( + HANDLE section, 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); + +// Interception of NtUnmapViewOfSection on the child process. +// It should never be called directly. This function provides the means to +// detect dlls being unloaded, so we can clean up our interceptions. +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, + PVOID base); + +// ----------------------------------------------------------------------- +// Interceptors without IPC. + +// Interception of NtSetInformationThread on the child process. +// It should never be called directly. +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread64( + HANDLE thread, THREAD_INFORMATION_CLASS thread_info_class, + PVOID thread_information, ULONG thread_information_bytes); + +// Interception of NtOpenThreadToken on the child process. +// It should never be called directly +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadToken64( + HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, + PHANDLE token); + +// Interception of NtOpenThreadTokenEx on the child process. +// It should never be called directly +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( + HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, + ULONG handle_attributes, PHANDLE token); + +} // extern "C" + +} // namespace sandbox + +#endif // SANDBOX_SRC_INTERCEPTORS_64_H_ diff --git a/sandbox/src/resolver_64.cc b/sandbox/src/resolver_64.cc new file mode 100644 index 0000000..c0accc7 --- /dev/null +++ b/sandbox/src/resolver_64.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2006-2010 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. + +#include "sandbox/src/resolver.h" + +#include "base/pe_image.h" +#include "sandbox/src/sandbox_nt_util.h" + +namespace { + +const BYTE kPushRax = 0x50; +const USHORT kMovRax = 0xB848; +const ULONG kMovRspRax = 0x24048948; +const BYTE kRetNp = 0xC3; + +#pragma pack(push, 1) +struct InternalThunk { + // This struct contains roughly the following code: + // 00 50 push rax + // 01 48b8f0debc9a78563412 mov rax,123456789ABCDEF0h + // 0b 48890424 mov qword ptr [rsp],rax + // 0f c3 ret + // + // The code modifies rax, but that should not be an issue for the common + // calling conventions. + + InternalThunk() { + push_rax = kPushRax; + mov_rax = kMovRax; + interceptor_function = 0; + mov_rsp_rax = kMovRspRax; + ret = kRetNp; + }; + BYTE push_rax; // = 50 + USHORT mov_rax; // = 48 B8 + ULONG_PTR interceptor_function; + ULONG mov_rsp_rax; // = 48 89 04 24 + BYTE ret; // = C3 +}; +#pragma pack(pop) + +} // 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; +} + +size_t ResolverThunk::GetInternalThunkSize() const { + return sizeof(InternalThunk); +} + +bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes, + const void* original_function, + const void* interceptor) { + if (storage_bytes < sizeof(InternalThunk)) + return false; + + InternalThunk* thunk = new(storage, NT_PLACE) InternalThunk; + thunk->interceptor_function = reinterpret_cast<ULONG_PTR>(interceptor); + + return true; +} + +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; +} + +} // namespace sandbox diff --git a/sandbox/src/service_resolver_64.cc b/sandbox/src/service_resolver_64.cc index 3a46d73..3045840 100644 --- a/sandbox/src/service_resolver_64.cc +++ b/sandbox/src/service_resolver_64.cc @@ -2,50 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "sandbox/wow_helper/service64_resolver.h" +#include "sandbox/src/service_resolver.h" +#include "base/logging.h" +#include "base/pe_image.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 + // This struct contains roughly the following code: + // 00 mov r10,rcx + // 03 mov eax,52h + // 08 syscall + // 0a ret + // 0b xchg ax,ax + // 0e xchg ax,ax + + ULONG mov_r10_rcx_mov_eax; // = 4C 8B D1 B8 ULONG service_id; USHORT syscall; // = 0F 05 BYTE ret; // = C3 @@ -54,49 +34,9 @@ struct ServiceEntry { 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; -}; - +// We don't have an internal thunk for x64. struct ServiceFullThunk { - sandbox::PatchInfo patch_info; ServiceEntry original; - InternalThunk internal_thunk; }; #pragma pack(pop) @@ -131,35 +71,18 @@ bool WriteProtectedChildMemory(HANDLE child_process, 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 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 ServiceResolverThunk::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); @@ -182,7 +105,7 @@ NTSTATUS Service64ResolverThunk::Setup(const void* target_module, return ret; } -NTSTATUS Service64ResolverThunk::ResolveInterceptor( +NTSTATUS ServiceResolverThunk::ResolveInterceptor( const void* interceptor_module, const char* interceptor_name, const void** address) { @@ -194,13 +117,15 @@ NTSTATUS Service64ResolverThunk::ResolveInterceptor( // In this case all the work is done from the parent, so resolve is // just a simple GetProcAddress. -NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module, +NTSTATUS ServiceResolverThunk::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); + PEImage module_image(module); + *address = module_image.GetProcAddress(function_name); if (NULL == *address) return STATUS_UNSUCCESSFUL; @@ -208,11 +133,11 @@ NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module, return STATUS_SUCCESS; } -size_t Service64ResolverThunk::GetThunkSize() const { +size_t ServiceResolverThunk::GetThunkSize() const { return sizeof(ServiceFullThunk); } -bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const { +bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { ServiceEntry function_code; SIZE_T read; if (!::ReadProcessMemory(process_, target_, &function_code, @@ -222,65 +147,32 @@ bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const { if (sizeof(function_code) != read) return false; - if (kMmovR10EcxMovEax != function_code.mov_r10_ecx_mov_eax || + if (kMmovR10EcxMovEax != function_code.mov_r10_rcx_mov_eax || kSyscall != function_code.syscall || kRetNp != function_code.ret) return false; - // Save the verified code + // Save the verified code. memcpy(local_thunk, &function_code, sizeof(function_code)); return true; } -NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk, - void* remote_thunk) { +NTSTATUS ServiceResolverThunk::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; + remote_thunk); // 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)) + ServiceEntry local_service; + DCHECK_GE(GetInternalThunkSize(), sizeof(local_service)); + if (!SetInternalThunk(&local_service, sizeof(local_service), NULL, + interceptor_)) 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 + // Copy the local thunk buffer to the child. + SIZE_T actual; if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, sizeof(ServiceFullThunk), &actual)) return STATUS_UNSUCCESSFUL; @@ -288,12 +180,29 @@ NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk, if (sizeof(ServiceFullThunk) != actual) return STATUS_UNSUCCESSFUL; - // and now change the function to intercept, on the child - if (!::WriteProtectedChildMemory(process_, target_, &local_service, + // And now change the function to intercept, on the child. + if (NULL != ntdll_base_) { + // Running a unit test. + if (!::WriteProcessMemory(process_, target_, &local_service, + sizeof(local_service), &actual)) + return STATUS_UNSUCCESSFUL; + } else { + if (!WriteProtectedChildMemory(process_, target_, &local_service, sizeof(local_service))) - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; + } return STATUS_SUCCESS; } +bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { + NOTREACHED(); + return false; +} + +bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { + NOTREACHED(); + return false; +} + } // namespace sandbox diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc index 3af81f2..ee26c9e 100644 --- a/sandbox/src/service_resolver_unittest.cc +++ b/sandbox/src/service_resolver_unittest.cc @@ -36,7 +36,7 @@ class ResolverThunkTest : public T { const char* interceptor_name, const void* interceptor_entry_point, void* thunk_storage, - uint32 storage_bytes) { + size_t storage_bytes) { NTSTATUS ret = STATUS_SUCCESS; ret = ResolverThunk::Init(target_module, interceptor_module, target_name, interceptor_name, interceptor_entry_point, @@ -86,7 +86,7 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) { void* function_entry = resolver; size_t thunk_size = resolver->GetThunkSize(); scoped_array<char> thunk(new char[thunk_size]); - uint32 used; + size_t used; NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry, thunk.get(), thunk_size, @@ -125,14 +125,16 @@ TEST(ServiceResolverTest, PatchesServices) { } TEST(ServiceResolverTest, FailsIfNotService) { - NTSTATUS ret = PatchNtdll("RtlUlongByteSwap", false); - EXPECT_NE(STATUS_SUCCESS, ret); +#if !defined(_WIN64) + EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false)); +#endif - ret = PatchNtdll("LdrLoadDll", false); - EXPECT_NE(STATUS_SUCCESS, ret); + EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false)); } TEST(ServiceResolverTest, PatchesPatchedServices) { +// We don't support "relaxed mode" for Win64 apps. +#if !defined(_WIN64) NTSTATUS ret = PatchNtdll("NtClose", true); EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError(); @@ -147,6 +149,7 @@ TEST(ServiceResolverTest, PatchesPatchedServices) { ret = PatchNtdll("NtMapViewOfSection", true); EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " << ::GetLastError(); +#endif } } // namespace |