32位彙編第一講x86和8086的區別,以及OllyDbg調試器的使用

 

 

             32位彙編第一講x86和8086的區別,以及OllyDbg調試器的使用

一丶32位(x86也稱爲80386)與8086(16位)彙編的區別

1.寄存器的改變

  AX 變爲 EAX  能夠這樣想,16位通用寄存器前邊都加個E開頭c++

例如:編程

  

EAX  EBX ECX EDX ESI EDI ESP EBP    ;八個寄存器
EIP EFLAGES                         ;特殊寄存器
CS ES SS DS GS FS            ;其中GS FS是新增長的寄存器,這些段寄存器,並非4個字節(32位的)仍是之前16位的

注意在32位下沒有分段的概念的,由於尋址能力是 0- FFFFFFFF  ,在當時的inter認爲當初的4G已經很厲害了,那是後最好的內存才1G,放到如今看windows

咱們感受4G不夠用了,但也是近幾年纔開始用的8G安全

有分區的概念,好比咱們16位彙編中,給代碼分段的時候,順便分了一下區,分區是爲了更好的管理代碼的編寫框架

2.地址有20根總線變爲32根總線(也就是4G)

3.寄存器的數量沒有作改變

2.32位寄存器和16位寄存器的兼容

EAX 的低16位變爲AX了,因此兼容的16位,其他的寄存器同理編輯器

32位中的段寄存器不是咱們能操做的了,給操做系統使用,因此有了權限一說函數

在16位中,咱們能夠直接操做段寄存器分段,或者尋址,而這樣很不安全,萬一你分段的時候,正好在操做系統的代碼區,那麼你能夠修改代碼,那麼操做系統就崩潰了工具

因此爲了系統的穩定,操做系統不讓使用段寄存器了,而這些段寄存器操做系統都記錄了一些表的信息spa

二丶編寫32位中的彙編代碼

1.介紹

  在編寫32位彙編的時候,介紹一下編譯器和鏈接器,之前咱們使用的彙編編譯器是能夠編譯32位彙編的,可是鏈接器是不能鏈接32位彙編程序操作系統

因此link鏈接器須要改成32位的,若是有安裝過vc++6.0 那麼是能夠找到它的鏈接器的,咱們使用它的鏈接器便可.

2.分區概念

  上面說了,操做系統不讓咱們使用段寄存器,那麼咱們能夠去分區,分爲 常量區  全局數據區  代碼區 (沒有棧區,棧區由編譯器維護,編譯器分配)

首先介紹一下僞指令的用法(僞指令在16位彙編最後一講都講了,那麼這節課就要調用僞指令去編寫彙編代碼了,還會增長僞指令去講解)

1.僞指令

      ①.model僞指令的使用

memorymodel: 表示你要設置的內存模式 這裏咱們設置平坦模式(表示內存是連續的,由於不能分段了)平坦模式 FLAT

[,langtype]調用約定: 若是這裏寫了調用約定,那麼之後咱們使用 函數的僞指令(PROC)的時候,就不用指明調用約定

了並且win32能夠調用操做系統API,而調用API的時候,這些API的調用約定,也是你這裏給指定的

用法例子:

  

.386   ;這裏表示咱們要寫386的程序(也就是32位)彙編程序,指明一下,這個不是僞指令
.model FLAT,stdcall ;內存設置爲平坦模式,默認調用約定stdcall

  ②僞指令PROTO(函數聲明)

函數聲明的僞指令,這個主要是針對咱們本身寫的函數,若是調用的時候,函數正好在下面(他會從上面找,找不到報錯)因此聲明一下告訴它存在便可

例子:

  

;使用僞指令聲明
My_ADD PROTO n1:dword,n2:dword

;調用
invoke My_Add ,1,2  ;函數實如今下面,若是不寫聲明告訴存在,就會調用出錯
My_ADD PROC n1:dword,n2:dword ;定義了一個函數,參數是n1,n2,指明的大小是DWORD(4個字節的),這裏沒有寫調用約定,上面寫了默認的調用約定了

My_ADD endp  ;函數定義的結束標誌

  ③僞指令 option(選項的僞指令)

這個僞指令主要是增長額外選項,好比上面咱們調用函數,彙編不區分大小寫,你這樣寫是能夠調用的,可是爲了

沒必要要的麻煩,咱們加上一個選項,也就是大小寫敏感,也就是區分大小寫,這樣咱們調用系統API的時候就不用怕出錯了

使用例子:

  

option casemap:none  ;使用大小寫敏感的選項

   ④定義常量去的僞指令(.const)

上面說了,內存有了保護模式,分爲了 可讀可寫可執行,若是是常量去,那麼只能讀,不能寫,不能執行

語法:

  

這個比較簡單了

使用例子:

  

.const ;定義常量區
    g_szTitle db "Hello"  ;在常量區中定義常量字符串

   ⑤數據區的定義(.data)

數據區,專門定義數據使用的,是可讀可寫的

語法:

它分爲兩種,一種是初始化的數據區,一種是未初始化的數據區

初始化數據區的寫法:

  

.data ;定義數據區
      ....;你本身的數據 

未初始化的數據區寫法

.data ?;加?號表示未初始化
    g_szData dw ? ;數據的申請必須是? 也就是未初始化的

二者的區別

  初始化的數據,不過你定義數據的時候,是否給? 都會寫的EXE(PE文件中)

  未初始化的數據, 定義數據的時候只能給? 不在PE文件中保存

  ⑥代碼區的僞指令(.code)

定義執行的代碼區

語法:

例子:

  

.code
START:     ;代碼開始執行的標號

end START; end表示文件結束START表示要從START開始執行代碼

 

  ⑦多文件編譯ASM(#include 後綴名.inc)

咱們有時候會想,代碼不可能一個文件寫完,好比多個文件聯合編譯,因此就有了.inc文件

通常咱們定義數據區,或者定義的宏都放在.inc的文件中

而後ASM文件使用include xxxx.inc 包含你本身的.inc文件便可

3.一段完整的win32彙編代碼框架

上面的僞指令已經講完了,這裏寫一段完整的彙編代碼

.386                                ;定義爲386的彙編程序
.model FLAT,stdcall                ;內存爲平坦模式,默認調用約定stdcall
option casemap:none             ;增長選項,區分大小寫

.const                              ;定義常量區(這些應該放到.inc文件中這裏不妨了,放的話就是拷貝過去,而後這個文件引用便可)

    g_szTitle db "Title",0        ;win32字符串結尾都是0結尾了
    g_szMsg  db "Hello 51asm.com",0

.data                               ;定義數據區
 
.code                               ;定義代碼區
START:
    .....                ;你的核心代碼
end START

三丶編譯鏈接Win32彙編程序

在32位中,編譯彙編程序和鏈接彙編程序就有點不一樣了

1.編譯:

在CMD中輸入

ml /c  /coff 文件名.asm

 上面說過,咱們在32位下,有了PE文件格式(exe文件),而PE文件格式是 COFF格式,也稱做爲PE

編譯幫助:

表示咱們要編譯爲一個PE的obj格式

編譯咱們的代碼

而後出現這個,表示編譯成功,看下obj文件

若是咱們不加,就會編譯成了16位的了,而鏈接的時候就會找16位的鏈接器,就會出錯,顯示找不到入口點的

錯誤

2.鏈接

鏈接的時候,不能在使用16位的鏈接器了,這裏可使用VC自帶的link,沒有沒有關係,我會在天天的資料中上傳所用的工具

鏈接選項(對咱們有用的)

這個對咱們有用,由於在32系統下,有了窗口的概念的,表示你要鏈接成什麼程序,控制檯的仍是窗口的

假設咱們要鏈接爲一個控制檯的程序

link /subsystem:console 文件名.obj  ;鏈接成一個控制檯的程序

代碼沒有出錯,則正常顯示

 四丶寫一個窗口版本探彈消息的程序,並用OllyDbg去分析

1.編寫窗口程序

咱們基於上面的32位程序的框架,寫一個簡單版本的信息框,彈出一個消息,把咱們常量區的數據彈出來

並用OlleyDbg去分析

首先查一下MessageBox的用法

咱們知道了,第一個參數是窗口句柄,沒有咱們能夠給NULL 而NULL 在彙編中沒有,咱們就用宏定義 (EQU)

第二個參數是一個0結尾字符串的首地址,那麼在彙編中能夠經過 offset僞指令,把常量區的地址給它

第三個參數同樣

第四個參數是顯示彈框的按鈕風格,咱們通常使用MB_OK,而MB_OK 是0,彙編中也沒有,因此咱們定義一下

彙編代碼例子:

.386
.model FLAT,stdcall  ;設置內存爲平坦模式,默認調用約定STDCALL
option casemap:none     ;區分大小寫

NULL EQU 0      ;定義NULL
MB_OK EQU 0     ;定義爲0
MessageBoxA PROTO hWnd:DWORD, :DWORD,:DWORD,:DWORD    ;函數聲明,聲明爲有4個參數,默認調用約定是Stdcall
.const
    g_szTitle db "Title",0
    g_szMsg   db  "Hello www.w1x8.com ",0

.data

.code
START:
    
    invoke MessageBoxA,NULL, offset g_szMsg,offset g_szTitle,MB_OK;調用API
end START

這裏使用的是MessageBoxA,由於操做系統分爲寬字節和Ascii碼版本

這裏編譯的時候命令仍是上面的那個命令,(ml /c /coff 文件名.obj)

鏈接的時候不同了

鏈接的時候咱們須要連接爲Windows窗口程序,並且最重要的一點就是MessageBoxA的實現代碼在User32.lib中,因此也要一併的加入進來

link /subsystem:windows 文件名.obj  user32.lib ;注意,user32.lib放到彙編程序所在的目錄下

看下編譯出來的程序

2.使用OllyDbg分析

把咱們的exe放到OllyDbg中分析

這裏先說下經常使用的快捷鍵

F2      : 設置/取消斷點
F3      : 加載文件
F4      : 運行到選中的位置
F5      : 縮小/還原窗口
F7      : 單步步入
F8      : 單步步過
F9      : 運行程序
F10     : 彈出右鍵菜單
F12     : 使正在執行的程序暫停
CTRL+F2 : 從新載入文件
CTRL+F8 : 以指令爲單位逐條自動執行
CTRL+F9 : 執行到當前函數的return處
CTRL+F11: 跟蹤進入
CTRL+F12: 跟蹤跳過
CTRL+G  : 跳到某地址處
CTRL+B  : 查找二進制字串
CTRL+N  : 查看當前模塊中的名稱
CTRL+K  : 查看調用樹
CTRL+E  : 編輯選中行的二進制數據
CTRL+減 : 轉到上一個函數過程處
CTRL+加 : 轉到下一個函數過程處
ALT+F2  : 關閉已加載的文件
ALT+F9  : 執行到到用戶空間代碼
ALT+B   : 查看斷點
ALT+E   : 查看已加載的可執行模塊
ALT+Q   : 關閉並退出OD調試器
分號    : 加註釋
冒號    : 加標籤
空格    : 激活/禁用斷點;彙編選中行
-/+     : 回/前看執行過的指令
今天咱們用到的是 F7  F8 Ctrl + F2的指令
載入咱們的EXE文件

能夠看到咱們的彙編代碼都在這裏,咱們F8單步執行,找到第一個Call,也就是MessageBoxA,F8走到Call的地方

F7進入

而後看下,他也是同樣壓棧ebp,出棧ebp,而後看下棧區,

看下EBP的位置(這裏的EBP是執指向棧頂的,由於咱們 mov ebp,esp了)

而後棧的格式和咱們前邊講的是同樣的

棧的當前結構:

 

保存棧底的值(ebp)

返回地址  

參數一

參數二

參數三

參數四

3.使用OD把咱們的標題修改了成輸出的消息,把之前的標題,修改成輸出的消息(有點繞,就是兩個互換輸出)

思路:

  咱們把壓棧的順序修改一下

雙擊,把當前的壓棧的順序修改一下

push 1.00402008  修改成: push 1.0040200E
push 1.0040200E  修改成: push 1.00402008

 

而後選擇這兩行,右鍵 -> 複製到可執行文件 而後選擇 選擇全部複製(至關於修改後的EXE)

最後彈出了個新的,咱們點擊保存文件便可

修改後的EXE

五丶關於PE文件的那點事

 

 上面說了咱們的信息會保存在exe文件中(也就是PE)咱們用WinHex(16進制編輯器)查看一下

1.32位執行的開始

咱們的EXE在這裏上面的位置,都是爲了兼容16位的,而真正的32位程序是從PE這裏開始執行的,

上面的某些字段保存了PE所在的偏移,好比PE所在的位置是C8,那麼上面的字段就會有C8保存,由於軟件已啓動

會根據這個偏移尋找PE文件的位置,這裏C8位置在3C的位置

那麼就表明咱們不改變這個值,其他的隨便修改,那麼不影響32位程序的使用,咱們修改一下

修改後仍是能運行的

 

這個彙編程序會崩潰,緣由是咱們沒有寫退出,好比16位彙編中的退出是 

mov ah,4c00h
int 21h

這裏就不寫了

2.32彙編中簡單的Dll劫持和API HOOK(思想)

注入方法不少,這裏有個簡單的,好比咱們上面調用了一個MessageBoxA

他是在Lib中尋找dll的路徑,以及MessageBoxA在那個Dll中

咱們使用的這個Dll是動態的Dll,裏面記錄了Dll所在的路徑,以及導出函數

而咱們彙編中剛在這樣用則是把user32.lib中當前調用的MessageBoxA所在的Dll路徑,以及Dll導出函數的信息

鏈接到EXE文件中

因此說EXE文件中也會保存Dll的信息

咱們使用WinHex查找一下EXE中是否有MessageBoxA

CTRL + F 查找,輸入字符串

找到了所在的位置,咱們把USER32.DLL改下名

 

 

 

能夠看到,他找不到AAER32.dll,若是厲害的本身能夠寫一個AAER32.DLL,(固然細節不少,這裏只是簡單的思想)

咱們就能夠把DLL劫持了

好比咱們把前邊的函數名字修改了,那麼若是你厲害,能夠寫個相同函數,就造成了APIHOOK

 

課堂資料下載地址:

 當前第一課課程資料: 連接:http://pan.baidu.com/s/1geLWBzP 密碼:2ko2

當前32位彙編全部課程資料:  連接:http://pan.baidu.com/s/1geC3iNL 密碼:0hpc

相關文章
相關標籤/搜索