一般情況下,為了應付游戲的動態內存地址,我們用基址的方式來讀取內存,不過前提是可以知道基址。有的游戲,基址是很難分析到的,而且很多游戲加了隱藏和變換,搞的分析起來特別復雜。這個時候,借助Seraph,我們可以用另一種方式——搜索內存。
雖然找不出基址,但是我們可以很輕松的找到一些我們想要的數據的直接地址。比如我們在一次游戲的運行里,可以用CE找到血的地址是H900010, 血最大值的地址是H900014,MP地址H900020,最大MPH900024。
雖然下一次游戲運行時,這些地址都會變,但是我們知道,這些地址互相間的相對地址偏移是不變的。也就是說最大血地址=血地址+4,MP地址=血地址+H10
這樣我們就可以搜索了。舉個例子,我們知道我們的血/最大血/MP/最大MP分別是8000/8000/12000/12000。那么在腳本里,告訴Seraph的內存搜索引擎,我們要搜索一個地址,它的值是8000,這個地址+4的值也是8000,這個地址+H10和+H14的值是12000。這樣的地址,一般在游戲里只有一個。
怎么搜索呢?
復制代碼 代碼如下:
ClearSearchMemoryTable()
AddSearchMemoryItem(H900010, 2, 8000)
AddSearchMemoryItem(H900014, 2, 8000)
AddSearchMemoryItem(H900020, 2, 12000)
AddSearchMemoryItem(H900024, 2, 12000)
if SearchMemory(H000000, Address) then
Print("找到地址:"Address)
end if
注意,以上代碼里,我們調用AddSearchMemoryItem函數來設置一些我們要搜索的條件。
第一個參數是每個值的地址。不用擔心這個地址在下一次游戲運行時不正確,Seraph搜索只關心所有添加的搜索項之間的“相對地址”。
第二個參數是指定類型,2代表四字節整型。我們同樣可以添加雙字節,浮點數,以及字符串等不同類型。詳見幫助手冊。
第三個參數就是這個搜索項的值。你必須填入這個數據的當前值,如果填錯了,就搜不到了。(關于怎么在腳本里指定當前的用于搜索的值,我們之后講)
注意,第一行的ClearSearchMemoryTable()是用于清除上一次添加的搜索項。重新開始一次搜索前我們都要調一上這個函數。
添加完了這4個搜索項以后,我們用SearchMemory開始搜索。第一個參數表示搜索的開始值,我們一般都可以用H000000。第二個參數值用于返回搜索到的結果。
搜到的結果就是第一個搜索項的地址,也就是當前血的地址。我們可以保存這個地址,用ReadMemory隨時去讀數據。
那么,整體的流程應該是:
1. 在參數設置里,我們添加一些參數,用于填入搜索的數據。告訴用戶在腳本開始前,先設置這些數據。比如,填入自己的血,MP,并在紅藍滿的時候開始腳本。
2. 在腳本一開始,用GetConfigNumber等函數取出設置的值,用以上代碼搜索內存,把得到的數據保存下來
3. 在腳本運行中,用保存下的地址,加上各種我們已經知道的偏移量,隨時讀取各項數據的值。
小技巧:
怎樣添加搜索項才可以最方便準確的搜索到我想要的那個唯一的內存地址?
當然是與角色越相關越好的。比如角色的各項屬性值。使用更多的搜索項可以有效的防止搜索的不準確(即搜到不止一個地址),但是也會帶來每次啟動腳本時的麻煩,因為我們啟動時都要設置一下搜索值。建議用一些不經常變的值,比如,等級,攻擊值等,只有升了級才會變。而血值是經常變的。
同時,根據我們的經驗,角色名字是很好的一個搜索項。如果我們可以分析到角色名字的地址,加在搜索項里(字串型),一般就可以很準確的搜索到結果。
一般的游戲角色名是UTF8形式的。我們可能要先將角色名用GBToUTF8函數轉換成UTF8編碼的字串,再用AddSearchMemoryItem添加。
如果有時候我們添加的數項不夠,或者我們在調試自己腳本的時候,會搜索到不同的內存地址,我們想讓腳本全部輸出,怎么辦?
復制內容到剪貼板
代碼:
AddSearchMemoryItem(...)
AddSearchMemoryItem(...)
...
Address=0
while SearchMemory(Address+1, Address)
Print("找到地址:"Address)
wend
原理就是從0開始,每搜索到一個地址,先輸出,然后從這個地址+1繼續往下搜,一直到搜不到為止。