1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/policy/win/hook_util/hook_util.h"
#include <windows.h>
// Compile in this test DLL, so that it's in the IAT.
#include "chrome/chrome_elf/hook_util/test/hook_util_test_dll.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// IATHook test constants.
const char kIATTestDllName[] = "hook_util_test_dll.dll";
const char kIATExportedApiFunction[] = "ExportedApi";
// IATHook function, which does nothing.
void IATHookedExportedApi() {
return;
}
// Shady third-party IATHook function, which also does nothing, but different
// chunk of code/address.
void IATHookedExportedApiTwo() {
printf("Something to make this function different!\n");
return;
}
class HookTest : public testing::Test {
protected:
HookTest() = default;
};
//------------------------------------------------------------------------------
// IATHook tests
//------------------------------------------------------------------------------
TEST_F(HookTest, IATHook) {
// Sanity test with no hook.
ASSERT_EQ(0, ExportedApiCallCount());
ExportedApi();
ExportedApi();
ASSERT_EQ(2, ExportedApiCallCount());
// Apply IAT hook.
sandbox::policy::IATHook iat_hook;
if (iat_hook.Hook(
::GetModuleHandle(nullptr), kIATTestDllName, kIATExportedApiFunction,
reinterpret_cast<void*>(IATHookedExportedApi)) != NO_ERROR) {
ADD_FAILURE();
return;
}
// Make sure hooking twice with the same object fails.
if (iat_hook.Hook(::GetModuleHandle(nullptr), kIATTestDllName,
kIATExportedApiFunction,
reinterpret_cast<void*>(IATHookedExportedApi)) !=
ERROR_SHARING_VIOLATION)
ADD_FAILURE();
// Call count should not change with hook.
ExportedApi();
ExportedApi();
ExportedApi();
EXPECT_EQ(2, ExportedApiCallCount());
// Remove hook.
if (iat_hook.Unhook() != NO_ERROR)
ADD_FAILURE();
// Sanity test things are back to normal.
ExportedApi();
EXPECT_EQ(3, ExportedApiCallCount());
// Double unhook should fail.
if (iat_hook.Unhook() != ERROR_INVALID_PARAMETER)
ADD_FAILURE();
// Try hooking a non-existent function.
if (iat_hook.Hook(::GetModuleHandle(nullptr), kIATTestDllName, "FooBarred",
reinterpret_cast<void*>(IATHookedExportedApi)) !=
ERROR_PROC_NOT_FOUND)
ADD_FAILURE();
// Test the case where someone else hooks our hook! Unhook() should leave it.
if (iat_hook.Hook(
::GetModuleHandle(nullptr), kIATTestDllName, kIATExportedApiFunction,
reinterpret_cast<void*>(IATHookedExportedApi)) != NO_ERROR) {
ADD_FAILURE();
return;
}
sandbox::policy::IATHook shady_third_party_iat_hook;
if (shady_third_party_iat_hook.Hook(
::GetModuleHandle(nullptr), kIATTestDllName, kIATExportedApiFunction,
reinterpret_cast<void*>(IATHookedExportedApiTwo)) != NO_ERROR)
ADD_FAILURE();
if (iat_hook.Unhook() != ERROR_INVALID_FUNCTION)
ADD_FAILURE();
if (shady_third_party_iat_hook.Unhook() != NO_ERROR)
ADD_FAILURE();
// NOTE: the first hook was left in and couldn't be cleaned up.
}
} // namespace
|