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