这一期主要分享Hook中的Trampoline(蹦床)技术,这个相当于是Detour的进化版。Trampoline的最大的优势是解决Detour调用被Hook函数带来的无限递归问题。
一,技术介绍Trampoline和Detour的区别1.Dertour(转向)结合上一期内容Detour是拦截目标函数并把代码重定向到自己的函数(Hook函数)当中。比如当程序正常调用一个目标函数时实际上执行的是被我们修改后的指令,通过插入的Jmp指令让CPU跳转到我们的代码。本质就是拦截和重定向目标函数。
举例:汽车正常形式的一条公路上,我们设立了个路障(拦截)和指示牌(转向),强制让所有车开往我们指定的一条小路(Hook函数)上。
2.Trampoline(蹦床)跟Detour不同的是,在实行Detour之前先备份被窃取的字节(原始指令),再分配一块内存空间(Trampoline空间)存放原始指令。在这原始指令后面紧接着一个Jmp指令用来跳转回被窃取的字节之后的位置,继续执行原始函数的剩余部分。这样就达到了备份原始指令的目的,我们先通过Detour跳转到我们的Hook函数执行想要的功能逻辑(如果Ho ...
今天分享函数Hook中的Detour技术,这项技术可以拦截修改或者完全替换目标函数的任意代码。我们最多接触的是Cheat Engine 当中的注入脚本功能,想把这个功能转换成C++程序的话只能通过detour(转向)来实现。下面这篇文章当中将介绍Hook技术的具体实现detour方法。
一,技术介绍1.Detour和Hook的区别在一些技术文章中总能看到两种术语,Detour和Hook。Hook是个更广泛的概念,一般是指拦截和修改正常执行程序的技术。Hook有多种实现方式,其中一个是detour。
那么Detour指的是通过跳转来转向原始程序的技术。先转向到另一段代码(此代码不一定是自己的代码,可以转向到进程内存的不同位置)然后通常会返回原始位置。
在实际编程开发当中,很多开发者会把这两种术语互换使用。尤其是在Windows开发领域。例如微软的Detour库本质上就是个函数hooking的库,但是名称却使用了”Detours”。
2.中间函数钩子(Mid Function Hooking)detour技术还有一种称呼叫 Mid Function Hooking 。我们Detour函数 ...
今天分享的新技术是怎么调用游戏当中的函数,这就引出一个新问题,为啥要调用游戏中的函数?虽然我们可以自己为游戏编写任何形式的函数来执行,但是有一部分复杂的函数是很难自己去写的。比如射线检测函数,游戏中成功定位到此函数的话就没必要单独再编写一份复杂的射线检测了,直接调用自带的函数即可。
一,技术解析这种技术一般被称为 “函数指针重定向” ,这项技术允许我们直接调用游戏内存中的函数,就跟调用自己写的函数一样。这项技术通常用于游戏模组开发,游戏外挂开发,调试工具开发等技术。以下是C++形式的大致原理讲解:
12345678//通过typedef定义函数指针typedef cvar_t*(__cdecl * _Cvar_Get)(const char *var_name, const char *var_value, int flags);//将函数指针进行实例化,将其内存指向指定地址_Cvar_Get Cvar_Get = (_Cvar_Get)0x043F688;//调用函数Cvar_Get("cl_gamepath", "OpenArena", 0 ...
大部分FPS作弊程序都有一些必不可少的功能,包括自瞄,透视,自动扳机等。在研究这项技术时我发现这些技术的关键点在于调用游戏中的射线检测函数。下面我将介绍一些常见游戏引擎当中的射线检测功能,以及简单的讲解射线检测的实现原理。
一,射线检测的介绍基本原理首先射线就是一条从一个点出发一直延长的线,跟现实中的激光一样但是在游戏中是无终点并且一般是不可见的。这条从一个点射出来的线碰到障碍物(开发者定义的障碍物)就会停止。在FPS游戏从始至终一直会使用这个射线来检测与游戏场景当中一些特定物体的交互情况。
在游戏中射线检测有很多的用途,比如玩家前面有一扇门,游戏开发者设定按下E键会开门。按照一般逻辑我们只有接近门然后视角对着门按E才能开门。那么怎么知道玩家是否在门的附近,而且是否面对着门呢?
当然就是用射线检测来实现这一功能。这个功能跟蝙蝠的超声波一样,从玩家的准星当中发出一条直线类似于超声波,等遇到前方的门或者其他物品之后这条射线就停止运动并返回它碰到的物品信息。在每一帧一直检测玩家的准星发射的射线碰到的物品以及距离,再根据相应的物品做出相应的操作。
在一部分游戏中摄像机发射的Line Tr ...
逆向工程
未读这一期分析游戏的得分系统,我原本以为得分系统是很简单的其实没有那么简单。因为游戏采用了单独加分减分机制最终得分会根据当时一段时间的各种分数的加减来计算出来的。不跟据时间进行的计算会通过其他函数来进行写入操作,所以主要涉及更新得分的函数有两个。
分数函数的分析1.查找得分地址在游戏左上角可以看到得分系统其实都是按整数来计算的,在 Cheat Engine 当中我们直接按 4字节 来进行搜索,每干掉一个非目标NPC都会进行相应的惩罚并减分数。从0开始搜索,按照杀掉的NPC输入相应的负值再次反复搜索就能定位到分数地址。
这里搜到的地址有5个而且都是静态地址,分数从游戏开始到结束都会存在并且不受环境因素影响(一会消失一会出现),所以一般都会以静态地址的方式来存储的。这里我们需要从这5个地址当中找到真正的分数地址,因此对每个地址的分数进行不停的修改直到找到真正的分数地址,最后锁定的正确地址为 HMA.exe+D64A78 。但是发现分数为正的时候是正常存储的,为负的时候变成了很大一串数字。这其实是因为补码的形式存储负数而导致的,补码最高位是符号位,0表示正数1表示负数。所以负数正常看的情况 ...
逆向工程
未读这一期主要分析对NPC造成伤害函数以及后座力函数。使用的工具有IDA Pro和Cheat Engine,还有利用Class Informer插件来简化工作量。
一,后座力函数的分析1.定位函数每次找指定的函数之前都建议用 Class Informer 插件来进行关键字搜索。比如我们这里需要查找跟后座力相关的类,那么我们就搜索关键字 Recoil 便能搜寻到相关的类:
很幸运地只搜到了叫 ZHM5WeaponRecoil 的类,看名称就知道是跟武器后座力有关的。双击打开可以看到虚函数表,每一个虚函数点进去找到最长的那一个,F5 生成 C++ 伪代码之后就可以分析了。
2.函数伪代码大致分析可以发现这个函数是通过 __thiscall 方式调用的,接受两个参数一个是this指针(指向武器对象),另一个是浮点数(可能与射击时间或强度有关)。把此函数命名为 weaponRecoil :
1void __thiscall weaponRecoil(int this, float a2);
现在通过 Cheat Engine 的动态分析可以确定的是 this+0x38 / 0x3 ...
逆向工程
未读这一期主要分析射击函数,分析步骤跟上一期一样先用Cheat Engine来定位函数位置,再通过IDA Pro进行静态分析。大多数FPS游戏中找射击函数是要通过子弹数来定位的,第一步自然而然就是找出内存中的子弹存储地址。再查看此地址被哪个汇编代码所更改来锁定相应的函数。
射击函数的分析一,定位子弹内存地址首先把Cheat Engine附加进程到游戏的可执行程序当中,然后搜索随便一个枪械的子弹数量。子弹数量多数情况下会被存储为整数形式,有可能是2字节的也有可能是4字节的。要是没有搜到可以换扫描类型来搜索,一些游戏会对子弹数或者生命值之类的数据进行加密处理,这种情况后续会单独出一期教程来讲解。现在回到主题在4字节搜索的情况下进行多次搜索还是不能定位到子弹数量。切换2字节类型来进行搜索很快就能找到子弹数量,但是有三个搜索结果都是子弹数量。
可以看到其中两个是静态地址,把这其中一个数据进行修改回到游戏查看实际子弹数量有没有发生改变。把三个数据都挨个进行测试之后发现两个静态地址修改后不会发生任何变化。所以可以确定这两个静态地址不是真正的子弹内存地址。
二,找出子弹相关的汇编代码筛选来子弹地址 ...
逆向工程
未读本系列HITMAN 5的教程主要是针对游戏的主要功能进行逆向分析,使用的工具分别有Cheat Engine ,IDA Pro ,ReClass.NET 。Cheat Engine 是用来实时调试,修改内存值,测试验证推理等等用途。IDA Pro 用来静态分析函数的主要实现逻辑等。ReClass.NET 可以分析数据的内存结构,类指针的分析。
这一期教程的分析内容主要针对生命值函数。下面对这一函数进行锁定位置和详细分析运行逻辑。本系列教程的后续会对游戏的主要功能函数都挨个进行分析。
生命值函数的分析一,定位生命值首先打开Cheat Engine并且点击左上角的选择程序按钮,选择游戏程序点确定就能把调试器附加到游戏上面。此时可以对游戏内存地址进行任意的搜索。
生命值一般在游戏当中以浮点值的形式存储的,单浮点数占用4个字节的位置,因此搜索时可以用4字节方式搜索也可以直接按浮点数形式搜索。一般情况下都是按四字节来搜索,因为少部分游戏不采用浮点值存储而用整数值,所以以防万一我这里还是按照四字节方式来搜索。在这款游戏中生命值的具体数值时看不到的,在低难度的情况下收到伤害之后生命值会慢慢的进行 ...
技术分享
未读PID是Process ID的缩写,每个正在运行的软件都会有各自的PID,类似于身份证号。只要进程被运行,操作系统会给每个运行的进程分配一个数字标识符。获得PID就可以对指定的进程进行内存修改,附加调试器等等操作。正常情况下打开Windows系统的任务管理器就能看到所有进程的PID信息:
模块基址(Module Base Address)指的是被加载到内存中程序的内存空间起始地址。每打开一个进程操作系统除了分配PID之外还会给程序分配一段内存地址用来存放程序的代码和数据。这个内存地址的起点就是模块基址。PID是身份证号情况下模块基址相当于是家庭住址。
PID和模块基址对于逆向分析和内存分析来说至关重要,下面我会介绍外部程序(.exe程序)和DLL注入(内部注入)获取程序的PID和模块基址的具体方法。
一,外部程序1.PID获取(1)Windows API外部程序主要是通过调用 Windows API 的方式来获取其他程序的所有信息。要获取PID有几个API需要先了解分别是CreateToolhelp32Snapshot 函数:
1234HANDLE CreateToolhelp32 ...