封装Detours用于Python中x64函数hook详解

 更新时间:2023年12月23日 08:55:20   作者:Python成长路  
Detours是微软发布的一个API hook框架,同时支持x86和x64,看文档说也支持ARM和ARM64的Windows,这篇文章主要介绍了封装Detours用于Python中x64函数hook,需要的朋友可以参考下

Detours

代码仓库: https://github.com/microsoft/Detours

x64写一个任意地址hook要比x86麻烦的多,所以这里直接封装框架来用于x64的hook。

Detours是微软发布的一个API hook框架,同时支持x86和x64,看文档说也支持ARM和ARM64的Windows。

编译文档

Detours翻了下github,并没有发现什么编译文档,就只有README里面有这么一段话:

大概意思是说打开visual studio的命令行,然后切换到源码目录,执行nmake就能编译,测试除了一个小问题确实是可以编译成功。

visual studio的命令行在开始菜单里打开,上面两个是x86的,下面两个是x64的,至于x64和x86_x64有啥区别我就不清楚了,因为测试编译的时候没什么不一样的,就懒得去搜了。

错误

编译的时候有一个错误: 'sn' 不是内部或外部命令,也不是可运行的程序

搜索发现这是一个秘钥管理和签名验证的工具,而visual studio安装完后就已经有了,那就是没加入到环境变量里,用everything搜索一下,把这个路径添加到环境变量。我就临时用set命令来设置环境变量

开始编译

如果要编译64位就打开64位的命令行,
set path=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64;%path%

nmake或者nmake all(可以从cmake文件里看到,还有nmake cleannmake test等)

这样就编译成功了,然后就会在bin.X64和lib.X64生成相应的文件,需要的是lib.X64下面的lib库

怎么编译Debug版本

这样编译出来的版本应该是Release版本,因为没有pdb文件,看了下cmake文件里的信息,指定Debug版本的变量是DETOURS_CONFIG, 而指定是x86、x64、arm的变量是DETOURS_TARGET_PROCESSOR

!IF "$(DETOURS_CONFIG)" == "Debug"
DETOURS_DEBUG=1
!ELSE
DETOURS_DEBUG=0
!ENDIF

那么只需要在编译之前执行下set DETOURS_CONFIG=Debug就可以编译成Debug版本的了,会生成一个lib.X64Debug目录,里面编译出来的lib就有了pdb文件

编译成dll

Detours的使用很简单,几行代码就行了,srcFunc是hook的函数指针的指针,注意这是二级指针(PVOID就是void *),具体为什么要定义二级指针看下面的解释。newFunc是新函数的函数指针,在c++里的话,可以直接传函数名。

#include "detours.h"
DWORD DetourHookFunction(PVOID* srcFunc, PVOID newFunc) {
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	DetourAttach(srcFunc, newFunc);
	DetourTransactionCommit();
	return 0;
}
DWORD DetourUnHookFunction(PVOID* srcFunc, PVOID newFunc) {
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	DetourDetach(srcFunc, newFunc);
	DetourTransactionCommit();
	return 0;
}

为了避免大家还不知道,我说一下怎么引入头文件和lib库

引入外部头文件

如果就想Detours就两个头文件,你可以直接添加到项目里,如果头文件比较多的话,放到dllmain.cpp目录下,然后在右键属性里,配置属性->C/C++->常规->附加包含目录添加这个头文件目录,我这里用$(ProjectDir)来表示项目的目录, 你也可以添加绝对路径。

注意上面配置(C)选所有配置,平台(P)选所有平台,避免每个配置都要添加一遍

lib库则是在链接器->常规->附加库目录里添加

你可以在输入里填lib库的名称(detours.lib)

不过我更喜欢在代码里用#pragma comment(lib, "detours.lib")来引入lib库,因为这样可以根据宏来分别引入Debug还是Release的lib

#ifdef _DEBUG
#pragma comment(lib, "detours.lib")
#else
#pragma comment(lib, "detoursd.lib")
#endif

也可以判断是x86还是x64

#ifdef _WIN64
#pragma comment(lib, "detours64.lib")
#else
#pragma comment(lib, "detours32.lib")
#endif

也可以两个宏都判断一下。

hook函数为啥要定义成二级指针

我为啥要定义成二级指针?因为DetourAttach函数就是传的二级指针,它的定义如下:

LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer,
                         _In_ PVOID pDetour);

为啥DetourAttach要把它定义成二级指针? 开始我也不理解这个问题,直到我想在Python里调用原函数,发生了无限递归的异常。

为啥C++写的代码不会触发无限递归,它同样是用的函数指针来调用,要想知道原因只能自己使用x64dbg调试看看。

经过漫长的调试发现,我传进去的ppPointer指针指向的值会被修改,它不在指向原函数(被hook函数),而是指向Detours新构建的一个函数指针,这也就能解释为啥不会无限递归了

这里再接上【Python微信机器人】第六七篇: 封装32位和64位Python hook框架实战打印微信日志这篇文章留的一个坑: 如何在新函数里调用原函数。

c_log_addr就是我传给DetourAttach的第一个参数ppPointer,我通过调用Detours修改后的函数指针也就是c_log_addr.value就可以避免无限递归的问题

你可以在hook前和hook后打印下c_log_addr.value的值看一下,肯定是不一样的,

Python使用Detours

这个就看【Python微信机器人】第六七篇: 封装32位和64位Python hook框架实战打印微信日志这篇文章了,里面说了怎么用Detours的dll hook日志

相关文章

  • pytorch dataset实战案例之读取数据集的代码

    pytorch dataset实战案例之读取数据集的代码

    这篇文章主要介绍了pytorch dataset实战案例读取数据集的相关知识,这段代码可以作为读取数据集的一个DataSet类的基础类,可以扩充进行修改,以后有类似需要可以拿过来修改,本文结合实例代码给大家详细讲解,需要的朋友可以参考下
    2022-10-10
  • Python数学建模StatsModels统计回归之线性回归示例详解

    Python数学建模StatsModels统计回归之线性回归示例详解

    这篇文章主要为大家介绍了Python数学建模中StatsModels统计回归之线性回归的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • Python3.0与2.X版本的区别实例分析

    Python3.0与2.X版本的区别实例分析

    这篇文章主要介绍了Python3.0与2.X版本的区别,包含了一些常见的区别及分析,还有笔者的一些感悟,需要的朋友可以参考下
    2014-08-08
  • 浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)

    浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)

    今天小编就为大家分享一篇浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • Python爬虫定时计划任务的几种常见方法(推荐)

    Python爬虫定时计划任务的几种常见方法(推荐)

    这篇文章主要介绍了Python爬虫定时计划任务的几种常见方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Python数字图像处理代数之加减乘运算

    Python数字图像处理代数之加减乘运算

    这篇文章主要介绍了Python数字图像处理代数运算,对其中的加、减、乘运算分别作了详细的讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • Python中工厂模式的实现小结

    Python中工厂模式的实现小结

    工厂模式是一种创建型设计模式,通过定义一个工厂类,将对象的实例化过程封装起来,本文主要介绍了Python中工厂模式的实现小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • python类方法中的self关键字使用

    python类方法中的self关键字使用

    这篇文章主要介绍了python类方法中的self关键字使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 解决python中的print函数自动换行的问题

    解决python中的print函数自动换行的问题

    这篇文章主要介绍了解决python中的print函数自动换行的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • python下如何让web元素的生成更简单的分析

    python下如何让web元素的生成更简单的分析

    做web不简单,特别是当你需要使用一些web效果的时候, 比如显示个圆角矩形,提示框之类的,也许你认为很简单,好让我们分析一下:
    2008-07-07

最新评论