• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
CloseHandleHook(HANDLE handle)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:
CloseHandleHooks()34   CloseHandleHooks() {}
~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 
AddIATPatch(const base::string16 & module)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 
Unpatch()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 
UseHooks()68 bool UseHooks() {
69   return false;
70 }
71 
GetModuleName(HMODULE module)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 
GetChromeDLLModule()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 
InstallCloseHandleHooks()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 
RemoveCloseHandleHooks()110 void RemoveCloseHandleHooks() {
111   g_hooks.Get().Unpatch();
112 }
113