|
|
Day 7 -- 代码注入:在游戏的伤口上撒点盐
Cheat Engine 从入门到住院 · Day 7
Day 5 我们学会了 NOP——把扣血代码删掉,让游戏不再扣血。简单粗暴,但也很"粗":只能删,不能改。
如果我想要的不是"不掉血",而是"每次被打反而加血"呢?或者"每次被打掉血的同时,金币加 100"呢?
NOP 做不到。你需要一个更强大的技能——代码注入。
简单说,代码注入就是在游戏的代码流程中"插队",让游戏执行你自己写的代码,然后再回到原来的流程。
━━━━━━━━━━━━━━━━━━━━
本文你将学到
代码注入的原理
CE 的 Auto Assembler 模板
如何编写简单的注入脚本
JMP + 跳板(Trampoline)机制
阅读时间:15 分钟 | 实操时间:30 分钟 | 难度:进阶
━━━━━━━━━━━━━━━━━━━━
CE Tutorial Step 7:代码注入
进入 Step 7。照例是血量和 Hit me。
任务:每次点击 Hit me,血量不但不减少,反而增加 2。
不能用 NOP(那只是不减少),也不能用冻结(那是锁定不变)。你需要修改游戏的扣血逻辑,让它变成加血逻辑。
━━━━━━━━━━━━━━━━━━━━
代码注入的原理
游戏原来的代码流程是这样的:
- 指令 A:计算伤害
- 指令 B:血量 = 血量 - 伤害 ← 扣血代码
- 指令 C:更新血条显示
复制代码
代码注入的做法是:
- 指令 A:计算伤害
- JMP 到你的代码区域 ← 跳转到你的"跳板"
- 你的代码:血量 = 血量 + 2 ← 你的自定义逻辑
- JMP 回指令 C ← 跳回去
- 指令 C:更新血条显示
复制代码
核心思路:
在内存中找一块空闲区域,写入你的自定义代码
把原来的扣血指令替换成一条 JMP 指令,跳到你的代码
你的代码执行完后,再 JMP 跳回到原来的下一条指令
这块空闲区域就叫"跳板"(Trampoline)或"代码洞穴"(Code Cave)。
━━━━━━━━━━━━━━━━━━━━
实操步骤
第一步:找到扣血代码
用老方法找到血量地址
右键 → Find out what writes to this address
点 Hit me,记录扣血指令
选中指令,点击 "Show disassembler" 打开反汇编视图
你会看到扣血指令在反汇编视图中高亮显示。
第二步:打开 Auto Assembler
在反汇编视图中,选中扣血指令,按 Ctrl+A(或菜单 Tools → Auto Assemble)。
这会打开 Auto Assembler 窗口——CE 内置的汇编脚本编辑器。
第三步:使用模板生成框架
在 Auto Assembler 窗口中,点击菜单 Template → Full Injection。
CE 会自动生成一个注入脚本框架,类似这样:
- alloc(newmem, 2048)
- label(returnhere)
- label(originalcode)
- label(exit)
- newmem:
- // 在这里写你的自定义代码
- originalcode:
- // 这里是原始指令(CE 自动填充)
- sub [rbx+000000EC], eax // 原来的扣血代码
- exit:
- jmp returnhere
- // 注入点
- "Tutorial-x86_64.exe"+2A123:
- jmp newmem
- nop
- returnhere:
复制代码
让我们逐行解读:
:在内存中分配 2048 字节的空间
标签:你的自定义代码写在这里
:原始指令(由 CE 自动填充)
+:执行完后跳回游戏原来的代码
最后几行:把原始位置的代码替换成
第四步:修改脚本
现在把框架中的部分改掉。原来是:
- originalcode:
- sub [rbx+000000EC], eax // 血量 -= 伤害
复制代码
改成:
- originalcode:
- add [rbx+000000EC], 2 // 血量 += 2
复制代码 换成,(伤害值)换成(固定加 2)。
第五步:执行脚本
点击 Auto Assembler 窗口中的 Execute。
CE 会把你的代码写入内存,并在原始位置插入跳转指令。
第六步:验证
回到 Tutorial,点 Hit me。血量增加了 2。
反复点几次,血量持续增加。点 Next,Step 7 通关。
━━━━━━━━━━━━━━━━━━━━
Auto Assembler 语法速成
你需要知道的基本语法:
- // 分配内存
- alloc(名称, 大小)
- // 标签(用于跳转的"书签")
- label(名称)
- // 基本指令
- mov [地址], 值 // 赋值
- add [地址], 值 // 加法
- sub [地址], 值 // 减法
- mul // 乘法
- nop // 空操作
- jmp 标签 // 无条件跳转
- cmp 操作数1, 操作数2 // 比较
- je 标签 // 相等则跳转
- jne 标签 // 不等则跳转
- jg 标签 // 大于则跳转
- jl 标签 // 小于则跳转
- // 启用/禁用段(用于脚本的开关功能)
- [ENABLE]
- // 注入代码
- [DISABLE]
- // 恢复原始代码
复制代码
━━━━━━━━━━━━━━━━━━━━
脚本的 ENABLE 和 DISABLE
一个完整的 CE 脚本通常包含两个部分:
- [ENABLE]
- alloc(newmem, 2048)
- label(returnhere)
- newmem:
- add [rbx+EC], 2
- jmp returnhere
- "Tutorial-x86_64.exe"+2A123:
- jmp newmem
- nop
- returnhere:
- [DISABLE]
- dealloc(newmem)
- "Tutorial-x86_64.exe"+2A123:
- sub [rbx+000000EC], eax
复制代码 部分是启用脚本时执行的(注入你的代码),部分是禁用脚本时执行的(恢复原始代码)。
这样你就可以把脚本保存到 Cheat Table 中,随时打开和关闭。
━━━━━━━━━━━━━━━━━━━━
注入代码的注意事项
保护寄存器
如果你的代码修改了某些寄存器的值,可能会影响后续的游戏逻辑。安全的做法是在修改前保存、修改后恢复:
- newmem:
- push eax // 保存 eax
- mov eax, 2
- add [rbx+EC], eax // 血量 += 2
- pop eax // 恢复 eax
- jmp returnhere
复制代码 把寄存器的值压入栈中保存,再取出来恢复。
指令长度对齐
JMP 指令通常需要 5 字节(32位)或更多字节。如果被替换的原始指令不够 5 字节,CE 会自动用 NOP 填充剩余空间。
如果原始指令超过 5 字节,CE 的模板会自动处理好对齐问题。
━━━━━━━━━━━━━━━━━━━━
常见问题
Q:执行脚本后游戏崩溃了怎么办?
A:你的汇编代码写错了,或者破坏了寄存器/栈的平衡。重启游戏,检查代码,注意 push 和 pop 要配对。
Q:Auto Assembler 的模板自动生成的代码能直接用吗?
A:模板生成的是"原样执行原始指令"的框架,直接执行等于什么都没改。你需要在和之间插入你的自定义逻辑,或者修改的内容。
Q:代码注入只能用于数值修改吗?
A:远不止。你可以修改任何游戏逻辑:跳过条件判断、修改函数返回值、插入日志输出等。代码注入是所有高级修改的基础。
━━━━━━━━━━━━━━━━━━━━
小结
今天我们学会了代码注入——CE 最强大的武器之一:
代码注入的原理:JMP 跳板 + 自定义代码 + JMP 返回
使用 Auto Assembler 模板快速生成注入框架
修改游戏逻辑(从扣血变为加血)
ENABLE/DISABLE 机制实现脚本的开关功能
从"找数据改数据"到"找代码改代码"再到"写自己的代码注入游戏",你的 CE 能力已经完成了三级跳。
明天 Day 8,我们要挑战多级指针——当指针指向的不是数据而是另一个指针时,你需要像剥洋葱一样一层层剥开。
提前警告:明天的内容是公认的 CE 学习最大门槛。但别怕,搞懂了之后你会发现它的逻辑其实很简单。 |
|