Detour开发包之API拦截技术

Detours使用——踩坑之路 运行完成后可以看到Detours里面的src文件夹下面有detours.h与detours.cpp,在lib.x64文件夹下面有detours.lib,我们后续使用Detours就需要这几个文件。注意,这里使用这几个文件的需要将文件复制到项目下面来,打开你的项目文件,确保下面有这几个文件,因为vs添加文件的话是不会将文件复制过来的(踩坑之一)。这个时候需要先运行vs中的一个bat文件,我的路径如下,直接将这个文件拖入cmd命令窗口中。下载的时候记住你下载的位置,默认·下载的话一般在这里面。 阅读详情
我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通过访 问源代码,我们可以轻而易举的使用重建(Rebuilding)操作系统或者应用程序的方法在它们中间插入新的功能或者做功能扩展。然而,在今天这个商业 化的开发世界里,以及在只有二进制代码发布的系统中,研究人员几乎没有机会可以得到源代码。本文主要讨论Detour在Windows二进制PE文件基础 上的API截获技术。对于Linux平台,作这件事情将会非常的简单,由于最初的操作系统设计者引入了LD_PRELOAD。如果你设置  LD_PRELOAD=mylib.so ,那么应用程序在载入 dll时,会先查看mylib.so的符号表,在relocation 的时候会优先 使用mylib.so 里的 symbol 。假如你在mylib.so里有个printf() ,那么这个printf就会替代libc的 printf。 而在mylib.so里的这个printf可以直接访问 libc.so里的printf函数指针来获得真正的 printf的入口地 址。 这样,所有的dll的API HOOK在loader加载dll的时候就已经完成,非常自然,和平台相关的部分全部交给loader去处理。

一、  Detour开发库:

  简介
Detours 是一个在x86平台上截获任意Win32函数调用的工具库。中断代码可以在运行时动态加载。Detours使用一个无条件转移指令来替换目标函数的最初几 条指令,将控制流转移到一个用户提供的截获函数。而目标函数中的一些指令被保存在一个被称为“trampoline” (译注:英文意为蹦床,杂技)的函 数中,在这里我觉得翻译成目标函数的部分克隆/拷贝比较贴切。这些指令包括目标函数中被替换的代码以及一个重新跳转到目标函数的无条件分支。而截获函数可 以替换目标函数,或者通过执行“trampoline”函数的时候将目标函数作为子程序来调用的办法来扩展功能。
Detours是执行时被插入 的。内存中的目标函数的代码不是在硬盘上被修改的,因而可以在一个很好的粒度上使得截获二进制函数的执行变得更容易。例如,一个应用程序执行时加载的 DLL中的函数过程可以被插入一段截获代码(detoured),与此同时,这个DLL还可以被其他应用程序按正常情况执行(译注:也就是按照不被截获的 方式执行,因为DLL二进制文件没有被修改,所以发生截获时不会影响其他进程空间加载这个DLL)。不同于DLL的重新链接或者静态重定向, Detours库中使用的这种中断技术确保不会影响到应用程序中的方法或者系统代码对目标函数的定位。
如果其他人为了调试或者在内部使用其他系统 检测手段而试图修改二进制代码,Detours将是一个可以普遍使用的开发包。据我所知,Detours是第一个可以在任意平台上将未修改的目标代码作为 一个可以通过“trampoline”调用的子程序来保留的开发包。而以前的系统在逻辑上预先将截获代码放到目标代码中,而不是将原始的目标代码做为一个 普通的子程序来调用。我们独特的“trampoline”设计对于扩展现有的软件的二进制代码是至关重要的。
出于使用基本的函数截获功能的目的, Detours同样提供了编辑任何DLL导入表的功能,达到向存在的二进制代码中添加任意数据节表的目的,向一个新进程或者一个已经运行着的进程中注入一 个DLL。一旦向一个进程注入了DLL,这个动态库就可以截获任何Win32函数,不论它是在应用程序中或者在系统库中。
  基本原理
    
1.  WIN32进程的内存管理 
众所周知,WINDOWS NT实现了虚拟存储器,每一WIN32进程拥有4GB的虚存空间, 关于WIN32进程的虚存结构及其操作的具体细节请参阅WIN32 API手册, 以下仅指出与Detours相关的几点: 
 (1) 进程要执行的指令也放在虚存空间中 
 (2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序 
(3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码 。
2. 拦截WIN32 API的原理 
Detours定义了三个概念:
    (1) Target函数:要拦截的函数,通常为Windows的API。
(2) Trampoline函数:Target函数的部分复制品。因为Detours将会改写Target函数,所以先把Target函数的前5个字节复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。
(3) Detour 函数:用来替代Target函数的函数。 

Detours 在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数的调用引导到自 己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+5共10个字节 作为Trampoline函数。请参考下面的图1和图2。

 
(图1:Detour函数的过程)
https://i-blog.csdnimg.cn/blog_migrate/28eca7829100c0ec439bb3308a99f192.png
 
(图2: Detour函数的调用过程)

https://i-blog.csdnimg.cn/blog_migrate/463d456c74e1cea63d2bf4d7a877bca5.png

说明:
  目标函数:
目 标函数的函数体(二进制)至少有5个字节以上。按照微软的说明文档Trampoline函数的函数体是拷贝前5个字节加一个无条件跳转指令的话(如果没有 特殊处理不可分割指令的话),那么前5个字节必须是完整指令,也就是不能第5个字节和第6个字节是一条不可分割的指令,否则会造成Trampoline函 数执行错误,一条完整的指令被硬性分割开来,造成程序崩溃。对于第5字节和第6个字节是不可分割指令需要调整拷贝到杂技函数(Trampoline)的字 节个数,这个值可以查看目标函数的汇编代码得到。此函数是目标函数的修改版本,不能在Detour函数中直接调用,需要通过对Trampoline函数的 调用来达到间接调用。
  Trampoline函数:
此函数默认分配了32个字节,函数的内容就是拷贝的目标函数的前5个字节,加上一个JMP Address_of_ Target _ Function+5指令,共10个字节。
此函数仅供您的Detour函数调用,执行完前5个字节的指令后再绝对跳转到目标函数的第6个字节继续执行原功能函数。
  Detour函数:
此 函数是用户需要的截获API的一个模拟版本,调用方式,参数个数必须和目标函数相一致。如目标函数是__stdcall,则Detour函数声明也必须是 __stdcall,参数个数和类型也必须相同,否则会造成程序崩溃。此函数在程序调用目标函数的第一条指令的时候就会被调用(无条件跳转过来的),如果 在此函数中想继续调用目标函数,必须调用Trampoline函数(Trampoline函数在执行完目标函数的前5个字节的指令后会无条件跳转到目标函 数的5个字节后继续执行),不能再直接调用目标函数,否则将进入无穷递归(目标函数跳转到Detour函数,Detour函数又跳转到目标函数的递归,因 为目标函数在内存中的前5个字节已经被修改成绝对跳转)。通过对Trampoline函数的调用后可以获取目标函数的执行结果,此特性对分析目标函数非常 有用,而且可以将目标函数的输出结果进行修改后再传回给应用程序。

Detour提供了向运行中的应用程序注入Detour函数和在二进制 文件基础上注入Detour函数两种方式。本章主要讨论第二种工作方式。通过Detours提供的开发包可以在二进制EXE文件中添加一个名称为 Detour的节表,如下图3所示,主要目的是实现PE加载器加载应用程序的时候会自动加载您编写的Detours DLL,在Detours Dll中 的DLLMain中完成对目标函数的Detour。
 
(图3)

https://i-blog.csdnimg.cn/blog_migrate/9c067fc50300a0189d322127c84af678.png

二、  Detours提供的截获API的相关接口

Detours的提供的API 接口可以作为一个共享DLL给外部程序调用,也可以作为一个静态Lib链接到您的程序内部。

Trampoline函数可以动态或者静态的创建,如果目标函数本身是一个链接符号,使用静态的trampoline函数将非常简单。如果目标函数不能在链接时可见,那么可以使用动态trampoline函数。

  要使用静态的trampoline函数来截获目标函数,应用程序生成trampoline的时候必须使用
DETOUR_TRAMPOLINE宏。DETOUR_TRAMPOLINE有两个输入参数:trampoline的原型和目标函数的名字。
注 意,对于正确的截获模型,包括目标函数,trampoline函数,以及截获函数都必须是完全一致的调用形式,包括参数格式和调用约定。当通过 trampoline函数调用目标函数的时候拷贝正确参数是截获函数的责任。由于目标函数仅仅是截获函数的一个可调用分支(截获函数可以调用 trampoline函数也可以不调用),这种责任几乎就是一种下意识的行为。

使用相同的调用约定可以确保寄存器中的值被正确的保存,并且保证调用堆栈在截获函数调用目标函数的时候能正确的建立和销毁。

可以使用DetourFunctionWithTrampoline函数来截获目标函数。这个函数有两个参数:trampoline函数以及截获函数的指针。因为目标函数已经被加到trampoline函数中,所有不需要在参数中特别指定。

  我们可以使用DetourFunction函数来创建一个动态的trampoline函数,它包括两个参数:一个指向目标函数的指针和一个截获函数的指针。DetourFunction分配一个新的trampoline函数并将适当的截获代码插入到目标函数中去。

当目标函数不是很容易使用的时候,DetourFindFunction函数可以找到那个函数,不管它是DLL中导出的函数,或者是可以通过二进制目标函数的调试符号找到。

DetourFindFunction 接受两个参数:库的名字和函数的名字。如果DetourFindFunction函数找到了指定的函数,返回该函数的指针,否则将返回一个NULL指针。 DetourFindFunction会首先使用Win32函数LoadLibrary 和GetProcAddress来定位函数,如果函数没有在 DLL的导出表中找到,DetourFindFunction将使用ImageHlp库来搜索有效的调试符号(译注:这里的调试符号是指Windows本 身提供的调试符号,需要单独安装,具体信息请参考Windows的用户诊断支持信息)。DetourFindFunction返回的函数指针可以用来传递 给DetourFunction以生成一个动态的trampoline函数。

我们可以调用DetourRemoveTrampoline来去掉对一个目标函数的截获。

注意,因为Detours中的函数会修改应用程序的地址空间,请确保当加入截获函数或者去掉截获函数的时候没有其他线程在进程空间中执行,这是程序员的责任。一个简单的方法保证这个时候是单线程执行就是在加载Detours库的时候在DllMain中呼叫函数。

三、  使用Detours实现对API的截获的两种方法

建立一个MFC对话框工程,在对话框的OK按钮的单击事件中加入对MessageBoxA函数的调用,编译后的程序名称MessageBoxApp,效果如图。

https://i-blog.csdnimg.cn/blog_migrate/768ad84ed01ffb28d3bcadc56b88ebd9.png 
(图4)


  静态方法

建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:

DETOUR_TRAMPOLINE(int WINAPI Real_Messagebox(HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
UINT uType), ::MessageBoxA);

生成一个静态的MessageBoxA的Trampoline函数,在Dll工程中加入目标函数的Detour函数:

int WINAPI MessageBox_Mine( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType)
{
  CString tmp= lpText;
  tmp+=” 被Detour截获”;

  return Real_Messagebox(hWnd,tmp,lpCaption,uType);

//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error 

}

在Dll入口函数中的加载Dll事件中加入:

DetourFunctionWithTrampoline((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);

在Dll入口函数中的卸载Dll事件中加入:

DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);

  动态方法

建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:

//声明MessageBoxA一样的函数原型
typedef int  (WINAPI * MessageBoxSys)( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType);

//目标函数指针
MessageBoxSys SystemMessageBox=NULL;

//Trampoline函数指针
MessageBoxSys Real_MessageBox=NULL;


在Dll工程中加入目标函数的Detour函数:

int WINAPI MessageBox_Mine( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType)
{
  CString tmp= lpText;
  tmp+=” 被Detour截获”;

  return Real_Messagebox(hWnd,tmp,lpCaption,uType);

//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error 

}

在Dll入口函数中的加载Dll事件中加入:

  SystemMessageBox=(MessageBoxSys)DetourFindFunction("user32.dll","MessageBoxA");

  if(SystemMessageBox==NULL)
  {
    return FASLE;
  }

  Real_MessageBox=(MessageBoxSys)DetourFunction((PBYTE)SystemMessageBox, (PBYTE)MessageBox_Mine);

在Dll入口函数中的卸载Dll事件中加入:

DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);

  重写二进制可执行文件
使用Detours自带的SetDll.exe重写二进制可执行文件,可以在需要截获的程序中加入一个新的Detours的PE节表。对于本文就是新建一个批处理文件调用SetDll.exe。

@echo off
if not exist MessageBoxApp.exe (
echo 请将文件解压到MessageBoxApp.exe的安装目录, 然后执行补丁程序
) else (
setdll /d:ApiHook.dll MessageBoxApp.exe
)
Pause

调用后使用depends.exe(微软VC6.0开发包的工具之一)观察MessageBoxApp.exe前后变化, 可以看到Setdll已经重写MessageBoxApp.exe
成功,加入了对ApiHook.dll的依赖关系。



此图已经缩小,点击察看原图。





      (执行SetDll.exe前)                                                       (执行SetDll.exe后)

执行SetDll.exe重写后的MessageBoxApp.exe,点击确定后可以看到结果如下:

 

至此,MessageBoxApp.exe对MessageBoxA函数的调用已经被截获,弹出的对话框内容已经明显说明这一点。 
 
DDetours:Delphi绕行库 DDetours是一个库,可让您挂接Delphi和Windows API函数。 它提供了一种简单的插入和移除挂钩的方法。 2.2版有哪些新功能? 支持FPC和较早的Delphi版本,特别是D7。 支持递归部分。 支持每个蹦床功能的自定义参数/标签。 有关完整更改,请参见CHANGELOG。 特征 : 支持x86和x64体系结构。 支持单个功能的多个钩子。 支持Delphi 7 / 2005-2010 / XE-Rio(Delphi 10.3)。 支持拉撒路/ FPC。 在hook函数中支持递归函数。 通过MethodName或MethodIndex支持挂钩接口方法。 支持 立即下载

相关推荐

缺乏detours.h引用问题

Detours是Microsoft开发一个库,1拦截x86机器上的任意的win32 API函数。 2插入任意的数据段到PE文件中,修改DDL文件的导入表。这是已经编译好的头文件以及lib包,只需要复制到项目即可。

Delphi中的钩子函数HOOK详解

Delphi中的钩子函数--HOOK,即系统挂钩捕捉键盘操作实例    在WINDOWS系统下,应用程序常常要截获其他程序的消息,并加以处理(例如跟踪键盘或鼠标的按键状况等)。    现在,我们假设在前台进行正常操作,在后台利用HOOK程序为系统安装一个键盘挂钩,当有按键操作时,系统发给键盘挂钩对应的消息,而这些消息被HOOK程序截获,并加以相应的处理,这样就可以监视键盘的使用状况了。一.实现方法

小宇飞刀的BLOG 1651

Detours4.0最新版HOOK库源码,支持32及64位程序,这是正版源码。官方是收费的。

Detours4.0最新版,支持32及64位程序,这是正版源码。官方是收费的。

微软研究院Detour开发包之API拦截技术

微软研究院Detour开发包之API拦截技术【】2009年03月12日 星期四 21:56标 题: 微软研究院Detour开发包之API拦截技术【原创】<br />作 者:shangzh<br />时 间: 2007-01-29,16:03<br />链 接: http://bbs.pediy.com/showthread.php?t=38759<br /><br />我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通

ljmscsq的专栏 1339

LSF实践专题(15):LSF队列优先级以及抢占功能初探

在LSF暂停作业时,会向作业发送一个SIGTSTP信号,并且将作业状态变成SSUSP(system suspend),表示被系统暂停,这时,最好是作业的应用能够捕获和处理SIGTSTP信号,否则,即使在LSF中,作业会被认为暂停了,并且释放了slots资源,但是在实际OS中,作业进程仍然在继续,并且不会释放CPU等计算资源。是指LSF自动将低优先级作业暂停(suspend),将空余出来的资源交给高优先级队列中的作业使用,等到高优先级队列的作业结束后,再将被暂停的作业恢复(resume)并继续运行。

richycn的博客 1919

Amesim管路仿真进阶:如何用阻力管实现不规则管路的高精度模拟

本文深入探讨了在Amesim仿真中,如何利用阻力管(Orifice with Table)元件,特别是TFORT0子模型,实现对不规则管路的高精度模拟。通过直接输入基于测试或CFD的流量-压降数据,该方法能有效弥补标准管路模型在复杂流道、内部结构复杂等场景下的不足,为液压、热管理等系统仿真提供精准可靠的部件模型。

cicd6pipeline的博客 671

[转]微软研究院Detour开发包之API拦截技术

 转载自:http://www.cnblogs.com/blue.net/archive/2009/07/30/1535214.html微软研究院Detour开发包之API拦截技术我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。 通过访 问源代码,我们可以轻而易举的使用重建(Rebuilding)操作

matrix2009的专栏 1269

Drools vs URule:5个真实项目场景告诉你如何选择开源规则引擎

本文通过电商风控、物流计费、会员体系、保险定价和物联网告警五个真实项目场景,深度对比了Drools与URule两款开源规则引擎。分析了两者在规则复杂度、性能表现、开发运维及适用场景上的核心差异,为技术选型提供基于实战的决策指南。

k6l7m8n9的博客 944

Detour开发包之API拦截技术(转载)

标 题: 微软研究院Detour开发包之API拦截技术作 者: shangzh时 间: 2007-01-29,16:03链 接: http://bbs.pediy.com/showthread.php?t=38759我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通过访问源代码,我们可以轻而易举的使用重建

johns78的专栏 733

Prokka实战:10分钟搞定细菌基因组注释(附详细参数解析)

本文深入解析Prokka细菌基因组注释工具的核心参数与实战策略。通过拆解其集成化工作流程,详细解读物种分类、功能注释、输出控制等关键参数,并提供快速初筛、高质量发表、质粒注释及批量处理四种典型场景的高效参数组合方案,帮助用户精准掌控注释过程,将原始序列转化为有价值的生物学见解。

weixin_29271053的博客 442

15.1-缓存调试解析

摘要:DSU-120提供L3缓存和监听过滤器(SF)RAM的调试功能,通过CLUSTERCDBG寄存器控制访问。该功能需在集群ON电源模式下使用,且需确保单核访问。寄存器位字段根据读写操作不同,可配置WAY、RAM类型等参数。数据读取分为监听过滤器RAM、标签RAM、数据RAM及MTE标签四种类型,各有特定的位字段解释。配置参数包括切片ID宽度、标签索引宽度等,随缓存大小变化。

baron-周贺贺-代码改变世界ctw 110

微软研究院Detour开发包之API拦截技术【原创】

标 题: 微软研究院Detour开发包之API拦截技术【原创】 作 者: shangzh 时 间: 2007-01-29,16:03 链 接: http://bbs.pediy.com/showthread.php?t=38759 我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通过访 问源代码,我们可以

小虎的空间 658

第 2 章:PassThrough 直通滤波

通过设置某个维度(如 x、y、z 或 rgb)的取值范围,仅保留该范围内的点,从而达到**点云裁剪(裁边)**或过滤异常值的目的。所有在该范围之外的点会被移除(可选是否保留);点云中包含背景、地面或传感器噪声,需要过滤;通过 z 轴过滤,只保留桌面上方的物体;多轴组合过滤(如同时过滤 x、y、z);可用于地面剔除、车载点云预处理等场景。不支持一次过滤多个字段,可多次调用;仅处理某一层或某一区域的点云数据。原始点云中包含地面、墙面、背景等;在区域裁剪、前景提取中广泛使用;设定一个轴(如z轴);

yumeiguo的博客 337
上一篇: Detour
下一篇: 注入Winlogon进程示例代码
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值