如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033
目录
编译器:VS2013
系统环境:Windows 7 64bit
工具:API Monitor 、 Dependency Walker
##前言
Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会受到系统的通知,这时程序就能在第一时间对该事件做出响应。
另一解释:钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
##1.代码级解释
###1.1 汇编代码
mov eax, pNewAddr
jmp eax
###1.2 读写进程内存方法
###1.2.1 读进程内存
VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);
ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
###1.2.2 写进程内存
VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
##2.应用示例
假设一个SDK有试用时间,可以使用API HOOK技术对时间函数进行拦截,返回一个永不过期的时间。
这里假设拦截KERNEL32的GetSystemTime函数
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "AdHookApi.h"
static CAdHookApi gHooks;
void WINAPI my_GetSystemTime(LPSYSTEMTIME lpSystemTime)
{
// 改变函数的行为,返回固定的时间
// 2018-7-28 10:00:00
lpSystemTime->wYear = 2018;
lpSystemTime->wMonth = 7;
lpSystemTime->wDayOfWeek = 0;
lpSystemTime->wDay = 28;
lpSystemTime->wHour = 10;
lpSystemTime->wMinute = 0;
lpSystemTime->wSecond = 0;
lpSystemTime->wMilliseconds = 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// 截获KERNEL32.DLL的API GetSystemTime到你的函数地址my_GetSystemTime
gHooks.Add(_T("KERNEL32.DLL"), "GetSystemTime", my_GetSystemTime);
// 开始HOOK所有的
gHooks.BeginAll();
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
gHooks.EndAll();
break;
}
}
return TRUE;
}
注意:
1.可以使用API Monitor对程序进行监控,从而精确找出程序调用的是哪个函数
2.Dependency Walker可以查看程序调用了哪些DLL
##3.API HOOK类库
上面的应用说明中使用了一个类库
AdHookApi.h
/////////////////////////////////////////////////////////////////////
// Author : CodeLive
// WeiBo : http://weibo.com/1655194010
// Email : [email protected]
// QQ : 5584173
// Date : 2004.04.21
/////////////////////////////////////////////////////////////////////
#ifndef __ADHOOKAPI_H__
#define __ADHOOKAPI_H__
#include
#include
#include
using namespace std;
// class CAdAutoHookApi
class CAdHookApi;
class CAdAutoHookApi
{
public:
CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr);
virtual ~CAdAutoHookApi();
private:
CAdHookApi *m_pHookApi;
void *m_pAddr;
};
// class CAdAutoHook
class CAdHookApi
{
public:
CAdHookApi();
virtual ~CAdHookApi();
protected:
struct HookMap
{
HANDLE hProcess;
void *pOldAddr;
void *pNewAddr;
BYTE chOldCode[8];
BYTE chNewCode[8];
BOOL bHooked;
DWORD dwData;
};
public:
HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);
HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0);
BOOL Remove(HANDLE hHook);
BOOL Begin(HANDLE hHook);
BOOL End(HANDLE hHook);
BOOL Begin2(void *pNewAddr);
BOOL End2(void *pNewAddr);
int BeginAll();
int EndAll();
int GetCount();
void *OldAddr2NewAddr(void *pOldAddr);
void *NewAddr2OldAddr(void *pNewAddr);
public:
static BOOL VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize);
static BOOL PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode,
const BYTE *verifyData = NULL, DWORD verifySize = 0);
protected:
CAdHookApi::HookMap *FromNewAddr(void *pNewAddr);
CAdHookApi::HookMap *FromOldAddr(void *pOldAddr);
BOOL HasHook(HANDLE hHook);
protected:
vector m_obHooks;
};
#endif // __ADHOOKAPI_H__
AdHookApi.cpp
/////////////////////////////////////////////////////////////////////
// Author : CodeLive
// WeiBo : http://weibo.com/1655194010
// Email : [email protected]
// QQ : 5584173
// Date : 2014.04.21
/////////////////////////////////////////////////////////////////////
//#include "stdafx.h"
#include "AdHookApi.h"
#include
#include
#include
#include
//#include "Common.h"
static BOOL gUseAPI = TRUE;
static BOOL WINAPI myReadMemory(HANDLE hProcess, LPVOID lpAddress, LPVOID lpBuffer, SIZE_T nSize)
{
BOOL bRet = FALSE;
DWORD dwOldProtect = 0;
bRet = VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);
if(gUseAPI)
{
DWORD dwRead = 0;
bRet = ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);
}
else
{
memcpy(lpBuffer, lpAddress, nSize);
}
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
assert(bRet);
return bRet;
}
static BOOL WINAPI myWriteMemory(HANDLE hProcess, LPVOID lpAddress, LPCVOID lpBuffer, SIZE_T nSize)
{
BOOL bRet = FALSE;
DWORD dwOldProtect = 0;
bRet = VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);
if(gUseAPI)
{
DWORD dwWrite = 0;
bRet = WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);
}
else
{
memcpy(lpAddress, lpBuffer, nSize);
}
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
assert(bRet);
return bRet;
}
// class CAdAutoHookApi
CAdAutoHookApi::CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr)
{
m_pHookApi = pHookApi;
m_pAddr = pAddr;
assert(m_pHookApi != NULL);
if(m_pHookApi != NULL)
{
m_pHookApi->End2(m_pAddr);
}
}
CAdAutoHookApi::~CAdAutoHookApi()
{
if(m_pHookApi != NULL)
{
m_pHookApi->Begin2(m_pAddr);
}
}
// class CAdHookApi
CAdHookApi::CAdHookApi()
{
}
CAdHookApi::~CAdHookApi()
{
EndAll();
}
BOOL CAdHookApi::VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize)
{
BOOL isPassed = FALSE;
if((verifyData != NULL) && (verifySize > 0))
{
BYTE *addrData = new BYTE[verifySize];
if(myReadMemory(GetCurrentProcess(), pAddr, addrData, verifySize))
{
if(memcmp(addrData, verifyData, verifySize) == 0)
{
isPassed = TRUE;
}
}
delete []addrData;
}
else
{
isPassed = TRUE;
}
return isPassed;
}
BOOL CAdHookApi::PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode,
const BYTE *verifyData, DWORD verifySize)
{
if(!VerifyAddress(pAddr, verifyData, verifySize))
{
return FALSE;
}
BOOL bRet = myWriteMemory(GetCurrentProcess(), pAddr, pCode, dwCode);
return bRet;
}
HANDLE CAdHookApi::Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData)
{
HMODULE hModule = LoadLibrary(lpszModule);
if(hModule == NULL)
{
return NULL;
}
void *pOldAddr = (void *)GetProcAddress(hModule, lpcFuncName);
if(pOldAddr == NULL)
{
return NULL;
}
return Add(pOldAddr, pNewAddr, NULL, 0, dwData);
}
HANDLE CAdHookApi::Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData, DWORD verifySize, DWORD dwData)
{
BOOL bRet = FALSE;
HookMap *pHook = new HookMap;
do
{
ZeroMemory(pHook, sizeof(HookMap));
pHook->hProcess = GetCurrentProcess();
pHook->pOldAddr = pOldAddr;
if(pHook->pOldAddr == NULL)
{
break ;
}
DWORD dwRead = 8;
if((verifyData != NULL) && (verifySize > 0) && (verifySize > dwRead))
{
dwRead = verifySize;
}
BYTE *addrData = new BYTE[dwRead];
if(!myReadMemory(pHook->hProcess, pHook->pOldAddr, addrData, dwRead))
{
delete []addrData;
break ;
}
if((verifyData != NULL) && (verifySize > 0) && (memcmp(addrData, verifyData, verifySize) != 0))
{
delete []addrData;
break ;
}
memcpy(pHook->chOldCode, addrData, 8);
delete []addrData;
DWORD dwTemp = (DWORD)pNewAddr;
pHook->pNewAddr = pNewAddr;
// mov eax, pNewAddr
// jmp eax
pHook->chNewCode[0] = 0xB8;
memcpy(pHook->chNewCode + 1, &dwTemp, sizeof(DWORD));
pHook->chNewCode[5] = 0xFF;
pHook->chNewCode[6] = 0xE0;
pHook->bHooked = FALSE;
pHook->dwData = dwData;
m_obHooks.push_back(pHook);
bRet = TRUE;
}while(0);
if(!bRet)
{
delete pHook;
pHook = NULL;
}
return (HANDLE)pHook;
}
BOOL CAdHookApi::Remove(HANDLE hHook)
{
BOOL bRet = FALSE;
HookMap *pHook = (HookMap *)hHook;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp == pHook)
{
End((HANDLE)pTemp);
delete pHook;
m_obHooks.erase(m_obHooks.begin() + i);
bRet = TRUE;
break ;
}
}
return bRet;
}
BOOL CAdHookApi::Begin(HANDLE hHook)
{
if(!HasHook(hHook))
{
return FALSE;
}
HookMap *pHook = (HookMap *)hHook;
if(pHook->bHooked)
{
return TRUE;
}
DWORD dwWrite = 8;
BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chNewCode, dwWrite);
if(bRet)
{
pHook->bHooked = TRUE;
}
return bRet;
}
BOOL CAdHookApi::End(HANDLE hHook)
{
if(!HasHook(hHook))
{
return FALSE;
}
HookMap *pHook = (HookMap *)hHook;
if(!pHook->bHooked)
{
return FALSE;
}
DWORD dwWrite = 8;
BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chOldCode, dwWrite);
if(bRet)
{
pHook->bHooked = FALSE;
}
return bRet;
}
BOOL CAdHookApi::Begin2(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return FALSE;
}
return Begin((HANDLE)pHook);
}
BOOL CAdHookApi::End2(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return FALSE;
}
return End((HANDLE)pHook);
}
void *CAdHookApi::OldAddr2NewAddr(void *pOldAddr)
{
HookMap *pHook = FromOldAddr(pOldAddr);
if(pHook == NULL)
{
return NULL;
}
return pHook->pNewAddr;
}
void *CAdHookApi::NewAddr2OldAddr(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return NULL;
}
return pHook->pOldAddr;
}
CAdHookApi::HookMap *CAdHookApi::FromNewAddr(void *pNewAddr)
{
HookMap *pHook = NULL;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp->pNewAddr == pNewAddr)
{
pHook = pTemp;
break ;
}
}
return pHook;
}
CAdHookApi::HookMap *CAdHookApi::FromOldAddr(void *pOldAddr)
{
HookMap *pHook = NULL;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp->pOldAddr == pOldAddr)
{
pHook = pTemp;
break ;
}
}
return pHook;
}
BOOL CAdHookApi::HasHook(HANDLE hHook)
{
BOOL bRet = FALSE;
HookMap *pHook = (HookMap *)hHook;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp == pHook)
{
bRet = TRUE;
break ;
}
}
return bRet;
}
int CAdHookApi::BeginAll()
{
int nRet = 0;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
BOOL bRet = Begin((HANDLE)pTemp);
if(bRet)
{
nRet ++;
}
}
return nRet;
}
int CAdHookApi::EndAll()
{
int nRet = 0;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
BOOL bRet = End((HANDLE)pTemp);
delete pTemp;
if(bRet)
{
nRet ++;
}
}
m_obHooks.clear();
return nRet;
}
int CAdHookApi::GetCount()
{
return (int)m_obHooks.size();
}
##4.API HOOK示例代码
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hDll;
SYSTEMTIME t;
GetSystemTime(&t);
printf("Before API HOOK : %04d-%02d-%02d %02d:%02d:%02d\n",t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute,t.wSecond);
//动态加载dll
hDll = LoadLibrary("apihook.dll");
GetSystemTime(&t);
printf("API HOOK : %04d-%02d-%02d %02d:%02d:%02d\n", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
//卸载dll
FreeLibrary(hDll);
GetSystemTime(&t);
printf("After API HOOK : %04d-%02d-%02d %02d:%02d:%02d\n", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
return 0;
}
LoadLibrary时拦截时间函数
FreeLibrary时释放拦截
##5.结果
Refrence:
https://www.52pojie.cn/thread-257140-1-1.html
https://baike.baidu.com/item/API HOOK/5667472
觉得文章对你有帮助,可以扫描二维码捐赠给博主,谢谢!
如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033