Index: chrome_elf/hook_util/test/hook_util_test.cc |
diff --git a/chrome_elf/hook_util/test/hook_util_test.cc b/chrome_elf/hook_util/test/hook_util_test.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ee2609c998ff0d361655584b25f30734849bd45f |
--- /dev/null |
+++ b/chrome_elf/hook_util/test/hook_util_test.cc |
@@ -0,0 +1,103 @@ |
+// Copyright 2016 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 <windows.h> |
+ |
+#include "chrome_elf/hook_util/hook_util.h" |
+// Compile in this test DLL, so that it's in the IAT. |
+#include "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() {} |
+}; |
+ |
+//------------------------------------------------------------------------------ |
+// IATHook tests |
+//------------------------------------------------------------------------------ |
+ |
+TEST_F(HookTest, IATHook) { |
+ // Sanity test with no hook. |
+ ASSERT_EQ(0, ExportedApiCallCount()); |
+ ExportedApi(); |
+ ExportedApi(); |
+ ASSERT_EQ(2, ExportedApiCallCount()); |
+ |
+ // Apply IAT hook. |
+ elf_hook::IATHook iat_hook; |
+ if (iat_hook.Hook(::GetModuleHandle(nullptr), kIATTestDllName, |
+ kIATExportedApiFunction, |
+ IATHookedExportedApi) != NO_ERROR) { |
+ ADD_FAILURE(); |
+ return; |
+ } |
+ |
+ // Make sure hooking twice with the same object fails. |
+ if (iat_hook.Hook(::GetModuleHandle(nullptr), kIATTestDllName, |
+ kIATExportedApiFunction, |
+ 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", |
+ 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, |
+ IATHookedExportedApi) != NO_ERROR) { |
+ ADD_FAILURE(); |
+ return; |
+ } |
+ elf_hook::IATHook shady_third_party_iat_hook; |
+ if (shady_third_party_iat_hook.Hook(::GetModuleHandle(nullptr), |
+ kIATTestDllName, kIATExportedApiFunction, |
+ 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 |