1// Copyright 2014 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. 4 5#include "chrome/app/close_handle_hook_win.h" 6 7#include <Windows.h> 8 9#include <vector> 10 11#include "base/files/file_path.h" 12#include "base/lazy_instance.h" 13#include "base/strings/string16.h" 14#include "base/win/iat_patch_function.h" 15#include "base/win/scoped_handle.h" 16#include "chrome/common/chrome_version_info.h" 17 18namespace { 19 20typedef BOOL (WINAPI* CloseHandleType) (HANDLE handle); 21CloseHandleType g_close_function = NULL; 22 23// The entry point for CloseHandle interception. This function notifies the 24// verifier about the handle that is being closed, and calls the original 25// function. 26BOOL WINAPI CloseHandleHook(HANDLE handle) { 27 base::win::OnHandleBeingClosed(handle); 28 return g_close_function(handle); 29} 30 31// Keeps track of all the hooks needed to intercept CloseHandle. 32class CloseHandleHooks { 33 public: 34 CloseHandleHooks() {} 35 ~CloseHandleHooks() {} 36 37 void AddIATPatch(const base::string16& module); 38 void Unpatch(); 39 40 private: 41 std::vector<base::win::IATPatchFunction*> hooks_; 42 DISALLOW_COPY_AND_ASSIGN(CloseHandleHooks); 43}; 44base::LazyInstance<CloseHandleHooks> g_hooks = LAZY_INSTANCE_INITIALIZER; 45 46void CloseHandleHooks::AddIATPatch(const base::string16& module) { 47 if (module.empty()) 48 return; 49 50 base::win::IATPatchFunction* patch = new base::win::IATPatchFunction; 51 patch->Patch(module.c_str(), "kernel32.dll", "CloseHandle", CloseHandleHook); 52 hooks_.push_back(patch); 53 if (!g_close_function) { 54 // Things are probably messed up if each intercepted function points to 55 // a different place, but we need only one function to call. 56 g_close_function = 57 reinterpret_cast<CloseHandleType>(patch->original_function()); 58 } 59} 60 61void CloseHandleHooks::Unpatch() { 62 for (std::vector<base::win::IATPatchFunction*>::iterator it = hooks_.begin(); 63 it != hooks_.end(); ++it) { 64 (*it)->Unpatch(); 65 } 66} 67 68bool UseHooks() { 69 return false; 70} 71 72base::string16 GetModuleName(HMODULE module) { 73 base::string16 name; 74 if (!module) 75 return name; 76 wchar_t buffer[MAX_PATH]; 77 int rv = GetModuleFileName(module, buffer, MAX_PATH); 78 if (rv == MAX_PATH) 79 return name; 80 81 buffer[MAX_PATH - 1] = L'\0'; 82 name.assign(buffer); 83 base::FilePath path(name); 84 return path.BaseName().AsUTF16Unsafe(); 85} 86 87HMODULE GetChromeDLLModule() { 88 HMODULE module; 89 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 90 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 91 reinterpret_cast<wchar_t*>(&GetChromeDLLModule), 92 &module)) { 93 return NULL; 94 } 95 return module; 96} 97 98} // namespace 99 100void InstallCloseHandleHooks() { 101 if (UseHooks()) { 102 CloseHandleHooks* hooks = g_hooks.Pointer(); 103 hooks->AddIATPatch(L"chrome.exe"); 104 hooks->AddIATPatch(GetModuleName(GetChromeDLLModule())); 105 } else { 106 base::win::DisableHandleVerifier(); 107 } 108} 109 110void RemoveCloseHandleHooks() { 111 g_hooks.Get().Unpatch(); 112} 113