封装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 clean
、nmake 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的更多相关文章
- python中format函数用于字符串的格式化
python中format函数用于字符串的格式化 通过关键字 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字 grade = {'name' : ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- Python 中的函数
学了 Python 中的数据类型,语句,接下来就来说一下 Python 中的函数,函数是结构化编程的核心.我们使用函数可以增加程序的可读性.自定义函数时使用关键字def 函数由多条语句组成.在定义函数 ...
- Python中split()函数的用法及实际使用示例
Python中split()函数,通常用于将字符串切片并转换为列表. 一.函数说明: split():语法:str.split(str="",num=string.count(st ...
- python中format函数
python中format函数用于字符串的格式化 通过关键字 1 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字 2 grade = {'nam ...
- 【313】python 中 print 函数用法总结
参考:python 中 print 函数用法总结 参考:Python print() 函数(菜鸟教程) 参考:Python 3 print 函数用法总结 目录: 字符串和数值类型 变量 格式化输出 p ...
- 11、python中的函数(基础)
一.什么是函数? 在数学中,x2+2x2+3=10这样的叫方程. 而ax2+bx2+c=d这样的才叫函数.数学的函数中,abcd等待输入的未知量叫自变量,它需要我们自己去输入,而x这种待求得未知量叫因 ...
- [19/10/13-星期日] Python中的函数
一.函数 # 第五章 函数 ## 函数简介(function) - 函数也是一个对象 - 对象是内存中专门用来存储数据的一块区域 - 函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行 ...
- Python中匿名函数与内置高阶函数详解
大家好,从今天起早起Python将持续更新由小甜同学从 初学者的角度 学习Python的笔记,其特点就是全文大多由 新手易理解 的 代码与注释及动态演示 .刚入门的读者千万不要错过! 很多人学习pyt ...
- 『无为则无心』Python函数 — 25、Python中的函数
目录 1.函数的使用 (1)定义函数 (2)调用函数 (3)使用函数的注意事项 2.函数的参数 3.实参的类型 Python函数的说明: Python中函数的应用非常广泛,前面章节中我们已经接触过多个 ...
随机推荐
- iFiles浏览iphone文件
我们希望能在iphone中浏览文件系统的目录
- 详细解释一下Spring是如何解决循环依赖问题的
Spring是如何解决循环依赖问题的? 我们都知道,如果在代码中,将两个或多个Bean互相之间持有对方的引用就会发生循环依赖.循环的依赖将会导致注入死循环,这是Spring发生循环依赖的原因 循环依赖 ...
- 面试官:说一下 MyBatis 缓存机制?
MyBatis 的缓存机制属于本地缓存,适用于单机系统,它的作用是减少数据库的查询次数,提高系统性能. MyBaits 中包含两级本地缓存: 一级缓存:SqlSession 级别的,是 MyBatis ...
- Games101现代计算机图形学入门 - 作业1~8 集合含提高项总结
Github 地址 :Games101 作业总结 Games101 官网:Games101 - 现代图形学入门 记录 Games101 Homework 系列 1 ~ 8 及相关作业提高项 环境安装 ...
- MySQL实战实战系列 07 行锁功过:怎么减少行锁对性能的影响?
在上一篇文章中,我跟你介绍了 MySQL 的全局锁和表级锁,今天我们就来讲讲 MySQL 的行锁. MySQL 的行锁是在引擎层由各个引擎自己实现的.但并不是所有的引擎都支持行锁,比如 MyISAM ...
- 开源.NetCore通用工具库Xmtool使用连载 - 扩展动态对象篇
[Github源码] <上一篇> 介绍了Xmtool工具库中的图形验证码类库,今天我们继续为大家介绍其中的扩展动态对象类库. 扩展动态对象是整个工具库中最重要的一个设计.在软件开发过程中, ...
- threading 专递类对象
import threading class MyClass: def __init__(self, name): self.name = name def my_method(self): prin ...
- python setup.py sdist bdist_wheel
# python setup.py sdist bdist_wheel# twine upload dist/*import ioimport osimport sysfrom shutil impo ...
- DevOps|研发效能解决的是企业效率问题
研发效能并不能解决企业效益问题 它不是利润中心,不能给你带来直接收入(研发效能相关工具厂商做咨询.出方案.卖工具除外).想要解决企业效益问题,依赖于企业战略.业务/产品.组织.运营.创新等其他方面. ...
- jmeter的全局变量(将登陆token设置全局)
1.首先调用登陆接口,用json提取器,取出响应内的token值 2.在beanshell取样器中设置全局变量 //设置全局变量方法一:用函数__setProperty设置${__setProper ...