#Windows核心编程 - API HOOK应用

如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033

目录

文章目录

  • #Windows核心编程 - API HOOK应用
  • @[toc]

编译器: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:00lpSystemTime->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_GetSystemTimegHooks.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  : dongfa@yeah.net
// QQ     : 5584173
// Date   : 2004.04.21
/#ifndef __ADHOOKAPI_H__
#define __ADHOOKAPI_H__
#include <windows.h>
#include <tchar.h>
#include <vector>
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<HookMap *> m_obHooks;
};#endif // __ADHOOKAPI_H__

AdHookApi.cpp

/
// Author : CodeLive
// WeiBo  : http://weibo.com/1655194010
// Email  : dongfa@yeah.net
// QQ     : 5584173
// Date   : 2014.04.21
///#include "stdafx.h"
#include "AdHookApi.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <Windows.h>
//#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 eaxpHook->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 <windows.h>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);//动态加载dllhDll = 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);//卸载dllFreeLibrary(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

Windows核心编程 - API HOOK应用相关推荐

  1. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  2. Windows核心编程_HOOK(续)_APIHOOK

    啰嗦啰嗦: 开始之前还是要啰嗦几句,看到自己博客粉丝增加,访问量也越来越多,感到非常开心,而且好评也是不少,指错也非常感谢,从错误中发现了很多问题,非常感谢,也高兴自己的文章能帮助到其它人. 就比如之 ...

  3. C++Windows核心编程读书笔记(转)

    http://www.makaidong.com/(马开东博客) 这篇笔记是我在读<windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的 ...

  4. [C++]《Windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  5. DLL基础——Windows核心编程学习手札之十九

    DLL基础 --Windows核心编程学习手札之十九 Windows API中的所有函数都包含在DLL中,3个最重要的DLL是Kernel32.dll,它包含用于管理内存.进程和线程的各个函数:Use ...

  6. Unicode——Windows核心编程学习手札之二

    Unicode --Windows核心编程学习手札之二 处理软件本地化的核心在于处理不同的字符集.文本串一直作为一系列单字节字符进行编码,并在结尾处放上一个零,当调用strlen函数时,获取以/0结尾 ...

  7. 转 windows核心编程 学习笔记 目录

    windows核心编程--SEH(结构异常处理) SEH 的工作原理.         Windows 程序设计中最重要的理念就是消息传递,事件驱动.当GUI应用程序触发一个消息时,系统将把该消息放入 ...

  8. Windows核心编程_获取鼠标指定位置的RGB颜色值

    Windows核心编程_获取鼠标指定位置的RGB颜色值 大家平常会见到很多屏幕取色工具,其原理都是获取鼠标位置的屏幕像素点颜色! 一般思路都是:获取鼠标位置,然后取出鼠标指向的屏幕像素点颜色! Get ...

  9. windows核心编程--2、windows的画笔画刷以及一些简单的应用

    一.前言     该系列前几篇:      windows核心编程–1.使用vs2019编写第一个win32项目 二.相关工具     IDE:vs2019     其他格式图片转ico脚本(贴在文末 ...

最新文章

  1. startos 5.1 如何 root 登陆
  2. 模拟STL链表类的实现
  3. python类高级用法_十.python面向对象高级用法
  4. java远程调用linux的命令或者脚本
  5. 2021手机CIS技术趋势总结
  6. cocos2d-x for wp 之Box2D的应用
  7. 旅游服务商Bikego完成A轮融资,共建创投、马蜂窝投资
  8. Django基础—— 19.Form
  9. 外媒:美国做空机构浑水放弃做空特斯拉
  10. 20150917-html第二次课
  11. Center OS7网络设置
  12. 2021-09-1311. 盛最多水的容器 数组 双指针
  13. 二、什么是asp网站
  14. MT9255无法使用mm指令编译某个模块的问题
  15. ajax——请求消息(request)和响应消息(response)
  16. 记录开发错误:ORA-00911: 无效字符
  17. 安装LoadRunner时提示“此计算机上缺少 vc2005_sp1_with_atl_fix_redist”的解决方法
  18. 【python】身份证号码有效性校验
  19. R语言实战读书笔记(八)回归
  20. NGS测序嵌合体是个需要去除的错误扩增序列

热门文章

  1. 初探arcgis的python脚本的使用 (三)
  2. 陈南峰质量讲堂3 | 质量工具方法之间的关系
  3. java相对路径上上级_关于上级目录与上上级目录的表示相对路径
  4. 查看首选DNS服务器地址
  5. Redis的后台启动
  6. Django 框架快速入门
  7. opencv-python截取视频中的图片
  8. GCC最新版安装及错误解决
  9. 机架服务器的系统安装,机架服务器操作系统安装
  10. Wavelet 工具箱的使用