一、Detours库的来历及下载:

Detours库类似于WTL的来历,是由Galen Hunt and Doug Brubacher自己开发出来,于99年7月发表在一篇名为《Detours: Binary Interception of Win32 Functions.》的论文中。基本原理是改写函数的头5个字节(因为一般函数开头都是保存堆栈环境的三条指令共5个字节:8B FF 55 8B EC)为一条跳转指令,直接跳转到自己的函数开头,从而实现API拦截的。后来得到MS的支持并在其网站上提供下载空间:

http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx

目前最新的版本是:Detours Express 2.1。

二、Detours的使用准备:

Detours库是以源码形式提供的,这给我们的使用带来极大的方便。你可以选择把它编译成库、也可以直接把源码加入工程……形式使用。农夫采取的方法是编译成库后使用的。编译库的方法很简单,下载包中已经制作好了makefile,我们只须直接用vc下的nmake工具直接编译即可。鉴于前段时间在网上看见有部分朋友对此也存疑惑,农夫在此“浪费”一下空间,详细解说一下编译的过程(括号中为本人的例子):

1、运行你下载的安装包,把文件解压到磁盘上

此处建议您把解压后的src文件夹拷贝到VC的安装目录的VC98子目录下(D:/SDK/6.0/VC98)。对于像我一样使用库的方式会有好处,稍后即讲:)。

2、编译并设置开发环境

在你刚才拷贝过去的src文件夹下建立一个*.bat文件,里面填上“../bin/nmake”内容后保存即可。运行该批处理文件,恭喜您:库已经编译完成,唯一要做的是要把../bin/Detoured.dll拷贝到您的系统目录下。现在您的工程里面包含如下文件即可运用Detours库来进行开发了:

#include <detours.h>

#pragma comment(lib, "detours.lib")
#pragma comment(lib, "detoured.lib")

对于没有把src文件拷贝过来的朋友,也不用着急。bat文件中把路径用全路径即可进行编译。不过你除了拷贝.dll文件外,还得要把.lib、.h文件拷贝到VC目录下,或者在你的VC环境中设置这些文件的包含路径,才可正常使用VC进行开发。看,是不是要麻烦些?

另外的建议:在Detours.h文件中定义一个函数指针类型,到用的时候您就知道会很方便了:

typedef  LONG (WINAPI* Detour)(PVOID*, PVOID);

三、几个重要的函数:

1、DetourAttach & DetourDetach

        这两个函数就是实际实现API挂钩的(改写头5个字节为一个跳转指令),前一个实现API拦截,后一个为在不需要的时候恢复原来的API。

第一个参数为自己定义的一个用于保存原来系统API的函数,该函数就相当于您没挂钩时的API。农夫习惯于在原有API的基础上加以“Sys”前缀来命名;

第二个参数为自己拦截API的功能函数,您想干什么“坏事”都是在这个函数中实现的。农夫习惯于在原有API的基础上加以“Hook”前缀来命名。

2、DetourCreateProcessWithDll

       该函数是在以DLL注入方式拦截API时使用的,它其实就是封装“CreateProcess”,以“CREATE_SUSPEND”方式创建进程,然后修改IAT,把Detoured.dll和您的*.dll插入到它的导入表,然后再启动进程。所以它的参数就是在普通的CreateProcess基础上增加了两个DLL的路径参数,最后一个参数为创建进程的函数指针,默认为CreateProcessA!这点要特别注意:如果您的程序拦截了该函数,而在HookCreateProcessA中又调用DetourCreateProcessWithDll函数的话,一定要在此传入SysCreateProcessA,否则您的程序就会递归调用了,当心您的程序崩溃!至于为何要这么调用?呵呵,问我干嘛?:)

当然其它的API也很有用,不过对于开发者来说,这三个最重要!

四、开发实例:

随源码有一个帮助文档,上面列举了很多例子:包含普通的API、类成员函数、COM接口、DLL方式注入……。包含了我们的大多应用领域。

下面举个拦截CreateFileA函数的例子。该例子将所有创建的文件移动到指定目录下(晕,第一次使用,怎么不能插入C++代码?):

1、定义保存系统原来函数的函数SysCreateProcessA:(听起来有点拗口)

static HANDLE (WINAPI* SysCreateFileA)( LPCTSTR lpFileName,       // pointer to name of the file
            DWORD dwDesiredAccess,      // access (read-write) mode
            DWORD dwShareMode,       // share mode
            LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
            DWORD dwCreationDisposition,    // how to create
            DWORD dwFlagsAndAttributes,     // file attributes
            HANDLE hTemplateFile      // handle to file with attributes to copy
            ) = CreateFileA;

2、编写自己的功能函数:

HANDLE WINAPI HookCreateFileA( LPCTSTR lpFileName,       // pointer to name of the file
        DWORD dwDesiredAccess,      // access (read-write) mode
        DWORD dwShareMode,       // share mode
        LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
        DWORD dwCreationDisposition,    // how to create
        DWORD dwFlagsAndAttributes,     // file attributes
        HANDLE hTemplateFile      // handle to file with attributes to copy
        )
{
 char chDestFile[256];

strcpy(chDestFile, lpFileName);
 if( strstr(lpFileName, "////.//") != NULL ) // 放过设备
 {
  // 创建的普通文件全部转到D盘去,这里没考虑是“读”访问
  char *p = strrchr(lpFileName, &apos;//&apos;);
  if( p++ == NULL )
  {
   p = lpFileName;
  }

sprintf(chDestFile, "D://%s", p);
 }

// 创建文件,注意这里不可以再调用CreateFileA,否则您就递归调用了!取而代之的应该是SysCreateFileA!!!!
 return SysCreateFileA(chDestFile, .....); // 后面的参数照搬下来就可以了
}

3、挂钩,用自己的函数替换系统API:

DetourAttach(&(PVOID&)SysCreateFileA, HookCreateFileA);
恢复时用DetourDetach即可。

这下运行您的程序,发现所有用CreateFileA创建的新文件都被转移到D盘下了。

五、几个问题:

1、字节编码:

很多Win32函数都有多字节A版和宽字符W版,之所以平时没有附加A或W后缀,那是因为编译器已经帮我们做了这个工作。但在汇编惜字节如金的条件下,如果有两种版本,请务必明确指出,不要用CreateFile这种函数;

2、应用对象:

该库适合于初学者在RING3下对大多数API的拦截。对于那些逆向高手来说,这个简直不值一提;

3、发布:

由于该库并没有包含在MS 的SDK中,所以要随程序一块打包Detoured.dll。当然如果您是直接用源码加入工程编译的则可免去这个文件;

4、拦截DLL参数设置:

拿上面CreateFile函数来说,假如我是想在文件名称符合特定条件下才将其转移到D盘上,比如当文件类型为TXT文件时才转移。我们可以把盘符“D”及文件类型“TXT”直接写死在程序里面。这样的话,假如有其它程序是把“PDF”文件放在F盘不是又要重写一个?

不要以为加一个接口就可以解决。如是,祝贺您步入了农夫当初的歧途:)!其实要传这个参数进去的实质是进程间通信问题。本人采取的是FileMapping,改写了一下Detours的源码。当然其它进程间通信方式也是可以的。

5、拦截DLL必须导出一个函数

一般搞个空函数就可以了。如果没有任何导出函数,您辛苦编写的DLL将无法工作,还可能为此花上一大堆时间去排查。像如下声明一个就行了:

////////////////////////////////////////////////////////////////////////////////
// Must at least ONE export function:
__declspec(dllexport) void ExportFunc(void)
{
}

六、后记

乡村野夫,恍惚于世。本应扶犁,贸入IT。

三十而立,一事无成。慨殇岁逝,辗转反侧。

写文静心,闲以思远。悠悠我祖,自爱陶潜。

拙作开篇,文中如有不当/错误之处,烦请各位朋友留下您宝贵的笔墨。

======================

初版写了很久怎么都不见??????

转载于:http://blog.csdn.net/vcplayer/article/details/2681758

http://blog.csdn.net/chence19871/article/details/10372695

运用Detours库hook API(原理是改写函数的头5个字节)的更多相关文章

  1. 《逆向工程核心原理》——通过调试方式hook Api

    1.附加目标进程, 2.CREATE_PROCESS_DEBUG_EVENT附加事件中将目标api处设置为0xcc(INT 3断点) 3.EXCEPTION_DEBUG_EVENT异常事件中,首先判断 ...

  2. HOOK相关原理与例子

    消息HOOK 原理: 1. 用户输入消息,消息被放到系统消息队列. 2. 程序发生了某些需要获取输入的事件,就从系统消息队列拿出消息放到程序消息队列中. 3. 应用程序检测到有新的消息进入到程序消息队 ...

  3. [Effective JavaScript 笔记]第6章:库和API设计--个人总结

    前言 又到了一章的总结,这章里的内容.是把我从一个代码的使用者,如何换位成一个代码的编写者.如何让别人用自己的代码更容易,不用去注意太多的无用细节,不用记住冗长的函数名.在使用API时怎样避免使用者会 ...

  4. 汇编Ring 3下实现 HOOK API

    [文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...

  5. Wordpress解析系列之PHP编写hook钩子原理简单实例

    Wordpress作为全球应用最广泛的个人博客建站工具,有很多的技术架构值得我们学习推敲.其中,最著名最经典的编码技术架构就是采用了hook的机制. hook翻译成中文是钩子的意思,单独看这个词我们难 ...

  6. 使用函数库(JAVA API)

    /*使用函数库(JAVA API) * 在JAVA的API里类被封装在一个个的package,要使用package的类之前必须 * 要知道这个类属于哪个package * 引用类方式: * 1.通过i ...

  7. HOOK API 在多线程时应该注意的问题点

    在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系 ...

  8. HOOK API(四)—— 进程防终止

    HOOK API(四) —— 进程防终止 0x00        前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API ...

  9. HOOK API(三)—— HOOK 所有程序的 MessageBox

    HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

随机推荐

  1. CS0016: 未能写入输出文件*****目录名称无效

    一大早,杀毒软件弹出删除隐私记录.清理空间一堆堆的提醒,一般我都是无视它,今天顺便点了下清理,然后出问题. 昨晚下班提交的代码,程序运行好好地,今早清理完系统,竟然就出问题了, 具体如下 CS0016 ...

  2. PHP根据身份证号码验证、获取星座、生肖和性别函数

    首先介绍一下身份证含义 新的18位身份证号码各位的含义:1-2位省.自治区.直辖市代码:3-4位地级市.盟.自治州代码:5-6位县.县级市.区代码:7-14位出生年月日,比如19670401代表196 ...

  3. 安装eclipse

    前提,安装好jdk并成功配置好环境变量 下载eclipse-standard-kepler-R-win32-x86_64,直接打开里面的eclipse.exe文件即可

  4. acdream 1154 Lowbit Sum

    先贴代码,以后再写题解... 首先,直接枚举肯定是会超时的,毕竟n就有10^9那么多... 对于每个数,我们先把它转化为二进制:例:21-->10101: 对于00001~10101,可以分为几 ...

  5. MEMS陀螺仪(gyroscope)的工作原理

    传统的陀螺仪主要是利用角动量守恒原理,因此它主要是一个不停转动的物体,它的转轴指向不随承载它的支架的旋转而变化. 但是MEMS陀螺仪(gyroscope)的工作原理不是这样的,因为要用微机械技术在硅片 ...

  6. Excel在任务栏中只显示一个窗口的解决办法

     Excel在任务栏中只显示一个窗口的解决办法  以前朋友遇到过这个问题,这次自己又遇到了,习惯了以前的那种在任务栏中显示全部窗口,方便用Alt+Tab键进行切换. 如果同时打开许多Excel工作簿, ...

  7. 快速配置 Samba 将 Linux 目录映射为 Windows 驱动器

    原文链接 samba client ubuntu redhat ubuntu gui tools 1,列出某个IP地址所提供的共享文件夹 smbclient -L 198.168.0.1   2,在s ...

  8. logback.xml配置详解

    先附上本文分析用的例子: <?xml version="1.0" encoding="UTF-8" ?> <configuration> ...

  9. hdu 4496 D-City(并查集)

    Problem Description Luxer is a really bad guy. He destroys everything he met. One day Luxer went to ...

  10. K-th Number(第k大数)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 45710   Accepted: 15199 Ca ...