使用 Cheat Engine 修改 Kingdom Rush 中的金钱、生命、星

最新博客链接

最近想学习一下 CE,刚好看见游戏库里装了 Kingdom Rush 就拿它来研究吧。这里写的东西,需要一些 Cheat Engine 的基础,可以看看教程。

这里主要是看写的注释,来理解脚本。(如果什么都不想看,可以直接复制粘贴 CE 自动汇编(AA)脚本)

我学习的链接:

你能学会的 Cheat Engine 零基础入门教程

Cheat Engine 基础教程 CE Tutorial | Ganlv's Blog

CE 教学实例应用-由浅入深学习游戏修改 [全十课]

参考链接:

Cheat Engine 官方 WIKI

x86 汇编指令列表

技术理解

我对一些用到的技术的简单理解:

  • 代码注入:在程序运行时,将自己写的代码,替换掉原有的代码
  • AOB:(Array Of Byte)在内存中搜索特定的一串数据,以决定注入代码的位置
  • 人造指针:单独找个地方,记录变量所在的地址

数据存储结构

数据在内存中的存储结构:

cb60f682359e51edf823f5fa707e1bb1.png

Cheat Engine 相关汇编知识

此脚本用到的 CE 汇编指令

x86 汇编指令列表

命令例子 功能
mov ebx,0000FFFF Move,寄存器直接赋值
mov ebx,eax Move,将右边直接给左边
mov ebx,[eax] Move,将右边所指的值给左边。[ ]代表括号内的是指针,操作时,操作其指向的内存值
cmp ebx,eax Compare,比较两寄存器值,若相等则 ZF 位 置 1(左减右)
je <label> Jump if Equal, ZF = 1 时跳转,可跳转至标记段代码
jne <label> Jump if Not Equal, ZF = 0 时跳转,可跳转至标记段代码
jmp <label> Jump

此脚本用到的 CE 自动汇编函数:(Auto Assembler)

Cheat Engine 官方 WIKI

函数 参数 作用
alloc alloc(SymbolName, Size, AllocateNearThisAddress OPTIONAL) Allocates a memory block of Size bytes and defines the SymbolName in the script, pointing to the beginning of the allocated memory block.
dealloc dealloc(SymbolName) Deallocates a block of memory allocated with alloc.
label label(LabelName) Enables the word 'LabelName' to be used as a symbol.
aobScanModule aobScanModule(SymbolName, ModuleName, AOBString) Scans the memory used by the module ModuleName for a specific byte pattern defined by AOBString and sets the resulting address to the symbol SymbolName.
registerSymbol registerSymbol(SymbolName) Adds a symbol to the user-defined symbol list so cheat tables and the memory browser can use that name instead of an address.
unregisterSymbol unregisterSymbol(SymbolName) Removes a symbol from the user-defined symbol list. No error will occur if the symbol doesn't exist.

此脚本用到的 CE 汇编语言数据类型

类型 占用空间
Bit(整型) 1 位
Byte(整型) 8 位(字节)
2 byte(整型) WORD(字)
4 Bytes(整型) DWORD(双字)
8 Bytes(整型) QWORD(四字)
Float(单浮点) DWORD(双字)
Double(双浮点) QWORD(四字)
String(字符串) 任意长度
Array of bytes(AOB) 任意长度

CE 常用寄存器

The x86 architecture has 8 General-Purpose Registers (GPR)
x86 架构有 8 个通用寄存器(32 位系统)

"E" (for "extended"), 32 bits.

General-Purpose Registers:EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI

Cheat Engine 汇编代码

学过 CE 的,通过注释,应该能看懂

{ Game   : Kingdom Rush.exe
  Version:
  Date   : 2022-06-19
  Author : Tsanfer

  更改金钱、生命、星
  (使用 AOB 和人造指针)
}

[ENABLE]

aobscanmodule(INJECT,lua51.dll,8B 29 8B 49 04 89 2C C2) // AOB 匹配入口
alloc(newmem,1024,INJECT) // 分配 1024 字节个内存,用于代码注入
alloc(man_pointer,24) // 动态分配内存,用于存放3个人造指针

// 注册全局符号
registersymbol(INJECT)
registersymbol(man_pointer) // 人造指针

// 声明标号
label(original_code)
label(return)
label(restore_reg)
label(check_is_gold)
label(check_is_gold_END)
label(check_is_live)
label(check_is_live_END)
label(check_is_star)
label(check_is_star_END)

// 数据存储结构:
// 偏移   数据                 变量类型
// 0      具体值               Double
// 8      指向值所属的公共结构 指针
// └─> 0
//     10 此公共结构的名称     字符串

// 程序执行顺序:(汇编代码如没有跳转,默认从上往下执行)
// INJECT -> newmem -> check_is_gold -> check_is_live
// -> check_is_star -> reset_reg -> original_code -> return

// 注入代码段
newmem:
  pushfd // 保存所有标志位
  push eax // eax 压栈保存,为后续操作腾出一个寄存器
  mov eax,[ecx+08] // 将当前值所属的公共类型所在的地址,给 eax

// 判断此值的类型是否为金钱(player_gold)
check_is_gold:
  cmp dword ptr [eax+10],'play' // 内存双字比较
  jne check_is_gold_END // 如不匹配,则停止后续比较,跳到此比较的结尾
  cmp dword ptr [eax+14],'er_g'
  jne check_is_gold_END
  cmp word ptr [eax+18],'ol' // 内存字比较
  jne check_is_gold_END
  cmp byte ptr [eax+1A],'d' // 内存字节比较
  jne check_is_gold_END
  mov [man_pointer],ecx // 匹配成功,将指向此值的指针保存在申请的内存中(制作人造指针)
check_is_gold_END:

// 判断此值的类型是否为生命(lives)
check_is_live:
  cmp dword ptr [eax+10],'live'
  jne check_is_live_END
  cmp byte ptr [eax+14],'s'
  jne check_is_gold_END
  mov [man_pointer+8],ecx // 将指针保存在第二个内存位置
  // (64位系统的指针大小为 64 bit,每个内存地址大小为 8bit,则需要平移8个内存地址,8x8=64)
check_is_live_END:

// 判断此值的类型是否为升级用的星(total_stars)
check_is_star:
  cmp dword ptr [eax+10],'tota'
  jne check_is_star_END
  cmp dword ptr [eax+14],'l_st'
  jne check_is_star_END
  cmp word ptr [eax+18],'ar'
  jne check_is_star_END
  cmp byte ptr [eax+1A],'s'
  jne check_is_star_END
  mov [man_pointer+10],ecx
check_is_star_END:

// 恢复临时使用的寄存器的值
restore_reg:
  pop eax
  popfd  // 还原所有标志位
  jmp original_code

// 原始代码
original_code:
  mov ebp,[ecx]
  mov ecx,[ecx+04]
  jmp return // 跳到返回

// 程序入口
INJECT:
  jmp newmem
return: // 返回

[DISABLE]
// 还原代码
INJECT:
  db 8B 29 8B 49 04

// 注销全局符号
unregistersymbol(INJECT)
unregistersymbol(man_pointer)
// 释放内存
dealloc(newmem)
dealloc(man_pointer)

{
// ORIGINAL CODE - INJECTION POINT: lua51.dll+1BDA

lua51.dll+1BBC: 23 48 08     - and ecx,[eax+08]
lua51.dll+1BBF: 6B C9 18     - imul ecx,ecx,18
lua51.dll+1BC2: 03 4D 14     - add ecx,[ebp+14]
lua51.dll+1BC5: 83 79 0C FB  - cmp dword ptr [ecx+0C],-05
lua51.dll+1BC9: 75 3A        - jne lua51.dll+1C05
lua51.dll+1BCB: 39 41 08     - cmp [ecx+08],eax
lua51.dll+1BCE: 75 35        - jne lua51.dll+1C05
lua51.dll+1BD0: 83 79 04 FF  - cmp dword ptr [ecx+04],-01
lua51.dll+1BD4: 74 36        - je lua51.dll+1C0C
lua51.dll+1BD6: 0F B6 46 FD  - movzx eax,byte ptr [esi-03]
// ---------- INJECTING HERE ----------
lua51.dll+1BDA: 8B 29        - mov ebp,[ecx]
lua51.dll+1BDC: 8B 49 04     - mov ecx,[ecx+04]
// ---------- DONE INJECTING  ----------
lua51.dll+1BDF: 89 2C C2     - mov [edx+eax*8],ebp
lua51.dll+1BE2: 89 4C C2 04  - mov [edx+eax*8+04],ecx
lua51.dll+1BE6: 8B 06        - mov eax,[esi]
lua51.dll+1BE8: 0F B6 CC     - movzx ecx,ah
lua51.dll+1BEB: 0F B6 E8     - movzx ebp,al
lua51.dll+1BEE: 83 C6 04     - add esi,04
lua51.dll+1BF1: C1 E8 10     - shr eax,10
lua51.dll+1BF4: FF 24 AB     - jmp dword ptr [ebx+ebp*4]
lua51.dll+1BF7: 0F B6 46 FD  - movzx eax,byte ptr [esi-03]
}

然后再手动添加 3 个人造指针的地址(man_pointer 和 man_pointer+8 和 man_pointer+10),就行了

Cheat Engine 使用界面

8928bbec97c970682e290b4a00a20e53.png

本文由Tsanfer's Blog 发布!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容