------------------------------
內容表
------------------------------
I. 介紹
II. 暫存器
II.a 32位暫存器
II.b 16位暫存器
III. 指令
III.a JMP
III.b MOV
III.c Push/Pop + The Stack
III.d alloc/label/registersymbol
III.e Call and Ret
III.f 其他
IV. Array of Bytes
V. 結尾
VI. 人員名單/致謝詞
額外內容: 寫一個腳本
------------------------------
I. 介紹
------------------------------
'喲,我猜你在讀這個是因為下面兩件事中的一個。
1) 你正在試圖學習自動彙編 (我不會叫你菜鳥,因為每個人都是從哪裡開始的,對吧 =) )
or
2) 你想測試你的自動彙編知識 (作為擴展)。
那么,如果你是前者,那就慢慢的體會好每個部分,並且在繼續進行前確認自己已經明白了這章。
內容表
------------------------------
I. 介紹
II. 暫存器
II.a 32位暫存器
II.b 16位暫存器
III. 指令
III.a JMP
III.b MOV
III.c Push/Pop + The Stack
III.d alloc/label/registersymbol
III.e Call and Ret
III.f 其他
IV. Array of Bytes
V. 結尾
VI. 人員名單/致謝詞
額外內容: 寫一個腳本
------------------------------
I. 介紹
------------------------------
'喲,我猜你在讀這個是因為下面兩件事中的一個。
1) 你正在試圖學習自動彙編 (我不會叫你菜鳥,因為每個人都是從哪裡開始的,對吧 =) )
or
2) 你想測試你的自動彙編知識 (作為擴展)。
那么,如果你是前者,那就慢慢的體會好每個部分,並且在繼續進行前確認自己已經明白了這章。
Dark Byte wrote: |
大多數人都認為AA很難,其實它可容易了。 |
來自CE作者自己的話
如果是後者,那我不會給你提任何的建議,即使我想幫忙。如果你發現有什麼錯了,或者含糊或者認為我可以做的更好,請告訴我。我一直處於自我學習的狀態! 等等!別問,我知道你在想什麼。
You wrote: |
為什麼我非要聽一個還在學習的人的話? |
好,我來告訴你,我的朋友。即使我仍然在學習,我了解AA,並且我認為與你分享知識是一件很棒的事。 =)
Edit: 這個是很久以前寫的,但是現在我學到了很多,並且已經重新檢查了。
現在,讓我們投身入奇幻的電腦世界
------------------------------
II. 暫存器
------------------------------
這些也許你已經在一些腳本中看到過,它們被非常廣泛的使用。有兩種暫存器被使用,接下來來進行講解。
---------------
II.a 32 Bit
---------------
首先,我將解釋每個暫存器是如何得到它們的名字的,這會幫助你記住它們哪個是哪個。首先,以E開頭 (如果你注意了下面,你會發現所有的暫存器都是以E開頭的) 它告訴你這個暫存器是32位暫存器。而A,B,C,D的含義你看完描述就能明顯得體會到了。像SI, DI, BP,SP,IP也是一樣。在 EAX, EBX, ECX, EDX後面的X,他簡單的表示已經沒有更多的字母了。有點像一個 NOP 命令 (之後你將讀到)。如果你注意了,你會發現每個32位暫存器都是3個字母。
EAX: 累加器(Acculmulator register)。能夠用來當存儲器
EBX: 從前,它是個基礎暫存器,但現在只是個閒著的存儲器
ECX: 計數器(Counting register)。也能用來當存儲器
EDX: 數據暫存器(Data register)。跟之前三個一樣,能用來當存儲器。
ESI: 源址變址暫存器(SourceIndex register)。是字元串形式的指針變數,但你現在還不用擔心那部分。能夠用來當存儲器。
EDI: 目的變址暫存器(DestinyIndex register)。又一次,能夠當作存儲器,並且是個字元串形式的指針變數,但別擔心。
EBP: 機制指針暫存器(Base Pointer register)。是用來臨時存儲ESP,當然也可以像常規的存儲器那樣使用。
ESP: 原址指針暫存器(Source Pointer register)。它在堆疊里指向暫存器和地址(這個內容待會再說)。
EIP: 指令指針暫存器(Instruction Pointer register)。錯誤的使用會使你正在試圖修改的程式崩潰。
---------------
II.b 16 Bit
---------------
16位暫存器和32位暫存器很相似,他們間有兩個區別。一是,32位暫存器名字是三個字母,而16位暫存器是兩個字母。還有一件事就是16位暫存器比32位暫存器多但別擔心。16位暫存器我們一般都用不上。
AX: 參照 EAX
BX: 參照EBX
CX: 參照ECX
DX: 參照EDX
SI: 參照ESI
DI: 參照EDI
BP: 參照EBP
SP: 參照ESP
IP: 參照EIP
---------------
關於暫存器的內容還很多。如果你想學習更多關於暫存器的只是,那就去拜Google大神吧。對於絕大多數的學習者來說求知慾都是很重要的。
------------------------------
III. 命令
------------------------------
當今,什麼語言沒有它自己的函式和命令呢? 與英文相比,命令像個單詞,而操作代碼像個句子。操作代碼並不難,比如:
Code: |
jmp 00123EAA |
關於操作代碼你應該知道兩點。
首先,在操作碼里,一般都會有個地址或者暫存器,以及一個顯而易見的命令。地址是Hex形式的,是Hexadecimal的縮寫。Hexadecimal是16進制數。就如同10進制那樣。
按照這種思路想一想。如同上面提到的那樣,我們一般使用十進制。這就意味著我們在一個列里不能有“10”,因為它占了兩個地方。而16進制,10至15都可以放在一個列裡頭。但是你會發現,“10”並沒有出現在列裡頭。
先冷靜,這是因為在Hex進制里,10是用A表示的,而11是用B,直到15是F。再往後,它就是10,然後11,直到1F,如果超過了20(十進制)就得從15(十六進制)往後算。有個簡單的轉換方法就是用作業系統自帶的計算器,這裡不贅述了。
還有,每一個地址都有它的操作碼和位元組碼。這個位元組數就是代表操作碼是什麼,每一個命令都一一對應已經定義好的位元組碼。我知道那些常用函式的位元組碼是什麼,如果你想知道那些位元組碼的話,你還是指望別人吧,推薦去拜Google大神 =)
最後,想注釋很方便。要注釋的話,就把"//"放在命令後邊或某塊空處,然後打上你想打的。如果你不打 "//" ,那電腦就會以為你在打命令呢。
現在,讓我們來了解每個命令都是幹啥的。
---------------
III.a JMP
---------------
JMP 命令是最常使用的命令之一 (就如同 MOV 那樣,接下來會講)。也許你在操作碼和腳本里看到的"JMP" 不像"MOV" 那么多,那是因為 JMP 命令有很多變種。下面就是列表。
JMP: 始終跳轉(Always jump to)
JE/JZ: 相等則跳轉(Jump to if equal)
JNE/JNZ: 不等則跳轉(Jump to if not equal)
JA: 無符號大於則跳轉( Jump to if Above)
JG: 有符號大於則跳轉(Jump to if Greater)
JNA: 無符號不大於則跳轉(Jump to if not Above)
JNG: 有符號不大於則跳轉(Jump to if not Greater)
JB: 無符號小於則跳轉(Jump to if Below)
JL: 有符號小於則跳轉(Jump to if Lower)
JNB: 無符號不小於則跳轉(Jump to if not Below)
JNL: 有符號不小於則跳轉(Jump to if not Lower)
JAE: 無符號大於等於則跳轉(Jump to if Above or Equal)
JGE: 有符號大於等於則跳轉(Jump to if Greater orEqual)
JNAE: 無符號不大於等於則跳轉(Jump to if not Above orEqual (即 JB) )
JNGE: 有符號不大於等於則跳轉(Jump to if not greaterthan or Equal (即JL) )
現在你大致了解了,應該有些疑惑。 "Jump to if greater"或者JG都是條件跳轉。條件跳轉都如同它們名字所描述的那樣,會在條件成立的情況下跳轉。通常,都會有CMP或者其他的比較函式在上面,這個待會再提。以上大抵就是JMP的故事。
---------------
III.b MOV
---------------
前文已經提過, MOV 命令是最被廣泛實用的命令,因為它是那么給力。下面就是MOV的例子:
Code: |
mov eax,ebx |
這個的意思是 "把ebx里存的地址放到eax里"。注意在兩個暫存器之間還有個逗號,而不是空格。最開始這可能有些令人費解,但是它真的很容易,下面來好好解釋一下。
"Mov"是"move"的意思。暫存器自身表示"這個暫存器里存的地址"。基本上來說, "把ebx里存的地址放到eax的地址裡面去",這會把eax之前的值覆蓋並徹底消滅掉。=D你可以通過這個方法複製ebx並把它貼上到eax里。
另一種Mov命令。
Code: |
mov eax,[ebx] |
這個的意思是把ebx裡面的值存到eax所存的地址里,很簡單,把暫存器或者地址用[]那么一括,就表示暫存器或者地址的值了。
下面這段代碼什麼效果都沒有。
Code: |
mov [eax],[ebx] |
沒效果,上面的代碼啥用沒有。你不能!你不能直接把一個值存在另一個值裡面。你可以間接得先把值存在其他的東西里 ;) 參考下面的代碼。
Code: |
push eax //先讓eax入棧—這個待會解釋 mov eax,[0100200A] //把值0100200A 存到eax里 mov [ebx],eax //把(值0100200A) 存到ebx的值裡面 pop eax //然後讓eax出棧,這個也待會講 |
解釋這個是為了MOV函式。繼續...
---------------
III.c Push and Pop + The Stack
---------------
你已經看了上面的Push和Pop 命令的用法。等等!我是尤里!我能讀你的思想!
You wrote: |
那個push和pop都是幹啥的?還有啥是stack? |
好,你讀了前文,在"Push"之後,我是這么注釋的。
Code: |
//Push eax onto the stack (讓eax入棧) |
這個基本上就是把eax存到堆疊里。而pop eax 基本上就是把eax從堆疊中清除。CEF的Skyone寫了一個非常非常好的關於堆疊的解釋,我甚至無法容忍自己不讓你像我那樣獲得對此學習的快樂;)
Skyone wrote: |
堆疊是用來存放可變的空白的值。它就如同: 你有用來做作業的一張紙,但是之後你的朋友打電話叫你給Phil打電話,他的電話是 555-6405。你慌了,沒地方記啊,所以你把它寫在了作業本上了。之後你撂下電話,就可以把Phil's電話寫在電話薄上了。在寫完號碼之後,你就把號碼從作業本用橡皮擦掉了,然後打電話給Phil,並且繼續做作業。 把值push to stack (入棧)就是 "在作業本上寫下Phil的電話號碼" 而pop就是 "把電話號碼錄入到電話薄上,然後再從作業本上擦掉。" |
繼續...
---------------
III.d Alloc/Label/RegisterSymbol
---------------
我一般喜歡用兩種方法來區分Auto Assembler腳本
1) 簡單的地址改變
如同下面的簡單代碼:
Code: |
[enable] 00ABC123: mov eax,ebx [disable] 00ABC123: mov ebx,eax |
這是在改變地址00ABC123裡面的操作碼。
但是也有非常複雜的腳本,就如同dICE 或 pID00的腳本。 (我不會在這裡介紹,因為那真的沒什麼必要去學)
在非常複雜的腳本當中,你會在最頂上看到某些函式,(注意,我並沒有經常使用)在一個複雜的腳本當中通常會出現"alloc","label"函式,有時還會出現"registersymbol"。
````````````
Label
````````````
我認為"label"函式是三個函式中最有重要的。他能夠允許你用在腳本中使用"label"定義的變數,如同下面這樣。(摸丸:label用於定義用於跳轉的標籤)
Code: |
label(Continue) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: //... //... SayWhat: jmp 0 //insta-crash! =D |
首先應該注意此腳本的一些問題,這個腳本沒有"alloc" 函式,之後我就講
接著,如果你明白為什麼程式執行了對應jne的label,那你做得不錯。
注意所有的labels(跳轉標籤)都在我的腳本中定義了,否則他們不會編譯。
````````````
Alloc
````````````
現在開始講解"alloc"函式。它是用來按照你的構想來分配X量的記憶體的函式 (hence,alloc,allocate)。這些記憶體不是那些用過的,而是那些你在運行程式中可以覆蓋的沒有被使用的記憶體。就如同我說的,它會分配X量的記憶體。 X是個位元組數的變數。1024bytes,或者1 kb(kilobyte) 一般就足夠你用了。現在我們了解了alloc函式,讓我來演示下如何來使用它,並利用之前所學到的一切。(摸丸:按照尺寸劃分一塊記憶體,並給它起個名字)
Code: |
alloc(AutoAssembler,1024) alloc(SayWhat,1024) label(Continue) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: //... SayWhat: jmp 0 |
注意為什麼我不這么做
Code: |
label(AutoAssembler) |
或者
Code: |
label(SayWhat) |
因為當用alloc劃分出記憶體的時候,他們在Cheat Engine的詞典中就自動得已經定義好了,便於我們調用。
````````````
RegisterSymbol
````````````
最後,函式"registersymbol"。它可以添加你Cheat Table中你註冊的標誌。注意,你始終需要去為它分配記憶體。讓我們在我們的腳本中試一試。
Code: |
alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: cmp eax,[WooHoo] SayWhat: jmp 0 |
````````````
Counterparts
````````````
現在,讓我們來繼續最後的一小段: the counterparts。
有兩種使用AutoAssembler script的方法。第一種,你可以注入一些東西。第二種,你可以把它添加到Cheat Table中。如果你決定要把它填到cheat table (當今大多數腳本都是如此),那你的代碼需要enable和disable兩部分代碼,如下。
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: cmp eax,[WooHoo] [DISABLE] |
現在,你會注意到,Disable部分什麼也沒有,不過一會就不會了!;)
你在Disable部分中所想達到的就是:撤銷你在Enable部分中所做的。
如何撤銷記憶體分配和註冊中的標記。現在,我感覺有個問題要來了
You wrote: |
你是怎么辦的? |
簡單來說,我的朋友。通過dealloc和 unregister symbol 函式! 喔,等等又有問題要來了。
"那label怎么辦?" 你問?
嗯,沒必要去撤銷label。 =) 這意味著在Disable部分中,你大概要從開始那段中扔掉一半的代碼! =)
那我們為什麼不把學的加進腳本里呢?
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: cmp eax,[WooHoo] [DISABLE] dealloc(AutoAssembler) dealloc(SayWhat) dealloc(WooHoo) unregistersymbol(WooHoo) |
喔這兒...還有個問題。
You wrote: |
為什麼你不用那個"1024"了? |
因為計算機知道你分配的AutoAssembler是大小為1024 bytes 的 (我們就把它當個例子試一試吧),你只是需要deallocAutoAssembler,它就知道應該取消分配AutoAssembler的全部1024 bytes了。(很抱歉,解釋的有些迷糊)
---------------
III.e Call and Ret
---------------
Call 函式和JMP 函式很相似。唯一的不同是Call有個返回到之前代碼的功能。這個簡單例子利用了下面的兩個函式。
Code: |
mov [0100579C],10 //把地址的值改成10 cmp [0100579C],0 //把它和0進行比較 call NameGoesHere //調用或者跳轉到 NameGoesHere jmp 01002FF5 NameGoesHere: dec [0100579C] //地址的值減1 cmp [0100579C],0 //跟0進行比較 jne NameGoesHere //如果不想等就返回到 //NameGoesHere的開始,否則繼續 ret //返回到之前,剛好是調用(call)函式之後 |
---------------
III.f Others
---------------
現在,很顯然,在Auto Assembler還有很多很多其他的函式,不然它就是個很局限的語言。
我會繼續盡我所能解釋更多的函式。 (喔,老兄...)
`````
Nop
`````
Nop: 這個我之前提過。它意味著 "無操作",大體上它可以抵消它之前的代碼。
`````
Inc/Dec
`````
Inc: 加一。用於給暫存器或地址加一。用法如下。
Code: |
inc eax |
Dec: 減一,跟Inc似的
`````
Add/Sub
`````
Add: 加法。用法如下。
Code: |
add eax,02 //給eax加2,並且將結果保存在eax中 |
Sub: 減法,用法類似Add
`````
Lea
`````
這個有點讓人迷糊,但還是繼續吧。看下邊的腳本。
Code: |
mov eax,00123ABC lea ebx,[eax+DEF] |
也許你分不清楚,[eax+DEF] 是一個指針。 LEA把後面被指向的[eax+DEF]的地址替換給前面被指向的ebx里。
`````
And/Or/Xor
`````
好,我不知道如何清晰的說明“異或(xor)”在英文中的含義 –很多網站都只是用幾行字這么描述的...
Them wrote: |
我估計你明白這些邏輯操作符的行為 |
如果誰能給我用英文為XOR做個定義我將感激不盡。即使如此,我還是不需要幫助就能解釋它們是如何在彙編中工作的。 ;)
首先,它們都有著類似於add、sub命令一樣的語法,如下。
Code: |
and eax,ebx |
每個eax 和 ebx 都可能是任何東西。喔不對,他不可能是 "mymom"。 -。-;
回到腳本。來處理這個,(對,我知道我們都不是電腦...) 我們先要給兩個暫存器值。就把12給eax,把27給ebx吧。下面,我們把它換成二進制的—那個零和一的語言。 =O 有問題嗎?
You wrote: |
怎么把十進制轉成二進制啊? |
我的傻朋友啊,你怎么把你的好友計算器給忘了,用十進制把數輸入,然後再點二進制啊! 有些事情需要注意,計算器不允許輸入小數,它會簡單的四捨五入下然後再轉成二進制。
我搞出了:
Code: |
EAX = 1100 & EBX = 11011 |
好,還能回想起國小時做的數學填空題嗎?讓我們在這兒做下。
Code: |
and eax,ebx EAX = 1100 EBX = 11011 ------------ |
現在,ADD(與)方法是如果都是1則是1,否則就是0。那就讓我們來做出這道題吧。
Code: |
and eax,ebx EAX = 01100 (加個0更輕鬆) EBX = 11011 ----------- 01000 |
現在我們把01000改成十進制,我們就會得到8,那個被存在EAX里的值。
接下來,是OR(或)函式。現在讓我們用相同的方法來輕鬆一下
Code: |
or eax,ebx EAX = 01100 EBX = 11011 ----------- |
OR函式的功能與AND函式正相反。都是0,則得0,否則就得1。
Code: |
or eax,ebx EAX = 01100 EBX = 11011 ------------ 11111 |
把11111轉成十進制,那會得到31,是EAX里存的值。
最後,是XOR(異或)函式。還是用那個方法。
Code: |
xor eax,ebx EAX = 01100 EBX = 11011 ----------- |
好,XOR函式是如果兩個數相同就得0,不同就得1。
Code: |
xor eax,ebx EAX = 01100 EBX = 11011 ----------- 10111 |
我們把它轉換成23,而23就是儲存在EAX里的值。順便一提,無論當我們寫的是腳本、代碼還是別的什麼,你都不需要考慮EAX裡面裝的什麼BlahBlahBlah的東西,我之所以這么做是讓你知道它是如何工作的。
`````
好,這就是你所有需要知道的命令,(夥計,這可真長...) 讓我們開始下一章節吧...
------------------------------
IV. Array of Bytes
------------------------------
好,想像一下。你已經有了你的代碼你的腳本你的地址,你準備開始hack。萬事俱備,只欠……。喔不! 補丁! 但別慌。現在你不用擔心等待別人發布新的記憶體地址!
You wrote: |
我慌了?沒印象啊... |
你沒慌?!
喔,你還不知道該怎么做
好,接下來讓我來告訴你,我的朋友
1) 打開你的CE並附加上正在Hacking的遊戲進程。
2) 點作弊表右上方的"手動添加地址(AddAddress Manually)"。
3) 點那個"地址(Address)"文本框,並且鍵入你想獲得的AOB碼的記憶體地址。
4) 點擊下拉框,點開"類型(Type)"並選擇“位元組數組(Array of Byte)”
5) 在number of bytes 或是Nr. of bytes鍵入8。
6) 點確認。 =)
好,現在你就得到了與你地址對應的AOB碼了,但是打補丁之後怎么辦呢?
1) 打開你的CE,然後載入你想hack的遊戲。
2) 在CE上方中間的搜尋部分中選擇下拉框中的值類型,並選擇位元組數組。
3) 現在,鍵入或者從記事本里把AOB碼貼上到值的框裡。
4) 先掃描,然後地址就應該出現了。如果沒有一個地址出現,那就把AOB碼弄短點 (從後面刪掉一組值),然後再掃描。(摸丸:這裡還應該勾選上“同時掃描唯讀記憶體”)
好,你已經得到了地址... 現在你要拿它做什麼呢? 把它轉換成你想要的腳本—就讓我們用 v.38版的Maplestory上帝模式腳本做例子吧。
Code: |
[ENABLE] 6803ec: je 0068133e [DISABLE] 6803ec: jne 0068133e |
既然你有了新地址,那就在Enable和Disable塊中刪除"6803EC",並且貼上上你的新地址。要確認別在那兒把冒號給忘了。
嗯,這就是AOB(Array of Bytes)...
------------------------------
V. Conclusion
------------------------------
...還有很多關於自動彙編的教程! 嘿等等,我感覺到一個問題要來?
You wrote: |
真的就這么簡單嗎? 就這樣? 沒有更多的竅門或者其他類似的了嗎? |
沒,就這樣! 又一次,我應該引用CE作者的話...
"大多數人都認為ASM很難,但事實上,它非常簡單。"~Dark Byte himself
即使如此,在此之後我還有一個關於寫腳本的小教程,請稍等,兄弟! 你沒必要讀"Writinga Script" 教程的,那只是個額外的部分,雖然我強烈推薦。
------------------------------
VI. Credits/Acknowledgements
------------------------------
在給出人員表之前,有很多需要感謝的人。
首先,首要的,Wizet,他製作了Maplestory所以我才能去hacking。 ; )
第二, Dark Byte,他創建了我們今天hack的基礎,並且為Cheat Engine製造了教程。嘿,我們都有個開始!
第三, Sponge和Labyrnth幫我做腳本。
第四,所有教程的作者,我學到了很多知識。
謝謝你們!
``````````
人員名單
``````````
注意,排名不分先後。
Scrbly's Tutorial on CodeInjection and AutoAssembler
Idogear'spost on Basic Assembly
TheSorc3r3r'stutorial on Beginning Assembly Language
Skyone's Tutorial on Basic Assembly
M3KillU's tutorial on Array of Bytes
Renkokuken'sPost on Register Sets
Vrunk'sTutorial on Allocated Memory
Dark Byte's Guide on Basic Assembler
Dark Byte's Guide on the registersymbol/unregistersymbolfunctions
Zhoul's "There's always more than 1 way to skin acat"
Dark Byte's "Auto assembler scripts in cheat tables"
------------------------------
Bonus. Writing a Script
------------------------------
既然你讀了教程,那也應該很了解了,但你還是想知道更多。我明白,就如同我體會過的—遺憾。我不認為有任何關於寫腳本的教程是我用的上的。
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: cmp eax,[WooHoo] SayWhat: jmp 0 [DISABLE] dealloc(AutoAssembler) dealloc(SayWhat) dealloc(WooHoo) unregistersymbol(WooHoo) |
還記得之前的這個腳本嗎? 現在讓我們用我們所學的大量內容把它弄完整。
Code: |
[ENABLE] alloc(AutoAssembler,1024) alloc(SayWhat,1024) alloc(WooHoo,1024) label(Continue) registersymbol(WooHoo) AutoAssembler: mov eax,02 cmp eax,03 jne Continue je SayWhat Continue: cmp eax,[WooHoo] SayWhat: jmp 0 [DISABLE] dealloc(AutoAssembler) dealloc(SayWhat) dealloc(WooHoo) unregistersymbol(WooHoo) |
對於腳本你需要有些東西,一個你試圖hack的程式的真實記憶體的地址。無論如何,它都不能是一個隨機的地址,或者是一些你不希望它發生但是會導致其發生的地址(崩潰,也許)。這個地址對於這件事很重要。
但是為什麼我們需要一個地址? 就如同之前我所說的,alloc 函式在你的程式中分配一塊未使用記憶體。因為這是未使用的,程式不會訪問這裡,所以,你要讓程式訪問它。
當你干預這些地址時,你需要注意一些至關重要的事情。第一,你必須用與源碼相同總量的位元組。如何知道一個操作碼位元組的數量呢? 簡單,看在地址和操作碼中間,那兒應該有一堆兩個一組兩個一組的字元,他們被稱為Array of Bytes。
nop 函式對於這種情況非常有幫助。就如同我之前解釋的那樣,它的含義是“無操作”。並且它只用一個位元組。這意味著,如果你用不了所有的位元組位置,那你就可以用nop把它填滿。
當填位元組時你可能會遇到三種情況。我已經描述了第一種你的代碼比源碼少的情況。剩下兩種情況的一個是,你的代碼所占的位元組數和源碼位元組數相等,一切剛剛好。
但最後一種情況有些令人困惑,那就是你的代碼的位元組比源碼的多。現在,你的代碼的位元組會把下面的代碼位元組覆蓋,直到位元組的位置夠用。
為什麼我們不玩Minesweeper呢? 一段時間之前,我還在學習寫腳本的時候,我寫了一小段代碼(我還是我,但那時我還知道的很少)。
Code: |
[enable] alloc(WhatNowMinesweeper,256) //分配... alloc(ChiliDog,4) label(ReturnHere) registersymbol(ChiliDog) //註冊... ChiliDog: dd 0 //用於參考引用,表示ChiliDog的值是從0開始 01002FF5: //這個地址是為MineSweeper寫入時間的 jmp WhatNowMinesweeper //我重寫了操作碼,讓它跳轉到我的腳本 nop //填充了最後的位元組 ReturnHere: //這個是乾什麼的我待會告訴你 WhatNowMinesweeper: //我的實際代碼 push eax //保存eax, 我們不這么做就會有問題 mov eax,[ChiliDog] //把ChiliDog的值傳入eax mov [0100579C],eax //把存有ChiliDog值的eax存入時間 pop eax //讓eax出棧,因為我們已經用完了 jmp ReturnHere //跳轉到ReturnHere, 待會解釋 [disable] dealloc(WhatNowMinesweeper) //取消分配記憶體 dealloc(ChiliDog) unregistersymbol(ChiliDog) //反註冊標識 01002FF5: //這是我修改來跳入我的代碼的地址 inc [0100579C] //這是源操作碼用以防止崩潰 |
現在,最最先要做的。我要告訴你"ReturnHere"是什麼。如你所知,一個被告知要執行一個操作碼的程式進程,他們會自動移動到下一個操作碼,然後繼續。這就如同一個無限的輪迴。這樣,如果我們弄了條死路,即代碼之後已經沒有代碼了,那這個程式幾乎就會崩潰。因此,我們要讓它執行過我們的代碼之後再返回到調用跳轉之後的位置上,這樣代碼就可以繼續了—並且我們也不會崩潰! =D
關於寫腳本還有很多內容。請自由的提問並且評論你是否喜歡。 =)