使用 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)在內存中搜索特定的一串數據,以決定注入代碼的位置
- 人造指針:單獨找個地方,記錄變量所在的地址
數據存儲結構
數據在內存中的存儲結構:
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.exeVersion:Date : 2022-06-19Author : 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_ENDcmp word ptr [eax+18],'ol' // 內存字比較jne check_is_gold_ENDcmp byte ptr [eax+1A],'d' // 內存字節比較jne check_is_gold_ENDmov [man_pointer],ecx // 匹配成功,將指向此值的指針保存在申請的內存中(制作人造指針) check_is_gold_END:// 判斷此值的類型是否為生命(lives) check_is_live:cmp dword ptr [eax+10],'live'jne check_is_live_ENDcmp byte ptr [eax+14],'s'jne check_is_gold_ENDmov [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_ENDcmp dword ptr [eax+14],'l_st'jne check_is_star_ENDcmp word ptr [eax+18],'ar'jne check_is_star_ENDcmp byte ptr [eax+1A],'s'jne check_is_star_ENDmov [man_pointer+10],ecx check_is_star_END:// 恢復臨時使用的寄存器的值 restore_reg:pop eaxpopfd // 還原所有標志位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+1BDAlua51.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 使用界面:
本文由Tsanfer’s Blog 發布!
總結
以上是生活随笔為你收集整理的使用 Cheat Engine 修改 Kingdom Rush 中的金钱、生命、星的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内存带宽性能测试工具
- 下一篇: 网店营销忌讳效应:要知道别人不喜欢什么