|
CE 修改单机版杀戮尖塔,通过群组搜索找到了当前血量和最大血量,但是过一会游戏地址就会发生变化还需要重新搜索,太麻烦了。于是乎决定找一个一劳永逸的办法解决手懒的问题{:301_997:}。
开始攻略
**由于游戏的地址一直在变所以图片中有些地址可能对不上,理解思路即可。
1、游戏 CE 双双启动;
2、群组搜索当前血量和最大血量;
得到两个结果,一般下面的就是啦,找不到可以修改试试看看游戏内有没有效果来判断。
3、对这个地址右键选择 “找出是什么改写了这个地址”,然后去游戏里挨揍一下,就有了下面的结果。
接着点这条指令,然后点右面的详细信息。
指令里有rcx、rbx 我们看下面的值,重点看rbx=0x40,后面要考~
4、点击确定回到上个页面点击 显示反汇编程序
为了每次能精准定位到它可以截图问AI让他帮你生成特征码,然后还能贴心的帮你写一个自动汇编的脚本。
AI给了我这段特征码 48 3B 01 89 04 19 85 D2 0F 84 并将其生成了一段自动汇编脚本。
在CE主界面点击 查看内存 然后按Ctrl + A,将汇编脚本粘贴进去,然后点左上角文件 分配到当前的CT表即可添加到CE界面中。
点击CE主界面右面的手动添加地址 输入我们刚注册的全局符号FoundAddr确定即可
然后右键 反汇编此内存区域 发现根据特征码找到的FoundAddr在我们需要的汇编代码上方,我们要的是尾号7566那行。
所以我们直接+3 得到了想要的地址
在CE主界面中勾选自动汇编脚本 下面手动添加的地址就自动出来了。
5、通过找出指令访问的地址,发现这条指令不光修改血量,还有好多地方能用得到它,所以接下来怎样找呢?
记得上面的mov [rcx+rbx],eax,在游戏里被攻击血量被修改的时候我们找出了是谁改写了它,所以rbx=0x40正是这个偏移对应了修改血量。
所以我们只要找到rcx即可,但刚才我们说了,有好多地址在改写访问这段指令,所以需要判断,只能祭出AI大法。(实力不够AI来凑)
谨慎询问中*****
“mov [rcx+rbx], eax。帮我写一个 CE 自动汇编脚本,要求:判断 rbx 是否 = 40,如果 = 40,获取当前 rcx 的地址存为 my_rcx,我可以直接添加地址进行修改。如果不 = 40,则继续运行游戏不做修改拦截”
[ENABLE]
// 就近分配内存,确保64位下5字节跳转不超范围
alloc(newmem, 2048, FoundAddr)
label(return_here)
label(my_rcx)
// 【关键】注册为全局符号,CE地址列表才能识别my_rcx
registersymbol(my_rcx)
newmem:
pushfq // 保存标志寄存器,不破坏原程序状态
cmp rbx, 0x40 // 判断 rbx 是否等于十六进制 40(对应CE寄存器窗口显示的40)
// 若要判断十进制40,改为 cmp rbx, 40
jne @f // 不相等则跳过保存
mov [my_rcx], rcx // 相等时保存当前rcx到变量
@@:
popfq // 恢复标志寄存器
// ========== 被覆盖的原始指令 ==========
mov [rcx+rbx], eax // 原指令(3字节)
// 若jmp覆盖了后方有效指令,请按原顺序补到此处
// =====================================
jmp return_here // 跳回原程序
my_rcx:
dq 0 // 64位变量,存储rcx地址
// ===================== 注入点 =====================
FoundAddr+3:
jmp newmem
return_here: // 跳回位置 = 注入点 + 5字节(jmp指令长度)
// =================================================
[DISABLE]
// 恢复原始指令(3字节原指令 + 2字节nop,共5字节,和jmp长度一致)
FoundAddr+3:
mov [rcx+rbx], eax
nop
nop
// 注销全局符号
unregistersymbol(my_rcx)
dealloc(newmem)
6、添加为自动汇编脚本 再手动添加地址 my_rcx 勾选指针 填上40 点击确定。
7、把两个自动汇编脚本都勾选上,去游戏里试一下。
好消息 成功得到了血量。
坏消息 打怪就会变成怪的血量 人物被攻击就会变成人物的血量。
8、看来还得再加判断
左边是人物,右边是怪物
发现我选的那个地方人物为1(偶尔会有变化,不同角色可能也不同) ,怪物则为0。以此作为区分判断。
9、修改第二个汇编脚本,增加第二个判断
[ENABLE]
// 在注入点附近分配内存,避免64位程序跳转超范围
alloc(newmem, 2048, FoundAddr)
label(return_here)
label(my_rcx)
label(restore_all)
// 注册全局符号,CE地址列表才能正常识别my_rcx
registersymbol(my_rcx)
newmem:
pushfq // 保存标志寄存器,不破坏原程序状态
// 条件1:判断 rbx 是否等于十六进制 0x40
cmp rbx, 0x40
jne restore_all // 不满足则直接跳过,不保存
// 条件2:rcx+0x90 处的4字节值 == 十六进制0x01
cmp dword ptr [rcx+0x90], 0x1
jne restore_all // 不满足则直接跳过,不保存
mov [my_rcx], rcx
restore_all:
popfq // 恢复标志寄存器
// ========== 被覆盖的原始指令区 ==========
mov [rcx+rbx], eax // 原指令(3字节)
// 若jmp覆盖了后方有效指令,请按原顺序补在此处
// =======================================
jmp return_here // 跳回游戏原流程
my_rcx:
dq 0 // 64位变量,存储符合条件的rcx地址
// ===================== 注入点 =====================
FoundAddr+3:
jmp newmem // 5字节长跳转
return_here: // 跳回位置 = 注入点地址 + 5
// =================================================
[DISABLE]
// 禁用时恢复原始5字节机器码
FoundAddr+3:
mov [rcx+rbx], eax
nop
nop
unregistersymbol(my_rcx)
dealloc(newmem)
10、回到游戏中测试一下,嗯不错,这回打怪的时候数值不会变,自己血量变化的时候数值一直显示正确,达到了目的。
血量找到了后续可以添加 my_rcx + 48 是格挡 my_rcx + 1C 是金币。终于不用每次都搜索了~
后记
本次操作仅作记录,和一点点思路分享给兄弟们,本人菜到处处问AI毫无技术可言,可以利用AI整合成一个汇编脚本,但是操作到最后目的达到了,就不想再动了。。。
另外需要注意的是不同角色的特征码有可能不同,人物和怪物区分判断的地方也有可能不一样,操作的时候还需要各位自行去判断分析。还有就是游戏长时间没有操作的时候第一步特征码可能都搜不到,还得重进游戏才能再次搜索到,希望各位大佬们提点一下。 |