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 18 namespace { 19 20 typedef BOOL (WINAPI* CloseHandleType) (HANDLE handle); 21 CloseHandleType 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. 26 BOOL 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. 32 class 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 }; 44 base::LazyInstance<CloseHandleHooks> g_hooks = LAZY_INSTANCE_INITIALIZER; 45 46 void 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 61 void CloseHandleHooks::Unpatch() { 62 for (std::vector<base::win::IATPatchFunction*>::iterator it = hooks_.begin(); 63 it != hooks_.end(); ++it) { 64 (*it)->Unpatch(); 65 } 66 } 67 68 bool UseHooks() { 69 return false; 70 } 71 72 base::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 87 HMODULE 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 100 void 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 110 void RemoveCloseHandleHooks() { 111 g_hooks.Get().Unpatch(); 112 } 113