文章目录
- Intro
- Pointers
- Memory leaks
- Pointer path
- Pointer scanning
- Example!
Intro
上节课我们学习了静态地址,这节课我们将着手关注动态地址,我们需要了解一个叫做指针的东西
Pointers
简单地说,指针是对象之间的单向连接
Pointers are connections between objects
这里的箭头就是指针,指针不一定是从高层往低层,比如 User Interface 当然还需要指向玩家的指针来获取血量信息
- Squally.exe -> World -> Player, Enemy#1 , Enemy#2 …
- Squally.exe -> User Interface -> …
- User Interface -> Player
让我们想象一个路径:
- Squally.exe -> World -> Player -> Inventory
如果我们需要找到玩家的金币数量,金币存在 Inventory 背包里,那么
- 找到 Squally.exe 指向 World 的指针
- 找到 World 指向 Player 的指针
- 找到 Inventory 指向 Gold 的指针
Memory leaks
为了更好理解指针,我们引入一个小例子叫做内存泄漏,内存泄漏是因为销毁了指针但忘记释放或删除对象,因此在这个例子中:玩家可能穿过一扇门并加载了新的地图,但老的地图没有销毁,只是 Squally.exe 指向 World 的指针被修改了!
Pointer path
当我们试图找到黄金,我们可以大致猜测程序的构成:
Squally.exe 中包含:Player XYZ、Player Health、World*、SoundSystem*、UserInterface*…
World 中包含:Map Width/Height、Player*、Enemy List*…
Player 中包含:Player Mana、Inventory*…
Inventory 中包含:NumberOfItems、ItemList*、Gold…
这里的 * 只是一个指针的符号,在32位系统上占用 4bytes,但在64位系统上占用 8bytes,那么此时 Player XYZ、Player Health 就是静态数据,其他的几乎都是动态的!
Allocations are random, but pointer paths are reliable
地址分配是随机的,但是指针的路径是可靠的,如果我们每次都通过这个指针路线那么就能获得金币~
在开始实战之前,让我们介绍一点符号化的对象,举个例子,Squally.exe + 4,代表了玩家的 X 值,Squally.exe + C,代表了 World*,那么地址 [Squally.exe+C] 就是 World 对象,[[Squally.exe+C] + 8] 就是 Player 对象,[[[Squally.exe+C]+8]+4] 就是 Inventory 对象,[[[Squally.exe+C]+8]+4]+8 就是金币了!
TIPS:上面一段内容推荐掌握C语言基础 & 仔细观看视频理解
Pointer scanning
现在我们知道可以这样找到 GOLD 的地址,接下来我们需要找到指向金币的指针路径,CE 有指针扫描仪可以方便完成这个工作,在讲解这些工具之前,先讲讲他们实际工作的原理。
不幸的是,没有办法可以从 GOLD 回溯到 Squally.exe,所有指针都只能从 Squally.exe 开始向下找到 GOLD 数据,这是计算机和数学中的图论问题,而 CE 或者其他任何引擎都没有好办法来优雅地解决这个问题,只能通过暴力搜索,一直尝试直到找到合适的路径!
- Squally.exe -> User Interface -> Player
- Squally.exe -> World -> Player
有两种可能来找到 Player 对象,但如果当玩家在过场动画,没有加载 UI,其中这一条就会断掉,因此某些路径是具有弹性的,因此指针扫描技术的一部分是在我们讨论实际实例之前,找到从静态到动态的可靠路径
在这之前,我想快速介绍一下 DLL 或称之为动态链接库,Squally.exe 可以创建类似 UI、World 这样的对象,但这并不是唯一的办法,实际上也有可能产生其他树的根源,比如 PhysicsSystem.dll -> PhysicsWorld,因此在这个结构中,我们有一个静态的 DLL 和 Squally.exe,在这情况下玩家的XY将存放在 DLL 中。
这两棵树也需要一定程度的交互来保证信息同步,比如 Player 中可能包含一个指向 Player Physics 的指针,你仍然可以通过指针扫描找到 XY,只是有可能指针扫描会追溯到 DLL,两种方法都可以工作!
这里有一个快速的方法帮你找到 DLL,以巫师3为例,文件夹下面有 PhysX3Common_x64.dll、steam_api64.dll,如果你要为这款游戏开发反重力,那么指针可能会从 PhysDLL 获得路径!接下来我们可以使用工具来解决这些问题
Example!
右键点击你找到的数值,点击 Pointer scan for this address
这里的 level 代表了几级指针,越小越快但可能会错过一些结果
然后 CE 会要求你将结果保存到某个文件里,随后就开始扫描指针了
结束后你会获得一大批指针路径,他们绝大多数不是可靠的,你只需要重新启动游戏就可以知道他们是否可靠了
接下来重新打开游戏,继续将 CE 附加到游戏上,选择保留地址/指针列表
随后我们将重复做一遍上面的无聊工作,显然生命值的地址已经变了,旧的地址不再有效
接下来我们可以做的是,在这个指针扫描窗口,重新扫描内存,并说他现在应该指向这个新的有效地址了,重新这样操作 1~3 次之后,剩下了这些
一般来说,比较短的路径比较好,不能保证这样可靠但现在我们能做的就是保留这些比较短的路径
把他们双击全部加入 CE 的指针列表,重新打开游戏以后就可以验证你是否成功了!显然这里有5条是可用的了
有些游戏可能需要更多的指针深度,可能要调整一些参数,但目前学到的足以应对大多数情况了!