123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- // Copyright 2017 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 "base/win/com_init_check_hook.h"
- #include <objbase.h>
- #include <shlobj.h>
- #include <wrl/client.h>
- #include "base/test/gtest_util.h"
- #include "base/win/com_init_util.h"
- #include "base/win/patch_util.h"
- #include "base/win/scoped_com_initializer.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace base {
- namespace win {
- using Microsoft::WRL::ComPtr;
- TEST(ComInitCheckHook, AssertNotInitialized) {
- ComInitCheckHook com_check_hook;
- AssertComApartmentType(ComApartmentType::NONE);
- ComPtr<IUnknown> shell_link;
- #if defined(COM_INIT_CHECK_HOOK_ENABLED)
- EXPECT_DCHECK_DEATH(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
- #else
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
- #endif
- }
- TEST(ComInitCheckHook, HookRemoval) {
- AssertComApartmentType(ComApartmentType::NONE);
- { ComInitCheckHook com_check_hook; }
- ComPtr<IUnknown> shell_link;
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
- }
- TEST(ComInitCheckHook, NoAssertComInitialized) {
- ComInitCheckHook com_check_hook;
- ScopedCOMInitializer com_initializer;
- ComPtr<IUnknown> shell_link;
- EXPECT_TRUE(SUCCEEDED(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link))));
- }
- TEST(ComInitCheckHook, MultipleHooks) {
- ComInitCheckHook com_check_hook_1;
- ComInitCheckHook com_check_hook_2;
- AssertComApartmentType(ComApartmentType::NONE);
- ComPtr<IUnknown> shell_link;
- #if defined(COM_INIT_CHECK_HOOK_ENABLED)
- EXPECT_DCHECK_DEATH(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
- #else
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
- #endif
- }
- TEST(ComInitCheckHook, UnexpectedHook) {
- #if defined(COM_INIT_CHECK_HOOK_ENABLED)
- HMODULE ole32_library = ::LoadLibrary(L"ole32.dll");
- ASSERT_TRUE(ole32_library);
- uint32_t co_create_instance_padded_address =
- reinterpret_cast<uint32_t>(
- GetProcAddress(ole32_library, "CoCreateInstance")) -
- 5;
- const unsigned char* co_create_instance_bytes =
- reinterpret_cast<const unsigned char*>(co_create_instance_padded_address);
- const unsigned char original_byte = co_create_instance_bytes[0];
- const unsigned char unexpected_byte = 0xdb;
- ASSERT_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&unexpected_byte),
- sizeof(unexpected_byte)));
- EXPECT_DCHECK_DEATH({ ComInitCheckHook com_check_hook; });
- // If this call fails, really bad things are going to happen to other tests
- // so CHECK here.
- CHECK_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&original_byte),
- sizeof(original_byte)));
- ::FreeLibrary(ole32_library);
- ole32_library = nullptr;
- #endif
- }
- TEST(ComInitCheckHook, ExternallyHooked) {
- #if defined(COM_INIT_CHECK_HOOK_ENABLED)
- HMODULE ole32_library = ::LoadLibrary(L"ole32.dll");
- ASSERT_TRUE(ole32_library);
- uint32_t co_create_instance_address = reinterpret_cast<uint32_t>(
- GetProcAddress(ole32_library, "CoCreateInstance"));
- const unsigned char* co_create_instance_bytes =
- reinterpret_cast<const unsigned char*>(co_create_instance_address);
- const unsigned char original_byte = co_create_instance_bytes[0];
- const unsigned char jmp_byte = 0xe9;
- ASSERT_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_address),
- reinterpret_cast<const void*>(&jmp_byte), sizeof(jmp_byte)));
- // Externally patched instances should crash so we catch these cases on bots.
- EXPECT_DCHECK_DEATH({ ComInitCheckHook com_check_hook; });
- // If this call fails, really bad things are going to happen to other tests
- // so CHECK here.
- CHECK_EQ(
- static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(reinterpret_cast<void*>(co_create_instance_address),
- reinterpret_cast<const void*>(&original_byte),
- sizeof(original_byte)));
- ::FreeLibrary(ole32_library);
- ole32_library = nullptr;
- #endif
- }
- TEST(ComInitCheckHook, UnexpectedChangeDuringHook) {
- #if defined(COM_INIT_CHECK_HOOK_ENABLED)
- HMODULE ole32_library = ::LoadLibrary(L"ole32.dll");
- ASSERT_TRUE(ole32_library);
- uint32_t co_create_instance_padded_address =
- reinterpret_cast<uint32_t>(
- GetProcAddress(ole32_library, "CoCreateInstance")) -
- 5;
- const unsigned char* co_create_instance_bytes =
- reinterpret_cast<const unsigned char*>(co_create_instance_padded_address);
- const unsigned char original_byte = co_create_instance_bytes[0];
- const unsigned char unexpected_byte = 0xdb;
- ASSERT_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&unexpected_byte),
- sizeof(unexpected_byte)));
- EXPECT_DCHECK_DEATH({
- ComInitCheckHook com_check_hook;
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&unexpected_byte),
- sizeof(unexpected_byte));
- });
- // If this call fails, really bad things are going to happen to other tests
- // so CHECK here.
- CHECK_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&original_byte),
- sizeof(original_byte)));
- ::FreeLibrary(ole32_library);
- ole32_library = nullptr;
- #endif
- }
- } // namespace win
- } // namespace base
|