封装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里面有这么一段话:

封装Detours用于Python中x64函数hook

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

封装Detours用于Python中x64函数hook

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

错误

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

封装Detours用于Python中x64函数hook

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

封装Detours用于Python中x64函数hook

开始编译

如果要编译64位就打开64位的命令行,set path=C:Program Files (x86)Microsoft SDKsWindowsv10.0AbinNETFX 4.8 Toolsx64;%path%

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

封装Detours用于Python中x64函数hook

这样就编译成功了,然后就会在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)选所有平台,避免每个配置都要添加一遍

封装Detours用于Python中x64函数hook

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

封装Detours用于Python中x64函数hook

你可以在输入里填lib库的名称(detours.lib)封装Detours用于Python中x64函数hook

不过我更喜欢在代码里用#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框架实战打印微信日志这篇文章留的一个坑:如何在新函数里调用原函数。

封装Detours用于Python中x64函数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日志


原文始发于微信公众号(Python成长路):封装Detours用于Python中x64函数hook

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/195989.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!