前言
又偷懶的好久,美滋滋。本來這次准備做一下CS1.6的修改,但是考慮到如果要修改CS,必然需要講到注入的方法,我們又還沒有講到注入,然后今天又發現動畫區有人做了一個CS1.6的視頻,得,我們還是繼續基礎班吧,哈,學好了基礎,我們再去玩玩1.6,可以做出更多有趣的功能。
之前的星際爭霸系列,是直接對exe進行修改,這樣的方式會更加簡單,將作弊植入了游戲中,但是同時也失去了開關的能力,我們無法控制作弊的開關狀態,因為他一直是開啟的。星際爭霸系列傳送門
如果想隨時開關,就像外掛一樣,那就需要使用注入了,就是我們今天要了解的內容。
這篇文章主要講三個部分:
- 基址獲取方式。
- 人造指針的制作。
- 簡單AA腳本注入。(第二第三其實寫在一起了,嘿嘿,湊點篇幅哈)
后續會專門有文章講解,怎么使用AA腳本制作修改器。
歡迎文明轉帖,請注明出處 丸子de爸爸。
所有技術只用於學習研究,請勿用於商用,請支持正版。
工具
項目開發中需要用到的工具:CE6.7(CheatEngine)
植物大戰僵屍游戲本體(不同版本可能出現不兼容,以后也會討論有兼容的解決辦法)
本次基礎概念
內存,一切皆內存,我們操作的全部都是內存。
所有地址相關的概念,都可以理解為坐標,用來給我們做標記的而已。
如果實在搞不明白,你想想指南針為啥指向北邊,為啥叫南北,只是定義,只是公認
模塊地址
簡單理解,就是exe運行起來,加載到內存中的時候,系統分配給exe的首地址。
也可以理解為,內存是一個櫃子,一共有40格,exe運行,系統把exe放到了第30格,然后模塊地址就是30。
基址
以陽光為例,由於內存是動態分配的,我們每一次搜索存放陽光的內存地址都會不一樣。
基址,就是指每一次分配我們都能通過偏移,來找到動態的地址,一般是由模塊地址+固定的偏移實現。
例:我知道陽光在內存中存放地址,是模塊地址+400的內存位置,所以陽光基址就一定是模塊地址+400。所以動態就變成了,30格的時候,30+400。在40格的時候,40+400了。
指針
指針其實就可以理解成外號,你的外號叫二狗子,別人先知道你的外號,然后熟悉了才可以根據外號找到你的真名。
更多的用處是引用,就像別人往往更願意叫你二狗子,而不願意叫你真名一樣。
例:一個指針叫做point,他指向內存的0xFF923200。那他就可以有兩個作用,一個就是直接使用指向的內存地址FF923200;另一個可以直接查到FF923200里的值。
什么叫做注入
寫出這個基礎概念的時候,我就發現自己被自己坑了。暫時簡單理解成,就像我們更改exe一樣,在適當的地方,更改程序的跳轉,使它執行我們需要的邏輯。
PS:有興趣的可以自己去查一查,這個要講我真的是講不來,太多要講了。
AA腳本是什么
AA腳本全稱:AutoAssemble腳本,自動匯編腳本。可以理解為一個預先編輯好的邏輯,在適當的時候使用軟件調用,就可以達到修改程序內存的作用。
功能實現
陽光基地址獲取
此處僅介紹兩種方法:
- 模塊地址偏移法。
- 人造指針動態獲取。
模塊地址偏移法
實現方案
由於每次運行程序,內存都會動態分配,所以陽光在內存中的地址也會變化,於是我們需要嘗試找到穩定的參照物。模塊地址便是我們的着手點。
所謂的模塊地址,就是exe加載到內存的時候所在的地址,他一般由進程名(模塊名) + 固定偏移組成
例: PlantsVsZombies.exe + 2EF1A
由於模塊地址是根據進程地址進行偏移,所以相對穩定(當然,目前沒有發現不穩定的情況,但是話不敢說滿),我們通過模塊地址指針進行偏移,就可以得到陽光的相對地址。
流程圖
由於設計到多重指針,比較復雜,下圖中的陽光地址用A1代替
A3如果不是,繼續向下尋找,直到找到模塊地址。第一次選擇改寫,是為了方便定位到第一個指針,不然訪問陽光的指針很多,很難定位
搜索陽光動態地址
打開游戲和CE,點擊CE中左上角小電腦選中游戲進程“PlantsVsZombies.exe”
可以看到目前的陽光數量是150,我們在CE中輸入150,按下首次搜索,如圖,會出現一大堆結果
回到游戲,種植一顆植物,陽光減少。
回到CE,將數值改為50,點擊再次搜索
結果變為了1個,雙擊列表中的結果,將結果添加到CE下方
雙擊數值數字那一欄,在彈出的框中改為500,確定
回到游戲,查看陽光數是不是變成了500,若沒有,請重復之前操作。
若游戲內陽光變為了500,則說明陽光地址查找成功,記錄地址,我這里是2DD89670
右鍵列表中的地址,選中“找出什么改寫了這個地址”
不要關閉此窗口,回到游戲,種一顆植物或者收集一個陽光,讓陽光發生變化
陽光變化后,回到CE,可以發現多出一條記錄(我這里是收集了一個陽光,怕不一致的可以照着來)
雙擊記錄,彈出窗口,記錄紅框位置的數據 指針2DD840F8, 偏移5578
勾選Hex,在搜索框中輸入上一步找到的指針,開啟新的搜索,我這是2DD840F8(每人都會不一樣)
又出現了一大堆結果,這時不要關閉當前CE,再另外打開一次CE,開啟一個新的CE程序,下文按先后順序代稱為CE1,CE2。
同時在植物大戰僵屍游戲中,選擇“菜單”-->“重新開始本局游戲”
此時你會發現,在CE1中,之前的陽光地址已經對不上了,因為陽光地址已經動態改變
切換到CE2,按照前面的方法,找到並記錄新游戲的陽光地址,我這里是2DFBEDD8,方法不重復演示了
找到后可以關閉CE2,重新切換回CE1
點擊手動添加地址,導入在CE2中記錄的新陽光地址,點擊確定
雙擊描述文字,可以對地址進行重命名
對新地址進行改寫跟蹤,按照前面的操作,找到新地址的指針為 2DFB9860
在搜索欄中, 輸入新的指針,點擊再次搜索,得到3個結果
我們可以看3個結果的地址,Windows中從004以后,才是用戶的程序,所以,我們要找的就是第三個024BAE98
雙擊添加到下面列表中
這一次右鍵,然后就要選擇訪問了
點完訪問是不是驚呆了,好多東西吧,沒事,現在不需要你弄懂,你只要選靠前的幾個mov中的其中一個雙擊
是不是看到了熟悉的東西,和之前類似,記錄下紅框內容,指針024BA630,偏移868
新建查詢,上一步的指針024BA630,在1000多個里面,發現有幾個綠色的,對了,這就是模塊基址了
分別查看4個地址的訪問,只有其中一個是一直在被訪問的,仍然是選擇最前的mov,打開后如圖
可以發現,我們已經很明確的找到了模塊基址 ,我這里為PlantsVsZombies.exe+355F28
終於到了最后一步,仍然點擊手動添加地址
按照之前我們找到的指針反過來寫,最下面寫模塊基址,然后第一個偏移量是之前找到的868,接下來是5578
可以看到在地址那欄已經顯示出了指針指向的地址,值為75,點擊確定
可以看到,我們的指針已經指向了目前陽光的地址
接下來可以重新開始本局,會發現仍然是能夠正確顯示陽光值,這里就不截圖了
刪除掉其他多余的項目,只留下陽光地址指針,便可以通過修改數值,達到修改陽光的目的了
總結
整體邏輯按照流程圖執行,中間之所以會選擇改寫地址,是因為多余地址很多,通過多次數據對比,來篩選出和陽光有關聯的指針。你如果願意一個個去試,只要耐心夠,也可以找到。最終的結果為:
通過當次反推,一層層拿到基址。再從基址往回偏移,拿到最后每一次動態的地址。
人造指針動態獲取
實現方案
我們在游戲第一次訪問陽光地址的時候,將陽光的地址紀錄下來,然后存到自己申請的內存地址。之后我們直接讀取自己的內存地址就行。
流程圖
使用人造指針流程就簡單很多,在訪問陽光的指令前執行腳本,將地址導出到人造指針給外部調用,難度主要是在自動匯編上。
注入地址搜索
先按照基礎方法找到本次游戲陽光地址
找到陽光地址之后,查看什么訪問了地址。選中mov那行,點擊反匯編程序
匯編語句這里不着重介紹,大家只要知道,add是兩數相加;mov是賦值語句,相當於mov a,b 就是 a = b
這里我們使用賦值語句,根據之前的學習,我們知道這句代碼意思是將陽光值,賦值給EAX寄存器
PS:匯編語言基礎大家可以稍微去找找資料,熟悉基礎指令,但是想制作修改器,它是必學的。
進入內存瀏覽器之后,ctrl+M能顯示模塊地址,可以看到很多的模塊地址
默認選中的那一行就是我們需要找的地址
自動匯編
選中在工具中,選擇自動匯編
打開自動匯編后,模板中先選擇“CT表框架代碼” ,再選擇“代碼注入”
AA腳本編輯
[ENABLE] //腳本啟動標志 alloc(newmem,32) //alloc為申明內存空間,alloc(分配的內存標簽名,申請字節數) label(returnhere) //申明標簽,用做跳轉 label(originalcode) label(exit) newmem: //這里讓你寫自己想要寫的代碼標簽 originalcode: //這里是原來的代碼標簽 mov eax,[edi+00005578] exit: //退出執行的標簽 jmp returnhere "PlantsVsZombies.exe"+9F2E5: //注入的代碼段地址,當前是模塊地址 jmp newmem //跳轉到newmem標簽 nop returnhere: [DISABLE] dealloc(newmem) //釋放內存空間 "PlantsVsZombies.exe"+9F2E5: mov eax,[edi+00005578]
選擇完之后會生成上面的腳本。
AA腳本的執行順序是,先找到注入代碼的地址段,開始執行,之后按照從上往下逐行執行
[ENABLE] //腳本啟動標志 alloc(newmem,32) //alloc為申明內存空間,alloc(分配的內存標簽名,申請字節數) label(returnhere) //申明標簽,用做跳轉 label(originalcode) label(exit) alloc(pointer,4) //***為自己的指針申明內存空間,因為就8位十六進制,所以4byte夠了 registersymbol(pointer) //***將point作為指針注冊到AA引擎中 newmem: //這里讓你寫自己想要寫的代碼標簽 originalcode: //這里是原來的代碼標簽 mov eax,[edi+00005578] //下面是修改的代碼 push eax //push用來eax存入棧里,完成業務之后,通過pop還原,保證原業務不出錯 lea eax,[edi+5578] //將[edi+5578]這個值的地址賦給eax,不明白可以去查匯編lea指令 mov [pointer],eax //讓point的值等於陽光的值的地址,外部調pointer的指針就會得到陽光值 pop eax //將eax值還原,不要引起邏輯異常 exit: //退出執行的標簽 jmp returnhere "PlantsVsZombies.exe"+9F2E5: //注入的代碼段地址,當前是模塊地址 jmp newmem //跳轉到newmem標簽 nop returnhere: [DISABLE] //腳本關閉標志 dealloc(newmem) //釋放內存空間 dealloc(pointer) //釋放指針空間 unregistersymbol(pointer) //****釋放指針 "PlantsVsZombies.exe"+9F2E5: mov eax,[edi+00005578]
按照上面腳本修改完成后,點擊自動匯編窗口的“文件”,“分配到當前的CT表即可”
指針調用
手動添加pointer指針,即可得到動態的陽光地址
總結
人造指針雖然涉及到自動匯編,但是在整體邏輯方面和工作量方面比基址方式要少得多,建議大家多多使用
注意造指針時,一定要選擇訪問地址,而不是改寫,不然就只有在改寫的時候會觸發指針賦值了
本篇總結
獲取基址只是開始修改的第一步,有了基址,我們便可以更改其中數值達到修改器的功能。
同時我們也可以通過注入的方式,修改程序代碼,就像外掛那樣,或者說,這已經是外掛了。
下章我們是繼續挖掘植物大戰僵屍新功能,還是直接使用易語言做輔助呢?留言吧...