首页 > 编程语言 >封装Detours用于Python中x64函数hook

封装Detours用于Python中x64函数hook

时间:2023-12-22 17:55:30浏览次数:32  
标签:lib 编译 Python x64 hook Detours

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日志

标签:lib,编译,Python,x64,hook,Detours
From: https://www.cnblogs.com/kanadeblisst/p/17922099.html

相关文章

  • #!/usr/bin/python3 和 #!/usr/bin/env python3 的区别
    #!/usr/bin/python3和#!/usr/bin/envpython3有何用处和区别,调用模块脚本时不加这句会报错。这个问题可能不少初学者也会遇到,实际上它的作用是用来指定Python的解释器。 脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它。——相当于写死了......
  • Python脚本
    Python脚本:Python脚本,比Shell要强大一些1.编辑一个文本文件,保存为hello.py2.添加可执行权限chmod +x hello.py 3.执行程序./hello.py ......
  • day 03-3 Python基础-运算符
    3.运算符3.1常见的运算符算数运算符运算符描述示例+加-减*乘/除%取模-返回除法的余数10%3结果输出1**指数-幂,x的y次幂2**3结果输出位8//整除-返回商的整数部分9//2结果输出为49.0//2.0结果输出位4.0比较运算符运算符......
  • react Hooks+Context 实现响应式布局
    1.创建文件 viewportContext.tsx importReactfrom"react";constdefaultValue={  width:window.innerWidth}constviewportContext=React.createContext(defaultValue);constViewportProvider=({children})=>{  const[width,setWidt......
  • python批量给文本文件txt内容添加特殊符号等内容:-----------------------------------
    python脚本内容如下:#导入需要使用的模块importosimporttkinter.filedialogfn=tkinter.filedialog.askopenfilename(title='选择了一个文件',filetypes=[('文本文件','.txt'),('所有文件','.*')])print("打开了文件:"+fn)line_count=0f=open......
  • 10个Python脚本自动化日常任务
    在这个自动化时代,我们有很多重复无聊的工作要做。想想这些你不再需要一次又一次地做的无聊的事情,让它自动化,让你的生活更轻松。那么在本文中,我将向您介绍10个Python自动化脚本,以使你的工作更加自动化,生活更加轻松。因此,没有更多的重复任务将这篇文章放在您的列表中,让我们开始......
  • Python自动化脚本
    自动生成素描草图在注册一些网站时,经常发愁头像怎么选?放真人照上去怕吓跑别人,放风景图片自己又不喜欢。是时候用素描草图了,妈妈再也不用担心我的头像吓跑人了!importcv2img=cv2.imread("elon.jpg")##ImagetoGrayImagegray_image=cv2.cvtColor(img,cv2.COLOR......
  • python脚本 接口
    在Python中,我们可以使用多种方式来实现和调用接口。以下是一些常见的方法:使用requests库进行HTTP请求:在Python中,我们通常使用requests库来发起API请求¹。例如,我们可以使用requests.get()方法来发起GET请求,并获取返回的状态码¹。此外,我们还可以使用requests.post()方法来发起POST......
  • Python DRF基础使用01
    目录1,web应用模式(了解)2,restful风格介绍(了解)3,restful设计风格(了解)4,restful案例(了解)5,数据准备6,查询所有数据(理解)7,创建对象(理解)8,获取单个对象(理解)9,修改单个对象(理解)10,删除单个对象(理解)11,DRF魅力展示(了解)12,序列化器概述(了解)13,序列化器定义(掌握)1......
  • Python DRF基础使用02
    目录1,ModelSerializer2,fields3,read_only_fields4,extra_kwargs5,APIView之request6,APIView之Response7,APIView实现列表视图8,APIView实现详情视图(带着id请求,所以叫做详情)9,二级视图,实现列表视图10,二级视图,实现详情视图11,get_object方法(三属性三方法其中一个)12,MiXin(提......