/*
Module : HookImportFunction.cpp
Purpose: Defines the implementation for code to hook a call to any imported Win32 SDK
Created: PJN / 23-10-1999
History: PJN / 01-01-2001 1. Now includes copyright message in the source code and documentation.
2. Fixed an access violation in where I was getting the name of the import
function but not checking for failure.
3. Fixed a compiler error where I was incorrectly casting to a PDWORD instead
of a DWORD
Copyright (c) 1996 - 2001 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)
All rights reserved.
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/
////////////////// Includes ////////////////////////////////////
#include "stdafx.h"
#include "HookImportFunction.h"
////////////////// Defines / Locals ////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MakePtr(cast, ptr, AddValue) (cast)((DWORD)(ptr)+(DWORD)(AddValue))
BOOL IsNT();
////////////////// Implementation //////////////////////////////
BOOL HookImportFunctionsByName(HMODULE hModule, LPCSTR szImportMod, UINT uiCount,
LPHOOKFUNCDESC paHookArray, PROC* paOrigFuncs, UINT* puiHooked)
{
// Double check the parameters.
ASSERT(szImportMod);
ASSERT(uiCount);
ASSERT(!IsBadReadPtr(paHookArray, sizeof(HOOKFUNCDESC)*uiCount));
#ifdef _DEBUG
if (paOrigFuncs)
ASSERT(!IsBadWritePtr(paOrigFuncs, sizeof(PROC)*uiCount));
if (puiHooked)
ASSERT(!IsBadWritePtr(puiHooked, sizeof(UINT)));
//Check each function name in the hook array.
for (UINT i = 0; i<uiCount; i++)
{
ASSERT(paHookArray[i].szFunc);
ASSERT(*paHookArray[i].szFunc != _T('\0'));
// If the proc is not NULL, then it is checked.
if (paHookArray[i].pProc)
ASSERT(!IsBadCodePtr(paHookArray[i].pProc));
}
#endif
// Do the parameter validation for real.
if ((uiCount == 0) || (szImportMod == NULL) || (IsBadReadPtr(paHookArray, sizeof(HOOKFUNCDESC)*uiCount)))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return FALSE;
}
if (paOrigFuncs && IsBadWritePtr(paOrigFuncs, sizeof(PROC)*uiCount))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return FALSE;
}
if (puiHooked && IsBadWritePtr(puiHooked, sizeof(UINT)))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return FALSE;
}
// Is this a system DLL, which Windows95 will not let you patch
// since it is above the 2GB line?
if (!IsNT() && ((DWORD)hModule >= 0x80000000))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return FALSE;
}
// TODO TODO
// Should each item in the hook array be checked in release builds?
if (paOrigFuncs)
memset(paOrigFuncs, NULL, sizeof(PROC)*uiCount); // Set all the values in paOrigFuncs to NULL.
if (puiHooked)
*puiHooked = 0; // Set the number of functions hooked to zero.
// Get the specific import descriptor.
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor(hModule, szImportMod);
if (pImportDesc == NULL)
return FALSE; // The requested module was not imported.
// Get the original thunk information for this DLL. I cannot use
// the thunk information stored in the pImportDesc->FirstThunk
// because the that is the array that the loader has already
// bashed to fix up all the imports. This pointer gives us acess
// to the function names.
PIMAGE_THUNK_DATA pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk);
// Get the array pointed to by the pImportDesc->FirstThunk. This is
// where I will do the actual bash.
PIMAGE_THUNK_DATA pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk);
// Loop through and look for the one that matches the name.
while (pOrigThunk->u1.Function)
{
// Only look at those that are imported by name, not ordinal.
if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
{
// Look get the name of this imported function.
PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData);
// If the name starts with NULL (or is NULL), then just skip out now.
if ((pByName == NULL) || (_T('\0') == pByName->Name[0]))
continue;
// Determines if we do the hook.
BOOL bDoHook = FALSE;
// TODO TODO
// Might want to consider bsearch here.
// See if the particular function name is in the import
// list. It might be good to consider requiring the
// paHookArray to be in sorted order so bsearch could be
// used so the lookup will be faster. However, the size of
// uiCount coming into this function should be rather
// small but it is called for each function imported by
// szImportMod.
for (UINT i = 0; i<uiCount; i++)
{
if ((paHookArray[i].szFunc[0] == pByName->Name[0]) &&
(strcmpi(paHookArray[i].szFunc, (char*)pByName->Name) == 0))
{
// If the proc is NULL, kick out, otherwise go
// ahead and hook it.
if (paHookArray[i].pProc)
bDoHook = TRUE;
break;
}
}
if (bDoHook)
{
// I found it. Now I need to change the protection to
// writable before I do the blast. Note that I am now
// blasting into the real thunk area!
MEMORY_BASIC_INFORMATION mbi_thunk;
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
VERIFY(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect));
// Save the original address if requested.
if (paOrigFuncs)
paOrigFuncs[i] = (PROC)pRealThunk->u1.Function;
// Do the actual hook.
pRealThunk->u1.Function = (PDWORD)paHookArray[i].pProc;
// Change the protection back to what it was before I blasted.
DWORD dwOldProtect;
VERIFY(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect));
// Increment the total number hooked.
if (puiHooked)
*puiHooked += 1;
}
}
// Increment both tables.
pOrigThunk++;
pRealThunk++;
}
// All OK, JumpMaster!
SetLastError(ERROR_SUCCESS);
return TRUE;
}
PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportMod)
{
// Always check parameters.
ASSERT(szImportMod);
ASSERT(hModule);
if ((szImportMod == NULL) || (hModule == NULL))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
}
// Get the Dos header.
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
// Is this the MZ header?
if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) || (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE))
{
ASSERT(FALSE);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
}
// Get the PE header.
PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeade
HookImportFunctionByName - code for hooking import functions
需积分: 50 41 浏览量
2006-02-23
09:05:59
上传
评论
收藏 7KB ZIP 举报
普通网友
- 粉丝: 882
- 资源: 2万+
最新资源
- AIS2024 valid
- 最入门的爬虫代码 python.docx
- 爬虫零基础入门-爬取天气预报.pdf
- 最通俗易懂的 MongoDB 非结构化文档存储数据库教程.zip
- 以mongodb为数据库的订单物流小项目.zip
- 腾讯云-mongodb数据库, 项目部署.zip
- 腾讯 APIJSON 的 MongoDB 数据库插件.zip
- 理解非关系型数据库和关系型数据库的区别.zip
- 操作简单的Mongodb网页web管理工具,基于Spring Boot2.0支持mongodb集群.zip
- tms-mongodb-web,提供访问mongodb数据的REST API和可灵活扩展的mongodb web 客户端.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈