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

封装Detours用于Python中x64函数hook的更多相关文章

  1. python中format函数用于字符串的格式化

    python中format函数用于字符串的格式化 通过关键字 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字 grade = {'name' : ...

  2. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  3. Python 中的函数

    学了 Python 中的数据类型,语句,接下来就来说一下 Python 中的函数,函数是结构化编程的核心.我们使用函数可以增加程序的可读性.自定义函数时使用关键字def 函数由多条语句组成.在定义函数 ...

  4. Python中split()函数的用法及实际使用示例

    Python中split()函数,通常用于将字符串切片并转换为列表. 一.函数说明: split():语法:str.split(str="",num=string.count(st ...

  5. python中format函数

    python中format函数用于字符串的格式化 通过关键字 1 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字 2 grade = {'nam ...

  6. 【313】python 中 print 函数用法总结

    参考:python 中 print 函数用法总结 参考:Python print() 函数(菜鸟教程) 参考:Python 3 print 函数用法总结 目录: 字符串和数值类型 变量 格式化输出 p ...

  7. 11、python中的函数(基础)

    一.什么是函数? 在数学中,x2+2x2+3=10这样的叫方程. 而ax2+bx2+c=d这样的才叫函数.数学的函数中,abcd等待输入的未知量叫自变量,它需要我们自己去输入,而x这种待求得未知量叫因 ...

  8. [19/10/13-星期日] Python中的函数

    一.函数 # 第五章 函数 ## 函数简介(function) - 函数也是一个对象 - 对象是内存中专门用来存储数据的一块区域 - 函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行 ...

  9. Python中匿名函数与内置高阶函数详解

    大家好,从今天起早起Python将持续更新由小甜同学从 初学者的角度 学习Python的笔记,其特点就是全文大多由 新手易理解 的 代码与注释及动态演示 .刚入门的读者千万不要错过! 很多人学习pyt ...

  10. 『无为则无心』Python函数 — 25、Python中的函数

    目录 1.函数的使用 (1)定义函数 (2)调用函数 (3)使用函数的注意事项 2.函数的参数 3.实参的类型 Python函数的说明: Python中函数的应用非常广泛,前面章节中我们已经接触过多个 ...

随机推荐

  1. Go开始:Go基本元素介绍

    本文深入探讨了Go编程语言中的核心概念,包括标识符.关键字.具名函数.具名值.定义类型.类型别名.包和模块管理,以及代码块和断行.这些元素是构成Go程序的基础,也是编写高质量代码的关键. 关注Tech ...

  2. 什么是IP协议?

    简介: IP(Internet Protocol)协议,又称网际协议,是TCP/IP协议的核心.它负责Internet上网络之间的通信,并规定了将数据报从一个网络传输到另一个网络所应遵循的规则.具体来 ...

  3. 一次性全讲透GaussDB(DWS)锁的问题

    本文分享自华为云社区<GaussDB(DWS)锁问题全解>,作者: yd_211043076. 一.gaussdb有哪些锁 1.常规锁:常规锁主要用于业务访问数据库对象的加锁,保护并发操作 ...

  4. window操作系统安装多个版本nodejs版本-控制工具nvm

    参考: https://blog.csdn.net/m0_38134431/article/details/118388297 https://juejin.cn/post/7044890876631 ...

  5. android模拟器推荐

    最近装了个海马模拟器用来调试cocos2dx-lua游戏. 安装完之后发现, 我之前装的virtual box被替换掉了, 因为海马模拟器要安装它自己匹配版本的virtual box, 所以我之前的装 ...

  6. Couchdb-权限绕过--命令执行--(CVE-2017-12635)&&(CVE-2017-12636)--H2database命令执行--(CVE-2022-23221)

    Couchdb-权限绕过--命令执行--(CVE-2017-12635)&&(CVE-2017-12636)--H2database命令执行--(CVE-2022-23221) 环境概 ...

  7. linux下查找文件中某字符串出现的行以及该行前后n行

    linux下查找文件中某字符串出现的行以及该行前后n行 查找指定字符串的前后n行 grep -A 100 -B 100 "要查找的字符串" 被查找的文件 -A after 后面 - ...

  8. 整理DB2左补零,右补零的方法

    在项目中经常遇到需要左补零,右补零的情况,在DB2实验环境中展示 1.左补零(1)数字左补零,数字长度不定用right(digits(cast(expression as bigint)),NUM)能 ...

  9. OKR 是什么?

    OKR OKR 是什么? OKR(Objectives and Key Results)目标与关键结果管理法,起源于英特尔,后在谷歌发扬光大. OKR 是一套协助组织进行目标管理的工具和方法,旨在促进 ...

  10. 洛谷P1144

    最短路计数 题目描述 给出一个 \(N\) 个顶点 \(M\) 条边的无向无权图,顶点编号为 \(1\sim N\).问从顶点 \(1\) 开始,到其他每个点的最短路有几条. 输入格式 第一行包含 \ ...