Microsoft Detours 2.1简介
http://blog.163.com/qcb_163/blog/static/9545466420117851038971/
Microsoft Detours 2.1简介
2011-08-0817:10:38| 分类: VC编程 | 标签: |字号大中小 订阅
一、简介
《Windows高级调试》第一章中提到了一个基于Microsoft Detours库的内存泄露检查工具LeakDiag。本文对这个库进行一些介绍。
一句话来说,Detours是一个用来在二进制级别上对程序中的函数(Function)或者过程(Procedure)进行修改的工具 库。一般我们将这种技术称为"Hook"。Detours的实现原理是将目标函数的前几个字节改为jmp指令跳转到自己的函数地址,以此接管对目标函数的 调用,并插入自己的处理代码。在现实中,这种技术可以应用在很多场景下。比如Hook某些Windows API,在实际调用到系统函数前进行一些过滤工作;软件中使用到了一些没有源代码的第三方库,但是又想增强其中某些函数的功能,等等。
图1 Hook前后的程序执行流程对比。
图2 Hook前后目标函数和跳板代码的改变
Detours相对其他一些Hook库和自己实现的代码来说,通常有以下这些优点:
· 考虑全面,代码非常稳定,并且经过了微软自己众多产品的验证。
· 可以简单的用纯C/C++代码实现对类的成员函数的Hook。
· 购买版权之后的Detours Professional还可以支持x64和IA64处理器。以此为基础编写的代码拥有更强的可移植性。
· 使用简单,不需要了解汇编指令以及技术细节。
二、使用方法
一般来说,使用Detours的代码都具有固定的模式。Detours1.5和Detours 2.1的接口函数变了很多,这里按照2.1版本对基本的使用方法进行说明。
常用的函数有下面几个:
· DetourTransactionBegin() :开始一次Hook或者Unhook过程。
· DetourUpdateThread() :列入一个在DetourTransaction过程中要进行update的线程。这个函数的作用稍微有一些复杂,会在后面专门说明。
· DetourAttach() :添加一个要Hook的函数。
· DetourDetach () :添加一个要Unhook的函数。
· DetourTransactionCommit() :执行当前的Transaction过程。在这个函数中才会真正进行Hook或者Unhook操作。前面三个函数都只是做一些记录工作。
在使用的时候,这几个函数的调用步骤基本上也是按照上面列出来的顺序。举例来说,现在想Hook掉API函数MessageBoxA,将消息框弹出的消息修改掉,可以按下面的方法做。
进行Hook的步骤:
1. 首 先需要定义目标函数的原型。如果目标函数是Windows API,可以到MSDN中查阅,但是需要注意ANSI版本和Unicode版本的区别。如果没有确切的原型声明,或者目标函数是通过逆向工程找出来的,那 么需要定义一个和目标函数原型兼容的声明,即参数个数和调用约定要相同。如MessageBoxA的原型是:
int MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTRlpCaption, UINT uType);
使用typedef定义如下:
typedef int (WINAPI *pfnMessageBoxA)( HWND hWnd,LPCSTR lpText, LPCSTR lpCaption, UINT uType);
2. 声明一个指向目标函数的函数指针:
pfnMessageBoxA g_pMessageBoxA = ::MessageBoxA;
3. 编写Hook函数的代码,用于替换目标函数。
4. 调用DetourTransactionBegin开始一次Detours事务。
5. 对进程中每个可能调用到目标函数的线程,都需要使用DetourUpdateThread加 入到update队列中。这是因为Hook时修改目标函数的前几个字节,如果某个线程刚好执行到这几个字节的位置时,粗暴的修改掉会造成该线程出现异常。 Detours事务处理时,会先枚举并暂停update队列中所有线程,获取它们的指令指针,如果发现这种情况,则将指令指针修改到跳板代码的对应字节 上。这样就避免出现崩溃的问题。
6. 对每个需要Hook的函数,调用DetourAttach加入到事务列表中。
7. 调用DetourTransactionCommit进行实际的Hook操作。
Unhook的过程和上面的流程基本一样,只是第6步改为调用DetourDetach函数。
Hook MessageBoxA的完整示例代码如下:
//Hook函数的向前声明
int WINAPIHook_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
//目标函数原型声明
typedef int(WINAPI *pfnMessageBoxA)( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINTuType);
//指向目标函数的指针
pfnMessageBoxAg_pMessageBoxA = ::MessageBoxA;
BOOLStartHook()
{//开始Hook
DetourTransactionBegin();
//只有一个线程,所以GetCurrentThread
DetourUpdateThread(GetCurrentThread());
//添加MessageBoxA的Hook
if(DetourAttach( &(PVOID&)g_pMessageBoxA, Hook_MessageBoxA) != NO_ERROR)
{
printf("Hook MessageBoxA fail.\n");
}
//完成事务
if(DetourTransactionCommit() != NO_ERROR)
{
printf("DetourTransactionCommit fail\n");
return FALSE;
}
else
{
printf("DetourTransactionCommit ok\n");
return TRUE;
}
}
BOOLStopHook()
{//停止Hook
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if(DetourDetach( &(PVOID&)g_pMessageBoxA, Hook_MessageBoxA) != NO_ERROR)
{
printf("Hook MessageBoxA fail.\n");
}
if(DetourTransactionCommit() != NO_ERROR)
{
printf("DetourTransactionCommit fail\n");
return FALSE;
}
else
{
printf("DetourTransactionCommit ok\n");
return TRUE;
}
}
int WINAPIHook_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
//需要调用原函数时,可以直接使用前面定义的指针变量
returng_pMessageBoxA( hWnd, "MessageBox after hook.","TestDetours", MB_OK);
}
在附件的示例代码中还包含了Hook类成员函数的代码。流程和上面基本一致,只是需要用一些强制转换来对付编译器的类型检查。
另外,Detours还包含一系列其他函数,如果需要使用的话,可以参考Detours安装目录下的示例。
三、使用Detours的注意事项
总体来说,Detours库的代码是非常稳定的,但是如果使用方法不对,会造成一些问题。有下面一些地方需要特别注意:
1. 一定要枚举线程并调用DetourUpdateThread函数。否则可能出现很低几率的崩溃问题,这种问题很难被检查出来。
2. 如果Hook函数在DLL中,那么绝大多数情况下不能在Unhook之后卸载这个DLL,或者卸载存在造成崩溃的危险。因为某些线程的调用堆栈中可能还包含Hook函数,这时卸载掉DLL,调用堆栈返回到Hook函数时内存位置已经不是合法的代码了。
3. Detours库设计时并没有考虑到卸载的问题,这 是因为钩子的卸载本身是不安全的。当Detours库代码存在于DLL中的时候,即使Unhook了所有函数,清理了所有自己使用到的函数,还是会占用一 些内存。卸载这个DLL会造成内存泄露,特别是反复的进行加载DLL->Hook->Unhook->卸载DLL的过程,会让这个问题 变得非常严重。后面会用一篇专题文章来讨论Detours内存泄露问题的调试和解决。
4. 有一些非常短的目标函数是无法Hook的。因为jmp指令需要占用一定空间,有些函数太过短小,甚至不够jmp指令的长度,自然是没有办法Hook掉的。
Detours不支持9x内核的Windows系统。因为9x内核下的内存模型和NT内核下有非常大的差别。
如何生成Detours.lib——Detours的使用准备
http://blog.csdn.net/sliufen/article/details/3932236
Detours是微软开发的一个函数库,可用于捕获系统API。在用其进行程序开发之前,得做一些准备工作:
一.下载Detours
在http://research.microsoft.com/sn/detours 可免费下载Detours,当前的最新版本是
- Detours Express 2.1 is available for immediate download under a no-fee, click-through license for research, non-commercial, and non-production use on 32-bit code.
- Detours Professional 2.1 includes a license for use in production environments and the right to distribute detour functions in products. In addition to support for 32-bit x86 code, Detours Professional 2.1 includes support for 64-bit code on x64 and IA64 processors. For information on licensing Detours Professional 2.1 visit Microsoft's IP Licensing Group at www.microsoft.com/iplicensing and search under Detours.
由于我只是用于研究学习,所以下载的是第一个版本。
二.安装Detours
从网上下载的是DetoursExpress.msi,安装该文件
三.生成Detours库
在安装后的文件夹下找不到直接可以拿来用的LIB文件,但是却有SRC文件(在**/Microsoft Research/Detours Express 2.1/src下)。该文件夹下还有Makefile,可以直接用来生成库。
安装后的文件夹目录
具体生成库的做法是:
1.将Detours路径下的SCR文件夹拷贝到**/Microsoft Visual Studio/VC98路径下,注意是整个文件夹
2.运行**/Microsoft Visual Studio/VC98/Bin下VCVARS32.BAT文件.
在开始->运行里面输入CMD命令,在出来的命令行窗口里,将路径换至**/Microsoft Visual Studio/VC98/Bin,再将VCVARS32.BAT文件拖进命令行窗口里就行
3.运行NMAKE命令
在命令行窗口里将路径换到**/Microsoft Visual Studio/VC98/SRC,然后输入../bin/nmake指令,回车
4.待此命令运行完后,在**/Microsoft Visual Studio/VC98/Lib文件下就能找到detoured.lib与detours.lib文件.
http://blog.csdn.net/jiangxinyu/article/details/8086831
Microsoft Detours 2.1简介的更多相关文章
- Microsoft Azure File 服务简介
我们非常高兴地宣布在微软Azure中国区推出 Microsoft Azure File 服务预览版.Azure File 服务使用标准 SMB 2.1 协议提供文件共享.Azure 中运行的应用程序现 ...
- Microsoft .NET Pet Shop 简介
最初研究 .NET Pet Shop 的目的是用 Microsoft .NET 实现 Sun 主要的 J2EE 蓝图应用程序 Sun Java Pet Store 同样的应用程序功能. 根据用 .NE ...
- 保持与 Microsoft Azure Files 的连接
我们在最近的博客文章中介绍了 Azure StorageFiles的预览版,请单击此处.该文章包含 Azure Files 的相关信息,说明了如何申请预览版并开始使用,还介绍了一些有助于创建共享和传 ...
- 全面了解POI操作Microsoft Office(Word、Excel、PowerPoint)
POI 与 Microsoft Office 1. POI 简介 POI 是 Apache 下的 Jakata 项目的一个子项目,主要用于提供 java 操作 Microsoft Office 办公套 ...
- 利用detours写了一个工具用于instrument任意指定dll的任意指定函数入口
目录 wiki Disas Dtest Simple withdll load一个dll到指定进程 tracebld显示相关进程涉及的文件读写操作 My Instrumentation tool: w ...
- SkinTK编译使用
简介 MFC这个东西已经落伍了,不建议使用.我就是吃饱了撑着,还在折腾这个. 平时写点带界面的小程序一般都用Qt来做,简单好用,也很容易做的比较漂亮.我觉得唯一一个算不得多大缺点的缺点就是Qt体积太大 ...
- Azure China (1) Azure公有云落地中国
<Windows Azure Platform 系列文章目录> 微软公有云Microsoft Azure已经落地中国,官方网址:http://www.windowsazure.cn/. 在 ...
- MSChart参考
MSChart在vs2008中使用遇到一个问题,坐标轴的标题为中文时被图表区域遮挡了一部分. 解决办法:在说明文字前加\n实现换一行显示. //this.Chart1.ChartAreas[0].Ax ...
- C#自定义控件的开发:Pin和Connector
C#自定义控件的开发:Pin和Connector 2009-08-03 14:46 wonsoft hi.baidu 我要评论(0) 字号:T | T 本文介绍了如何使用智能设备扩展C#自定义控件. ...
随机推荐
- UIScrollView控件详解
一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 (2)当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可 ...
- iOS 关于枚举的使用
枚举值 它是一个整形(int) 并且,它不参与内存的占用和释放,枚举定义变量即可直接使用,不用初始化. 在代码中使用枚举的目的只有一个,那就是增加代码的可读性. 使用: 枚举的定义如下: typed ...
- MongoDB 聚合
聚合操作过程中的数据记录和计算结果返回.聚合操作分组值从多个文档,并可以执行各种操作,分组数据返回单个结果.在SQL COUNT(*)和group by 相当于MongoDB的聚集. aggregat ...
- July收集荷兰国旗问题之三路partition
这道题目和分成两块的partition的扩展.比如有一堆0 1 2 数字组成的数组,要分成 00 00 11 1 1 222 2这样的顺序的. 利用lumoto版的partition能够非常好的解 ...
- [Falcor] Indroduce to Model
How to work with JSON data indirectly through a Falcor Model. The Falcor Model allows you to work wi ...
- Html----常见标签
文本格式化标签 标签 描述 <b> 定义粗体文本. <big> 定义大号字. <em> 定义着重文字. <i> 定义斜体字. <small> ...
- Apache MINA NioSocketAcceptor类的实现
NioSocketAcceptor 继承AbstractPollingIoAcceptor,实现SocketAcceptor接口 public final class NioSocketAccepto ...
- HDU 4455(dp)
题意:给定一个序列ai,个数为n.再给出一系列w:对于每个w,求序列中,所有长度为w的连续子串中的权值和,子串权值为子串中不同数的个数. 思路:动态规划,用dp[w]表示当前长度为w的时候的权值和.显 ...
- Vijos P1325桐桐的糖果计划(有向图双连通分量)
/*重边不能删 不能删 不能删...*/ #include<iostream> #include<cstdio> #include<cstring> #define ...
- Java POI 导出excel表
1.首先下载poi-3.6-20091214.jar,下载地址如下: http://download.csdn.net/detail/evangel_z/3895051 2.Student.java ...