Index: app/win/iat_patch_function.cc |
diff --git a/app/win/iat_patch_function.cc b/app/win/iat_patch_function.cc |
deleted file mode 100644 |
index 9abd6f22f56a5ba5c0fe91a44464a59359d758db..0000000000000000000000000000000000000000 |
--- a/app/win/iat_patch_function.cc |
+++ /dev/null |
@@ -1,278 +0,0 @@ |
-// Copyright (c) 2011 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 "app/win/iat_patch_function.h" |
- |
-#include "base/logging.h" |
-#include "base/win/pe_image.h" |
- |
-namespace app { |
-namespace win { |
- |
-namespace { |
- |
-struct InterceptFunctionInformation { |
- bool finished_operation; |
- const char* imported_from_module; |
- const char* function_name; |
- void* new_function; |
- void** old_function; |
- IMAGE_THUNK_DATA** iat_thunk; |
- DWORD return_code; |
-}; |
- |
-void* GetIATFunction(IMAGE_THUNK_DATA* iat_thunk) { |
- if (NULL == iat_thunk) { |
- NOTREACHED(); |
- return NULL; |
- } |
- |
- // Works around the 64 bit portability warning: |
- // The Function member inside IMAGE_THUNK_DATA is really a pointer |
- // to the IAT function. IMAGE_THUNK_DATA correctly maps to IMAGE_THUNK_DATA32 |
- // or IMAGE_THUNK_DATA64 for correct pointer size. |
- union FunctionThunk { |
- IMAGE_THUNK_DATA thunk; |
- void* pointer; |
- } iat_function; |
- |
- iat_function.thunk = *iat_thunk; |
- return iat_function.pointer; |
-} |
-// Change the page protection (of code pages) to writable and copy |
-// the data at the specified location |
-// |
-// Arguments: |
-// old_code Target location to copy |
-// new_code Source |
-// length Number of bytes to copy |
-// |
-// Returns: Windows error code (winerror.h). NO_ERROR if successful |
-DWORD ModifyCode(void* old_code, void* new_code, int length) { |
- if ((NULL == old_code) || (NULL == new_code) || (0 == length)) { |
- NOTREACHED(); |
- return ERROR_INVALID_PARAMETER; |
- } |
- |
- // Change the page protection so that we can write. |
- DWORD error = NO_ERROR; |
- DWORD old_page_protection = 0; |
- if (VirtualProtect(old_code, |
- length, |
- PAGE_READWRITE, |
- &old_page_protection)) { |
- |
- // Write the data. |
- CopyMemory(old_code, new_code, length); |
- |
- // Restore the old page protection. |
- error = ERROR_SUCCESS; |
- VirtualProtect(old_code, |
- length, |
- old_page_protection, |
- &old_page_protection); |
- } else { |
- error = GetLastError(); |
- NOTREACHED(); |
- } |
- |
- return error; |
-} |
- |
-bool InterceptEnumCallback(const base::win::PEImage& image, const char* module, |
- DWORD ordinal, const char* name, DWORD hint, |
- IMAGE_THUNK_DATA* iat, void* cookie) { |
- InterceptFunctionInformation* intercept_information = |
- reinterpret_cast<InterceptFunctionInformation*>(cookie); |
- |
- if (NULL == intercept_information) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- DCHECK(module); |
- |
- if ((0 == lstrcmpiA(module, intercept_information->imported_from_module)) && |
- (NULL != name) && |
- (0 == lstrcmpiA(name, intercept_information->function_name))) { |
- // Save the old pointer. |
- if (NULL != intercept_information->old_function) { |
- *(intercept_information->old_function) = GetIATFunction(iat); |
- } |
- |
- if (NULL != intercept_information->iat_thunk) { |
- *(intercept_information->iat_thunk) = iat; |
- } |
- |
- // portability check |
- COMPILE_ASSERT(sizeof(iat->u1.Function) == |
- sizeof(intercept_information->new_function), unknown_IAT_thunk_format); |
- |
- // Patch the function. |
- intercept_information->return_code = |
- ModifyCode(&(iat->u1.Function), |
- &(intercept_information->new_function), |
- sizeof(intercept_information->new_function)); |
- |
- // Terminate further enumeration. |
- intercept_information->finished_operation = true; |
- return false; |
- } |
- |
- return true; |
-} |
- |
-// Helper to intercept a function in an import table of a specific |
-// module. |
-// |
-// Arguments: |
-// module_handle Module to be intercepted |
-// imported_from_module Module that exports the symbol |
-// function_name Name of the API to be intercepted |
-// new_function Interceptor function |
-// old_function Receives the original function pointer |
-// iat_thunk Receives pointer to IAT_THUNK_DATA |
-// for the API from the import table. |
-// |
-// Returns: Returns NO_ERROR on success or Windows error code |
-// as defined in winerror.h |
-DWORD InterceptImportedFunction(HMODULE module_handle, |
- const char* imported_from_module, |
- const char* function_name, void* new_function, |
- void** old_function, |
- IMAGE_THUNK_DATA** iat_thunk) { |
- if ((NULL == module_handle) || (NULL == imported_from_module) || |
- (NULL == function_name) || (NULL == new_function)) { |
- NOTREACHED(); |
- return ERROR_INVALID_PARAMETER; |
- } |
- |
- base::win::PEImage target_image(module_handle); |
- if (!target_image.VerifyMagic()) { |
- NOTREACHED(); |
- return ERROR_INVALID_PARAMETER; |
- } |
- |
- InterceptFunctionInformation intercept_information = { |
- false, |
- imported_from_module, |
- function_name, |
- new_function, |
- old_function, |
- iat_thunk, |
- ERROR_GEN_FAILURE}; |
- |
- // First go through the IAT. If we don't find the import we are looking |
- // for in IAT, search delay import table. |
- target_image.EnumAllImports(InterceptEnumCallback, &intercept_information); |
- if (!intercept_information.finished_operation) { |
- target_image.EnumAllDelayImports(InterceptEnumCallback, |
- &intercept_information); |
- } |
- |
- return intercept_information.return_code; |
-} |
- |
-// Restore intercepted IAT entry with the original function. |
-// |
-// Arguments: |
-// intercept_function Interceptor function |
-// original_function Receives the original function pointer |
-// |
-// Returns: Returns NO_ERROR on success or Windows error code |
-// as defined in winerror.h |
-DWORD RestoreImportedFunction(void* intercept_function, |
- void* original_function, |
- IMAGE_THUNK_DATA* iat_thunk) { |
- if ((NULL == intercept_function) || (NULL == original_function) || |
- (NULL == iat_thunk)) { |
- NOTREACHED(); |
- return ERROR_INVALID_PARAMETER; |
- } |
- |
- if (GetIATFunction(iat_thunk) != intercept_function) { |
- // Check if someone else has intercepted on top of us. |
- // We cannot unpatch in this case, just raise a red flag. |
- NOTREACHED(); |
- return ERROR_INVALID_FUNCTION; |
- } |
- |
- return ModifyCode(&(iat_thunk->u1.Function), |
- &original_function, |
- sizeof(original_function)); |
-} |
- |
-} // namespace |
- |
-IATPatchFunction::IATPatchFunction() |
- : module_handle_(NULL), |
- original_function_(NULL), |
- iat_thunk_(NULL), |
- intercept_function_(NULL) { |
-} |
- |
-IATPatchFunction::~IATPatchFunction() { |
- if (NULL != intercept_function_) { |
- DWORD error = Unpatch(); |
- DCHECK_EQ(static_cast<DWORD>(NO_ERROR), error); |
- } |
-} |
- |
-DWORD IATPatchFunction::Patch(const wchar_t* module, |
- const char* imported_from_module, |
- const char* function_name, |
- void* new_function) { |
- DCHECK_EQ(static_cast<void*>(NULL), original_function_); |
- DCHECK_EQ(static_cast<IMAGE_THUNK_DATA*>(NULL), iat_thunk_); |
- DCHECK_EQ(static_cast<void*>(NULL), intercept_function_); |
- |
- HMODULE module_handle = LoadLibraryW(module); |
- |
- if (module_handle == NULL) { |
- NOTREACHED(); |
- return GetLastError(); |
- } |
- |
- DWORD error = InterceptImportedFunction(module_handle, |
- imported_from_module, |
- function_name, |
- new_function, |
- &original_function_, |
- &iat_thunk_); |
- |
- if (NO_ERROR == error) { |
- DCHECK_NE(original_function_, intercept_function_); |
- module_handle_ = module_handle; |
- intercept_function_ = new_function; |
- } else { |
- FreeLibrary(module_handle); |
- } |
- |
- return error; |
-} |
- |
-DWORD IATPatchFunction::Unpatch() { |
- DWORD error = RestoreImportedFunction(intercept_function_, |
- original_function_, |
- iat_thunk_); |
- DCHECK_EQ(static_cast<DWORD>(NO_ERROR), error); |
- |
- // Hands off the intercept if we fail to unpatch. |
- // If IATPatchFunction::Unpatch fails during RestoreImportedFunction |
- // it means that we cannot safely unpatch the import address table |
- // patch. In this case its better to be hands off the intercept as |
- // trying to unpatch again in the destructor of IATPatchFunction is |
- // not going to be any safer |
- if (module_handle_) |
- FreeLibrary(module_handle_); |
- module_handle_ = NULL; |
- intercept_function_ = NULL; |
- original_function_ = NULL; |
- iat_thunk_ = NULL; |
- |
- return error; |
-} |
- |
-} // namespace win |
-} // namespace app |