來(lái)源:YesCK
前言:
寫這篇文章出于個(gè)人興趣,要先聲明的是本人能力是非常有限!其中參考了許多文章!由于無(wú)法提供更多的信息教程,所以文章題目才叫做"給新手引路 之 濃縮匯編基礎(chǔ)"。主要講的是破解中所要的一些匯編知識(shí),方便新手們理解,我將用比較通俗的語(yǔ)言講述!希望大家別說(shuō)我"低級(jí)" - -b
寫此文的理由:
1、出于興趣
2、助于自己學(xué)習(xí)鞏固,利于新手
注:
本文并不教如何編寫匯編程序,只想引新手們進(jìn)Crack大門,一些遲遲無(wú)法Crack成功的人也就是這個(gè)原因了!
最好是能拋磚引玉了,勾起新手們學(xué)習(xí)匯編的興趣!
重要一點(diǎn)是:不懂匯編是完全沒(méi)辦法搞Crack的,希望大家?guī)е@點(diǎn)來(lái)學(xué)習(xí)!
-----------------------------------------------------------------------------------------------
1.0 關(guān)于匯編語(yǔ)言
匯編語(yǔ)言是創(chuàng)造出來(lái)代替原始的只能由處理器理解的二進(jìn)制代碼的,也就是在OD中常見(jiàn)的機(jī)器碼!用機(jī)器碼來(lái)寫程序,可以想象其難度吧,所以匯編語(yǔ)言就出現(xiàn)了,匯編代碼是直接描述處理器可以執(zhí)行的代碼,也就是在OD中最常見(jiàn)的反匯編代碼了!(當(dāng)然,有點(diǎn)不一樣),而匯編語(yǔ)言是和cpu相關(guān)的,和機(jī)器語(yǔ)言是一一對(duì)應(yīng)的!
2.0 關(guān)于cpu
CPU的任務(wù)就是執(zhí)行存放在存儲(chǔ)器里的指令序列。為此,除要完成算術(shù)邏輯操作外,還需要擔(dān)負(fù)CPU和存儲(chǔ)器以及I/O之間的數(shù)據(jù)傳送任務(wù)。早期的CPU芯片只包括運(yùn)算器和控制器兩大部分。到了近幾年,為了使存儲(chǔ)器速度能更好地與運(yùn)算器的速度相匹配,又在芯片中引入了高速緩沖存儲(chǔ)器(知道為什么P4比P4賽揚(yáng)貴那么多了吧?)。
看主要的部件:
1.算術(shù)邏輯部件ALU(arithmetic logic unit)用來(lái)進(jìn)行算術(shù)和邏輯運(yùn)算。這部分與我們的關(guān)系不太大,我們沒(méi)必要管它。
2.控制邏輯。同樣與我們的關(guān)系不大。
3.工作寄存器。意識(shí)了吧,寄存器呀!喂,,寄存器呀!~
3.0 寄存器
所要了解的是8個(gè)32位的寄存器,分別是eax,ebx,ecx,edx,esp,ebp,edi,esi
eax-edx這四個(gè)是通用寄存器,雖然各個(gè)都有各自的用途,不過(guò)你可以用它們來(lái)做任何事!是32位的,自然有低位和高位,我們又可以通過(guò) ax,bx,cx,dx來(lái)訪問(wèn)其低十六位,但高十六位是無(wú)法訪問(wèn)的!比如eax=12345678h,那么低十六位ax=5678h!而十六位的自然也有低位和高位,不過(guò)高八位是可以訪問(wèn)的,如ax可以分為ah和al,看字面就知道,ah(high)高八位,al就為低八位了!前面的例子,ax=5678h,那么ah=56h,al=78h!這四個(gè)寄存器主要是用來(lái)暫放計(jì)算結(jié)果或什么什么的!
esp-esi這四個(gè)主要是尋址時(shí)用來(lái)存放偏移或指針,所以,也就稱為指針寄存器或變址寄存器了~如在OD中看到的[eax],其實(shí)eax中存放的是一個(gè)內(nèi)存地址,而實(shí)際要訪問(wèn)的是那個(gè)內(nèi)存地址里的內(nèi)容!
esp(堆棧指針寄存器):
很重要的一個(gè)概論,堆棧有著先進(jìn)后出的特點(diǎn),就好像有一個(gè)圓柱形的筒子,該直徑剛好是一個(gè)乒乓球的直徑,所以最先放進(jìn)去的球當(dāng)然會(huì)最后出來(lái).而esp呢, 永遠(yuǎn)是指著最頂?shù)哪莻(gè)球的,也就是永遠(yuǎn)都指向棧頂!在od中也很常見(jiàn)了,比如push和pop就是對(duì)棧的操作,push把一個(gè)數(shù)據(jù)壓入棧中,也就是把一個(gè)球放進(jìn)去,再去調(diào)用push時(shí)就再放進(jìn)一個(gè),而esp則指向第二個(gè)放進(jìn)去的那個(gè)球了!使用pop呢就從棧中彈出一個(gè)數(shù)據(jù),前面說(shuō)了,堆棧有著先進(jìn)后出的特點(diǎn),所以用pop呢就從最后放進(jìn)去的那個(gè)球先出了(除非你破壞筒子(破壞堆棧?那是不可能的,程序馬上死給你看))!而esp還是指向棧頂!
取個(gè)代碼例子:
(1) mov ecx, 100<---------100傳入ecx
(2) mov eax, 200<---------200傳入eax
(3) push eax <------------ecx先進(jìn)了
(4) push ecx<-------------再來(lái)是eax
(5) pop ebx<--------------從棧頂取出一個(gè),也是最后進(jìn)去的那一個(gè),結(jié)果存到ebx
(6) pop ecx<--------------從棧頂取出一個(gè),也就是剛剛先進(jìn)去的那個(gè)了,結(jié)果存到ecx
最后ebx=200,ecx=100
到了win32的平臺(tái)下,api大家都知道了吧!api的參數(shù)都是靠堆棧來(lái)傳遞的,比如說(shuō)一個(gè)FindWindow,在C里我這樣調(diào)用
->::FindWindow(NULL,"a")->而反匯編之后在系統(tǒng)底層反匯編代碼就象這個(gè)樣子:
push xxxxxxxx->xxxxxxxx為"a"的內(nèi)存地址
push yyyyyyyy->yyyyyyyy為空中止字符串的指針
call zzzzzzzz->調(diào)用FindWindow
而在call里面先使用pop彈出先前壓入棧的參數(shù)再使用
ebp(基址指針寄存器):
它稱為基址指針寄存器,它們都可以與堆棧段寄存器SS(堆棧段)聯(lián)用來(lái)確定堆棧中的某一存儲(chǔ)單元的地址,ESP用來(lái)指示段頂?shù)钠频刂,而EBP可作為堆棧區(qū)中的一個(gè)基地址以便訪問(wèn)堆棧中的信息。
ESI(源變址寄存器)和EDI(目的變址寄存器)一般與數(shù)據(jù)段寄存器DS聯(lián)用,用來(lái)確定數(shù)據(jù)段中某一存儲(chǔ)單元的地址。這兩個(gè)變址寄存器有自動(dòng)增量和自動(dòng)減量的功能,可以很方便地用于變址。
還有兩個(gè)專用寄存器,分別是eip和flags
flags:
這個(gè)是標(biāo)志寄存器了,存放條件標(biāo)志碼、控制標(biāo)志和系統(tǒng)標(biāo)志的寄存器!在od中也見(jiàn)很多了,比如zf(零標(biāo)志),用cmp比較時(shí),把兩個(gè)操作數(shù)相減,為0就置zf為1,否則zf為0。而jnz就是看zf是否為0,為0就跳!這樣說(shuō)起來(lái)似乎更亂了,建議大家去記那些大于就跳,小于就跳的,比較簡(jiǎn)單(jnz就是不相等就跳)``哦呵呵!!至于其它標(biāo)志,這里不再闡述了,可以去參看匯編速查!
cmp eax,ebx<-比較eax和ebx,兩個(gè)相減,為0的話zf就為一,否則zf為0
jnz xxxxxxx<-判斷zf是否為0,為0就跳到xxxxxxx處,也就是所謂的不相等就跳
eip(指令指針寄存器):
這個(gè)很好理解,根據(jù)od來(lái)說(shuō),載入一個(gè)程序后,比如代碼像這樣:
0043C412 >/$Content$nbsp; 55 push ebp <-載入后停在這,看寄存器窗口eip這時(shí)為43c412
0043C413 |. 8BEC mov ebp, esp <-f8運(yùn)行一步之后,eip為43c413
0043C415 |. 6A FF push -1 <-eip為43c415
0043C417 |. 68 C8B64800 push 0048B6C8 <-eip為43c417
有人會(huì)說(shuō)"原來(lái)eip是指示當(dāng)前執(zhí)行到代碼處的地址的!" ,這不對(duì)!!因?yàn)閒8運(yùn)行還沒(méi)通過(guò)那條代碼,所以還不算已經(jīng)執(zhí)行了,沒(méi)錯(cuò),eip指向的就是下一條將要執(zhí)行的指令的指針!
段寄存器:
cs代碼段,ds數(shù)據(jù)段,ss堆棧段,es附加段
在Win32編程中段的概念已經(jīng)不重要了!而在Crack時(shí)你總不會(huì)是在調(diào)是dos時(shí)代的程序吧!-!
4.0 常用匯編指令
mov ax,cx <-很常用了,把cx的值送入ax中,cx值保持不變
cmp eax,ecx<-很常見(jiàn)了吧,比較eax和ecx,置標(biāo)志位!方法前面說(shuō)過(guò)了
xor eax,eax<-看這個(gè),eax與自己異或,是清零的操作!
lea eax,str<-并不傳送數(shù)據(jù),只傳送該數(shù)據(jù)的地址,將str字符串的地址傳到eax
push eax <-進(jìn)棧操作,前面說(shuō)過(guò)了,eax進(jìn)棧
pop ebx <-出棧操作,前面也說(shuō)了,彈出位于棧頂?shù)臄?shù)據(jù)存入ebx
ADD 加法指令 格式:ADD DST,SRC 執(zhí)行的操作:(DST)<-(SRC)+(DST)
SUB 減法指令 格式:SUB DST,SRC 執(zhí)行的操作:(DST)<-(DST)-(SRC)
MUL 無(wú)符號(hào)乘法指令 格式: MUL SRC 執(zhí)行的操作:字節(jié)操作(AX)<-(AL)*(SRC);字操作(DX,AX)<-(AX)*(SRC);雙字操作:(EDX,EAX)<- (EAX)*(SRC)
DIV 無(wú)符號(hào)除法指令 格式:DIV SRC 執(zhí)行的操作:字節(jié)操作:16們被除數(shù)在AX中,8位除數(shù)為源操作數(shù),結(jié)果的8位商在AL中,8位余數(shù)在AH中 。表示為:
(AL)<-(AX)/(SRC)的商,(AH)<-(AX)/(SRC)的余數(shù)。字操作:32位被除數(shù)在DX,AX中。其中DX為高位字,16位除數(shù)為源操作數(shù),結(jié)果的16 位商 在AX中,16位余數(shù)在DX中。表示為:(AX)<-(DX,AX)/(SRC)的商,(DX)<-(DX,AX)/(SRC)的余數(shù)。
nop <- 無(wú)操作,去掉指令用的吧!去掉一個(gè)跳轉(zhuǎn),讓程序直接往下走,就到注冊(cè)成功處啦(扯遠(yuǎn)了````)
call <- 調(diào)用子程序或函數(shù)用的
關(guān)于跳轉(zhuǎn)指令,可以查看匯編速查手冊(cè),別強(qiáng)迫自己把所有的都一下記住,浪費(fèi)精力,不懂時(shí)再查一下,久了就記住了!
5.0 高級(jí)語(yǔ)言程序的匯編淺解析
匯編語(yǔ)言要和硬件直接打交道,寫病毒是方便點(diǎn)啦!!而在高級(jí)語(yǔ)言中,如C中我們要面向的是問(wèn)題的解決,對(duì)于硬件資源操作,編譯器搞定了!在這里稍微講一下高級(jí)語(yǔ)言中與反匯編代碼相應(yīng)的一些地方:
1、定義變量
int a;
一個(gè)變量其實(shí)是存放在一個(gè)內(nèi)存地址里,如果對(duì)a進(jìn)行賦值"a=10",在反匯編中就有可能表現(xiàn)為:
mov word ptr[007e58c2],A
像這個(gè)樣子,而a所對(duì)應(yīng)的內(nèi)存地址就是0x007e58c2了,當(dāng)然是亂寫的一個(gè)地址而已,系統(tǒng)怎樣分配?(天知道...)
2、比如一個(gè)數(shù)組
char str[]="hello";
占用了6個(gè)字節(jié),最后一個(gè)是以0結(jié)尾的空字節(jié),數(shù)組名可以當(dāng)做數(shù)組的指針!str[0]='h',str[0]相應(yīng)一個(gè)變量地址,比如為[0040e123],那么[0040e124]就為'e',[0040e125]就為'l'....了`
3、指針
char *p;
指針也是一個(gè)變量,所以它也對(duì)應(yīng)一個(gè)內(nèi)存地址!但訪問(wèn)時(shí)應(yīng)該是訪問(wèn)其指向的內(nèi)存地址的內(nèi)容,而不是這個(gè)指針變量的內(nèi)容,其內(nèi)容只是一個(gè)地址而已!假如該指針變量地址為007e1000,那么語(yǔ)句p=a,這句在高級(jí)語(yǔ)言里是讓指針p指向a這個(gè)內(nèi)存單元!p里的內(nèi)容是a的地址,*p實(shí)際上是a的內(nèi)容了!而反匯編有可能表現(xiàn)成這樣:
mov [007e1000],007e2000<-假如007e2000為變量a的地址,那么就是把a(bǔ)的地址傳到007e1000這個(gè)內(nèi)容里了!
4、函數(shù)調(diào)用
sub(a,b);
假如sub是自定義的一個(gè)減法函數(shù),作用為參數(shù)一減去參數(shù)二,上面語(yǔ)句為在C中調(diào)中時(shí)傳遞參數(shù)!前面有說(shuō)過(guò)了,Win32平臺(tái)下函數(shù)調(diào)用的參數(shù)是通過(guò)堆棧來(lái)傳遞的,那么反匯編就是:
(假如a=2,b=1)
mov eax,2
mov ebx,1
push eax
push ebx
call 取地址(sub)
.......
-----------------------------------------------------------------------------------------------
好了,最后感謝大家能看完這篇了了草草的東西,我也回顧了不少知識(shí)!在本人能力范圍內(nèi)的事不知道對(duì)新手們有沒(méi)有幫助,還有一點(diǎn)要提醒各位新手,如果真想學(xué)好Crack學(xué)通Crack這門知識(shí)的話,不完全了解匯編是不行的!所以在看了我這篇之后如果能激起你學(xué)匯編的信心是最好的!要不等到Crack遇到什么問(wèn)題時(shí)才再想回過(guò)頭學(xué)匯編,那很難!~