|
|
Day 6 -- 指针入门:地址为什么每次重启都变了
Cheat Engine 从入门到住院 · Day 6
你花了 20 分钟找到了血量地址,改成了 99999,爽了一把。然后关掉游戏去吃饭,回来重新打开,血量地址变成了。
之前的工作全白费了。
这就像你记住了朋友住在"第 3 排第 7 号房间",但每次他搬家都换房间。你每次去找他都要重新打听。
有没有一个"永远不变的地址"能指向他?有的,这就是指针。
━━━━━━━━━━━━━━━━━━━━
本文你将学到
为什么内存地址每次重启会变(动态分配)
什么是指针,为什么指针地址是固定的
如何用 CE 找到指针
用指针实现"重启后依然有效"的修改
阅读时间:15 分钟 | 实操时间:30 分钟 | 难度:进阶
━━━━━━━━━━━━━━━━━━━━
CE Tutorial Step 6:指针
进入 Step 6。又是血量和 Change value 按钮。
但这一步的要求是:找到一个指针,使得即使点了 "Change pointer" 按钮(模拟重启,血量地址会变),你的修改依然有效。
━━━━━━━━━━━━━━━━━━━━
为什么地址会变
程序运行时,需要存储数据(血量、金币等)。操作系统会给程序分配内存,但每次分配的位置不一定相同。
这就像你去酒店开房间——每次入住分配的房间号不一样。你的行李(数据)每次在不同的房间里。
技术上这叫动态内存分配(Dynamic Memory Allocation)。程序用或申请内存,操作系统给一块空闲区域,具体在哪里取决于当时的内存使用状况。
所以直接记住地址没用,下次就变了。
━━━━━━━━━━━━━━━━━━━━
指针是什么
但程序自己总得知道血量在哪里吧?它不可能每次都重新搜索。
答案是:程序在一个固定的位置存了一个"门牌号",指向血量的实际地址。这个"门牌号"就是指针。
- 固定地址 0x00400000(指针)
- ↓ 存储的值是
- ↓ 0x0A1B2C3D
- ↓
- ↓ 指向
- ↓
- 动态地址 0x0A1B2C3D(血量 = 100)
复制代码
指针地址(0x00400000)是固定的,因为它存在程序的全局变量区或静态数据区,这些区域在程序加载时位置就确定了。
血量地址(0x0A1B2C3D)是动态的,每次运行可能不同。但指针的值会跟着更新,始终指向血量的当前位置。
所以你只要找到指针,就能永远找到血量。这就像:你不记朋友的房间号,你记他的手机号——打电话问他在哪个房间就行了。
━━━━━━━━━━━━━━━━━━━━
带偏移量的指针
现实中,指针通常不是直接指向目标值,而是指向一个结构体(数据块)的起始地址,目标值在结构体内部有一个偏移量。
- 指针 → 结构体起始地址 0x0A1B2C00
- + 偏移量 0x3D
- = 血量地址 0x0A1B2C3D
复制代码
类比:指针告诉你朋友住在"3 号楼"(结构体起始地址),偏移量告诉你他在"502 室"。完整地址是"3 号楼 502 室"。
━━━━━━━━━━━━━━━━━━━━
实操步骤
第一步:找到血量地址
用老方法找到当前血量的地址,比如。
第二步:找到什么代码在写入这个地址
右键 → Find out what writes to this address。
点 Hit me,记录下出现的指令。点击指令查看详情,在 "Extra info" 区域你会看到类似这样的信息:
- The value of the pointer needed to find this address is probably 0x0A1B2C00
复制代码
CE 会告诉你指针的可能值。同时你会看到指令类似:
这里的值就是指针指向的基地址(0x0A1B2C00),就是偏移量。
记住这两个信息:
指针指向的地址:偏移量:
第三步:搜索指针
关闭代码查找器窗口。回到 CE 主界面。
现在我们要搜索"谁存储了 0x0A1B2C00 这个值"——也就是找到指针本身。
设置:
Value:输入(注意这是十六进制)
Scan Type:Value Type:或(64 位程序用 8 Bytes)
勾选 Hex(十六进制搜索)
点击 First Scan。
结果中找到颜色为绿色的地址——绿色表示这是一个静态地址(基址),每次运行都不会变。
第四步:手动添加指针
在 CE 地址列表下方,点击 "Add Address Manually"(手动添加地址)。
勾选 "Pointer" 复选框,然后填写:
指针地址:输入刚才找到的绿色地址
偏移量(Offset):输入
点击 OK。地址列表中出现一个指针条目,显示的值应该就是当前血量。
第五步:验证
回到 Tutorial,点击 "Change pointer" 按钮。这会重新分配血量的内存地址。
看 CE 中的指针条目——它应该自动更新,显示新的地址,但值仍然是血量。
把值改成 5000,点 Tutorial 的 Next,Step 6 通关。
━━━━━━━━━━━━━━━━━━━━
绿色地址的秘密
在 CE 的搜索结果中,地址有两种颜色:
黑色:动态地址。每次运行可能不同。
绿色:静态地址(也叫基址 Base Address)。位于程序的可执行文件映像中,地址固定不变。
绿色地址是我们找指针时要重点关注的目标。因为指针链的起点必须是一个静态地址,否则整条链都会失效。
实际上,绿色地址在程序加载时会有一个"基址偏移"(Base Address + Module Offset),CE 会用类似- Tutorial-x86_64.exe+1A2B3C
复制代码 的方式表示。这种表示方式即使在有 ASLR(地址空间布局随机化)的情况下也是稳定的。
━━━━━━━━━━━━━━━━━━━━
指针的完整模型
把前面的知识串起来:
- 静态指针(绿色地址,固定不变)
- ↓ 存储的值 = 结构体基地址
- ↓
- 结构体基地址(动态,每次运行不同)
- + 偏移量
- ↓
- 目标数据(血量)
复制代码
你在 CE 中添加的指针条目,记录的是:
每次游戏运行,绿色地址里存的值可能不同(因为结构体的位置变了),但绿色地址本身的位置是固定的。CE 通过读取绿色地址里的值,加上偏移量,就能算出目标数据的当前地址。
━━━━━━━━━━━━━━━━━━━━
常见问题
Q:搜索指针时找不到绿色地址怎么办?
A:可能是多级指针——指针指向的不是静态地址,而是另一个动态地址,那个动态地址又被另一个指针指向。需要继续往上追溯,直到找到绿色地址。Day 8 会专门讲多级指针。
Q:偏移量怎么确定?
A:从代码查找器的 Extra Info 里可以看到。比如指令是,偏移量就是(十六进制)。
Q:64 位和 32 位程序的指针有什么区别?
A:32 位程序的指针是 4 字节(搜索用 4 Bytes),64 位程序的指针是 8 字节(搜索用 8 Bytes)。CE Tutorial 的 64 位版本需要用 8 Bytes 搜索指针。
━━━━━━━━━━━━━━━━━━━━
小结
今天我们跨过了 CE 学习中的第一道门槛——指针:
内存地址每次运行会变,因为操作系统动态分配内存
指针是一个固定地址,存储着目标数据的当前位置
通过代码查找器找到指针值和偏移量
搜索指针值,找到绿色(静态)地址
用指针方式添加地址,实现重启后依然有效
指针是整个 CE 使用中最核心的概念。理解了指针,你就能理解后面的多级指针、指针扫描等高级功能。
明天 Day 7,我们要学习代码注入——不是简单地 NOP 掉代码,而是在游戏里插入你自己写的代码。这是从"破坏"到"创造"的质变。 |
|