創作內容

4 GP

Cheat Engine 教學略翻和碎碎念

作者:likwueron│2011-09-02 00:14:53│贊助:8│人氣:10749
Cheat Engine 初次開啓它會跟你推薦教學程式(toturial),何樂而不為呢?點啦點啦!

我會稍微翻譯它在說什麼,不過我還是建議你看看原文。(因為保證翻得不完美)
一開始在說廢話,我就不翻了,下一步。
不過這邊有個密碼欄,可以讓你讀取進度xd。

Step 2:
你看到此視窗下面有一排字:Health: xxx
每當你點 'Hit me' 時,它都會減少。

通關條件是讓它變成 1000。

找出讓值有很多方法,不過最簡單的是使用確切值(Exact Value)
首先,確定 值類型(Value Type)為2 bytes 或4 bytes,1 byte 也是可以,但是當你找出位址(address),想修改時會碰上麻煩。
8 bytes 也許能,如果該 bytes 後的位址為0,但我可不會冒險。
單精數(single)倍精數(double)和其它的類型在這裡是沒用的,因為它們使用不同的方法存儲值。

接著把你看到的 Health 的值填入 Value 文字輸入框,然後點 '首次掃描(First Scan)'
過一陣子(如果你的電腦超慢的話),結果會顯示於左邊的清單。

如果你發現有多個位址,且你不是很確定的話,點 'Hit me',然後將新出現的值填入 Value 文字輸入框,並且點 '再次掃描(Next Scan)',
重覆上述動作直到你找到為止。(當然也包含只剩一個結果時...)

現在,雙擊左方清單中的位址。這會使該位址另外出現在下方的清單中,且顯示目前的值。
雙擊目前的值(或點選後按下 Enter 鍵),將值改為 1000。

如果一切順利,你應該就能點下一步(Next)了。
而如果中間有問題的話,點 '新的掃描(New Scan)' 然後重覆上述動作。

補充兼廢話:
我一直在想有沒有新的方法來解釋電腦儲存數字的方法,不過顯然我想不到。
電腦是以二進位來看待世界的,也就是0和1。雖然我們也能用 X 和 Y 或其它對立關係來表示,只是用數字比較方便。
在這二進制的世界中,最小的單位我們稱為 位元(bit),它只能表示1或0。
可想而知,如果我們有兩個位元,我們就能表示 0, 1, 2, 3(00, 01, 10, 11) 四種狀況,以此類推。
而當我們把八個 bit 合在一起時,我們稱之為 位元組(byte),它能表示256種狀況。
你可以想像,如果不考慮負數,一個 byte 能表示從0到255之間的任一正整數。
一個 byte 大多數情況下是不夠的,所以我們就有 2 bytes, 4 bytes, 8 bytes。
在早期記憶體有限的情形下,程式一般是用 2 bytes 來處理整數,不過那時代已經很遙遠了,現在的整數都是用 4 bytes 來處理。
(當年我用世紀帝國二的編輯器,讓兵的血一直增加,似乎到數萬之後它就自動掛了,看來其生命值是用2 bytes 儲存的?)
那負數呢?
我們先假設有個 4 bits 的記憶體,它的內容是 0101 ,也就是 5。
我們知道 5 + (-5) = 0 ,而得 0101 + 1011 = 0000,所以 1011 表示 -5。
正規的教科書會先講這叫二補數,加負號為原數所有位元反轉(1變0、0變1)後加1,而這個聰明的方法也使得某正數和其負數相加為0。

第二個重點是位址(address)
就好像郵差需要你家住址(address)才能把信交給你,電腦(精確來說是裡面一個叫 CPU 的東東)也要知道位址才能處理數字。
(你知道的,磚家向來喜歡用奇怪的名詞來愚弄大眾,但其實位址根本沒什麼了不起的,不講住址是基於「磚夜」因素)
目前各位使用的個人電腦(PC),每一個記憶體「小屋」都能容納1 byte的資料。
(不過每次讀取不一定只讀1 byte)
而 CPU 「郵差」已知的「門牌號碼」,和其架構有關,也就是常聽到的 32-bit 和 64-bit。
32-bit CPU 知道的門牌最多有 2^32 個,約莫 4 * 10^9 個,如果再加上每戶能容納 1 byte 的話,我們可知 32-bit CPU 能使用約4 * 10^9 bytes 的記憶體,也就是 4GB。
(因為二進制要轉十進制有點麻煩,所以我就省略了一些數字,不過記憶體是沒縮水的,1GB = 1024MB,但硬碟就不同了...)

Step 3:
在先前的測試中,我們知道初值所以我們能用 exact value,但是現在我們有個初值不明的狀態列(status bar)
我們唯一知道的是,它的值在0到500之間。每次你點 'hit me' 你會損失一些生命。
而每次損失的量都會顯示在狀態列上方。

這同時也有數種方法能找出值,像減少指定值(decreased value by...) 掃描,不過我還是用最簡單的方法:初值不明值(Unknown initial value)被減少的值(decreased value)
選擇 '初值不明值(Unknown initial value)',後點首次掃描(First scan),然後等它處理完。

之後,點 'hit me'。你會失去一些生命值。(失去的部份會顯示一段時間後消失,不過你不需要它們)
現在,選 '被減少的值(Decreased Value)',接著點 '再次掃描(Next Scan)'。
掃描結束後,重覆上述動作直到你找到為止。

因為我們知道值是介於0到500,所以只要將符合者加入清單就行了。
現在將值改為5000,好迎向下一關。

補充兼廢話:
如果你在上一關沒問題的話,這關也是小菜一碟。
教學所用的方法,能對付各種數值不明的情況。
不過,像這種你大概知道它的值為多少的情況,我會用 介於(Value between...)
而有顯示減少量,我會用 減少指定值(decreased value by...)

Step 4:
在前面的教學中,我們掃描 bytes,但有些遊戲會把資訊存儲在所謂的 '浮點數(floating point)'型式
(這也許是避免記憶體掃描器太容易找出位址)
所謂浮點數,就是小數。 (5.12和11321.1等之類的)

下面你會看到你的生命(health)彈藥量(ammo)。它們皆以浮點數的型式儲存,不過呢,生命是使用 float 類型而彈藥是使用 double 類型。
點 hit me 來減少一些生命,點 shoot 每次減少彈藥 0.5 發。

你需要將兩個值都改為5000以上才能進入下一關。

提示:建議在掃描 double 類型時關掉 "快速掃描(Fast Scan)"

補充兼廢話:

要了解浮點數之前先了解一下何為定點數(fixed point)
如果我們有一記憶體內容如右 10001001100,定點數會決定一個位置作為小數點,像是第四和第五個位置之間。
則我們得到 1000100.1100 ,十進制為 68.75 。
我想你已看出這種方式有點浪費空間,所以我們有浮點數。
簡單來說,浮點數是科學記號的二進制版,它分為三個部份:正負號, 指數, 尾數,關於其詳細規格可參見 Wikipedia

Step 5:
有時,數值的位置會因為重開遊戲而有所變化,甚至是遊戲執行中的時候。
在這情形下,你有兩種方法使表格照舊有用。
在此我向你介紹如何使用代碼尋找器(Code Finder)功能。

你每次開啓教學程式時,這邊的數值都會存在不同的位址,所以位址清單中的普通存取項目(entry)是沒有用的。
首先,用之前學到的方法找出該值所在的位址。
找到後,右鍵點擊它,點選 "找出何者寫入該位址(Find out what writes to this address)", 一個空白清單視窗就會彈出。
接著,點擊教學中的 Change value 按鈕,然後回頭看看 Cheat Engine。如果沒有錯的話,你會看到一段組合碼和位址出現在清單中。
點選並選擇替換(Replace)選項,將它換成什麼都不做。這同時也會將組合碼的位址記在代碼清單(code list)中,你可以在進階選項(advanced options)中找到它。(如果你選擇儲存表格的話)

點擊停止(stop),這樣遊戲就會再次正常執行,然後點關閉(close)關掉視窗。
現在,點 Change value,沒意外的話你就能點下一步(Next)了。

註:當你以夠快的速度凍結位址時,Next 按鈕也許就能使用。

補充兼廢話:
entry 我不太會翻,希望各位都能了解就是了...

先不要管那奇怪的組合碼是什麼意思,我想要說的是,當你點下 Change Value 按鈕時,程式會執行到該處,而剛剛好那行奇怪的程式碼會使得該值改變。
那我們怎麼確定使值改變的程式碼每次都在同一個地方?
其實我沒真正讀過這方面的資料,雖然我大概能猜得出來為什麼,不過還是不要唬爛太多好了。

哦對了,儲存表格的按鈕就是 Cheat Engine 主視窗的儲存按鈕。
懶惰的話就存在預設資料夾中就好了,這樣每次開啓和檔名同名的程式時,它都會問你要不要載入該表格。
如果Advanced Options沒有出現的話,你可以在主視窗的左下角找到一個 Advanced Options 按鈕,就是它了。
對清單上的項目右鍵->找出哪個位址被此代碼寫入(Find out what address this code write to),之後只要值改變,除錯器就會找到它的位址。

Step 6:
在前一步中,我解釋如何使用代碼尋找器來處理會被改變的位置。
但單獨使用的話是很難找到你想改變之值的位址,所以,我們有指標(pointer)

你會在下面找到兩個鈕。一個改變它的值,另一個則是同時改變值和其位置。
在這個階段中,你無需了解組譯器,但了解它仍對你有許多幫助。

首先找出該值,找到後使用找出何者存取此位址(Find out what accesses this address)
再按一次 Change value,清單中會出現一些項目。雙擊其中一個項目(或點選後點更多資訊(More information)),這時,一個新視窗會出現,詳細的告訴你該行指令(instruction)執行時發生了什麼事情。
如果該指令沒有任何東西出現在方括號[]之間,那就用清單中其它的項目;如果有的話,它會說哪個指標是你要的。
記下方括號之間所指的值(是其代表的16進制值),然後回到主視窗,以 4 byte 16進制(hex)的方式掃描該值。
掃完後,你可能會得到多個結果,我們要的通常是位址最小的那個。

現在點手動加入位址(Add Address Manually),並將其中的指標(Pointer)方框打勾。
你會看到視窗多出了指標位址欄(Address of pointer)偏移欄(Offset),將你剛剛掃描出的位址填入指標的位址,而如果先前的方括號中為算式,如 [esi+12],請將其後的數字填入偏移欄中,如果沒有,留空就行。

複雜指令範例:
[EAX*2+EDX+00000310] eax=4C 且 edx=00801234.
在此, EDX 應是指標的值,而 EAX*2+00000310 為偏移,所以你在偏移的部份該填入 2*4C+00000310=3A8. (請用小算盤的工程師型計算16進制)

回到我們的教學進度,點 OK 後位址就會加到清單中。如果一切無誤的話,你會看到位址欄寫 P->xxxxxxxx
xxxxxxx 應是你找到之值的位址。
現在,用指標改變其值為5000並凍結它,接著點 Change pointer。
過了幾秒,Next 應該就能按下去了。

補充:
你亦可使用指標掃描器(pointer scanner)找出指向該位址的指標

補充兼廢話:
指標說簡單很簡單,說難也可以難如上青天,不過我目前多半都是碰上簡單的部份,所以也只能簡單的講。
寄信的時候要把對方的住址寫上,不然郵差會退信;想存取某個值的時候也要說位址在哪,不然 CPU 會發火(有時就是程式整個當掉)。
而這個叫指標(pointer)的東西就是專門來儲存門牌號碼。

找出何者存取此位址(Find out what accesses this address),在這個案例中會找到四行指令。
別太緊張,往上看剛剛的概念,好了,你回想起指標是幹麻的了。
在之前我們已經找到你想改的值,而剛好你也知道它的位址,所以,如果額外資訊(extra info)視窗告訴你的值和位址是相同的,那就是它了。
如果有出現偏移,就把偏移納入考量。

後面組合語言的部份我就算了...我跟它不熟...
你可以參考這個討論串

Step 7:
代碼注射(Code injection)是一個將一小段代碼插入目的程序,並引導程式執行它的技術。

這次你有一個生命值,和一個每點一次就會減少1點生命的按鈕。
你的目標就是讓原本點一次就少1點血的按鈕變成每點一次就加2點血。

找出該址的位址並找到是誰在對它寫入,接著,點 顯示反組譯器(Show disassembler),並按 Ctrl+A 開啓自動組譯器(auto assembler) 視窗。
模版(template)->代碼注射(code injection),它會問你要注射到哪個位址,一般來說會自動補捉,如果沒有就輸入該指令的位址。
這會產生一段基本的自動組譯注射框架(basic auto assembler injection framework)好讓你寫入你的代碼。

注意 alloc 那行,這會配置出一塊記憶體空洞(memory cave)給你的代碼使用。
同時注意 newmem:, original code:, 和文字 "將你的代碼寫在這(Place your code here)",如同你所想的一樣,在那邊寫下生命加2的指令。
向你介紹個有用的指令,"ADD 指令",範例如下:
"ADD [00901234],9" 表示將位址 00901234 的值加 9
"ADD [ESP+4],9" 表示將位址 ESP+4 的值加 9
在這個例子中,你要使用 original code 中的位址給 ADD 指令。

註:
建議刪去那個在 original code 區會減少生命的指令,不然你得將生命加3才能使結果為加2(因為 original code 本身會使之減1)。

註2:
In some games the original code can exist out of multiple instructions, and sometimes, not always, it might happen
that a code at another place jumps into your jump instruction end will then cause unknown behavior.
If that happens, you should usually look near that instruction and see the jumps and fix it, or perhaps even choose to use a different address to do the code injection from.
As long as you're able to figure out the address to change from inside your injected code.

補充兼廢話:
那有關 memory cave 的部份我不會翻,啊,雖然不了解它對我們的計畫是沒影響的。
註2 的文法我不熟...不過我留原文啦,因為有些時候可能會發生些奇怪的事。

啊,好啦,我們正式進入邪惡的組合語言世界,請問你的感覺如何?
我在 Wikipedia 中找到 x86 指令集的介紹,如果你想知道那些指令大概是在幹麻的話。
在 Step 6 的廢話區,那個討論串也可以看一看。

Step 8:
這次會解釋什麼叫多層指標(multi-level pointer)
在第六步你有一個單層指標,且首次找到的位址正是基底位址(base address)
這次則是4層指標,它是指向生命值的指標的指標的指標的指標(a pointer to a pointer to a pointer to a pointer to the health)

基本上你要做得事情和 Step 6一樣,找出值,找出可能指向它的指標和其偏移,然後記下來。
但是這次你找出的指標亦被另一個指標所指向,你所要做的是用同樣的方法找出指標的指標,直到你找到基底位址為止。
(通常基底位址是靜態位址,它會是綠色的)

如果你認為你找出指標路徑的話(pointer path),點 Change pointer。
指標和值會改變,你有3秒的時間凍結位址的值至5000。

補充: 你亦可使用自動組譯器腳本或指標掃描器決解這問題。

補充2: 在某些情況下會建義更改 CE 的代碼尋找器設定至 Access violations ,像是碰上了如 mov eax, [eax] 這樣的指令,因為除錯暫存器只會在它改變"後"顯示它的狀況,使得指標很難找出來。

補充3: 如果你讀到這邊,你也許會注意到當查看組譯器指令時,指標是被同樣代碼區塊讀取並完成的(filled out)。
(同樣的路徑,如果你了解組譯器的話,就查到該路徑的源頭)
雖然不是總是如此,只是當你在除錯時碰上麻煩時,這是個用用的技巧。

補充兼廢話:
中間有一句我嚴重曲解原文: But in this case the address you'll find will also be a pointer. -> 但是這次你找出的指標亦被另一個指標所指向。
主要是因為我想不通為什麼他要這麼寫,所以我用我的知識來寫。

你的眼睛花掉屬於正常現象,因為多層指標開始有點難度了。
C 語言我會這麼寫:
int health = 100;
int *p_health = &health;
int **pp_health = &p_health;
int ***p3_health = &pp_health;
int ****p4_health = &p3_health;

變數 health ,是為整數,其值 100
變數 p_health,是為單層指標,其值為 health 的位址
變數 pp_health,是為雙層指標,其值為 p_health 的位址
變數 p3_health,是為三層指標,其值為 pp_health 的位址
變數 p4_health,是為四層指標,其值為 p3_health 的位址

* 和 & 如果在變數左邊會有特殊功能,也許你也猜到了。
* 會取得該指標的值,而 & 會取得該變數的位址。

不過上面的寫法是不能改變生命值的位址的,如果要改的話,需要使用動態記憶體配置。
只是 C 太久沒用了,我都忘了 malloc() 要怎麼用。

有人說指標是程式設計中最璀璨的星星,不過在你搞定它之前,它只會令你眼冒金星。
(真的有人為指標寫了一本書,也許質量不怎麼樣,不過內容稱得上是殺人利器)
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=1408726
Some rights reserved. 姓名標示-非商業性 2.5 台灣

相關創作

同標籤作品搜尋:cheat engine

留言共 2 篇留言

天使韋弗
太感謝你了~
是否能問幾個問題

08-08 15:05

kikiatw
我覺得你這段寫錯了
int health = 100;
int *p_health = &health;
int **pp_health = &p_health;
int ***p3_health = &pp_health;
int ****p4_health = &p3_health;

應該改成下面這一段
*p是一維指標
**p是二維指標
***p是三維指標
其實每個位址只需要一個指標就可以了, 就像我只需要一個正妹即可
int health = 100;
int *p_health = &health;
int *pp_health = &p_health;
int *p3_health = &pp_health;
int *p4_health = &p3_health;

09-09 21:47

likwueron
可能我真的忘了,因為純C現在不太碰09-09 21:55
我要留言提醒:您尚未登入,請先登入再留言

4喜歡★iqandadie 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:Cheat Engine... 後一篇:我好像猜錯了?...

追蹤私訊

作品資料夾

Arosi路人
嘻嘻嘻今天也更練習了,IG晚點更~看更多我要大聲說昨天18:51


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】