32位組合語言學習筆記 19 緩衝區溢位實驗

2021-06-27 16:22:40 字數 4003 閱讀 5868



如下示例**,摘錄自《深入理解計算機系統》:

#include

#include

size_t strlen(const char *s)

char *strcpy(char *dest, const char *src)

while (c);

return result; }

char *getline()

int main(int argc, char *argv)

標黃色的**是有問題的,如果讀入的字元大於buf[8],會導致緩衝區溢位。

gcc -o1 -m32 -o bufovf bufovf.c

編譯時,gcc

會發出警告:

/tmp/ccwrmuor.o: in function `getline':

bufovf.c:(.text+0x56):warning: the `gets' function is dangerous and should not be used.

objdump-d bufovf

disassembly of section .plt: ……

080484d4 :

80484d4:      55                     push  %ebp

80484d5:      89 e5                  mov   %esp,%ebp

80484d7:      83 ec 28               sub   $0x28,%esp //esp = esp – 0x28

80484da:      89 5d f4               mov   %ebx,0xfffffff4(%ebp) //

備份ebx

80484dd:      89 75 f8               mov   %esi,0xfffffff8(%ebp) //

備份esi

80484e0:      89 7d fc               mov   %edi,0xfffffffc(%ebp) //

備份edi

80484e3:      8d 75 ec               lea   0xffffffec(%ebp),%esi //esi = buf

80484e6:      89 34 24               mov   %esi,(%esp) //

80484e9:      e8 76 fe ff ff         call  8048364 //

呼叫gets函式

80484ee:      89 f7                  mov   %esi,%edi //edi = esi

80484f0:      fc                     cld   //

清除df

標誌。

80484f1:      b9 ff ff ff ff         mov   $0xffffffff,%ecx //ecx = -1

80484f6:      b8 00 00 00 00         mov   $0x0,%eax //eax = 0

80484fb:      f2 ae                  repnz scas %es:(%edi),%al//

掃瞄buf

的內容,當尋找到

al的值(

0)時,掃瞄結束。

80484fd:      f7 d1                  not   %ecx//ecx取反

80484ff:      83 e9 01               sub   $0x1,%ecx //ecx = ecx -1

,得到buf

的長度。

8048502:      89 0c 24               mov   %ecx,(%esp)//

把長度作為入參儲存到棧中

8048505:      e8 8a fe ff ff         call  8048394 //

呼叫malloc

804850a:      89 c3                  mov   %eax,%ebx//result = eax,

儲存malloc

分配的記憶體位址

804850c:      89 74 24 04            mov   %esi,0x4(%esp) //esp+4 = buffer

,源記憶體位址

8048510:      89 04 24               mov   %eax,(%esp) //esp = result

,目的記憶體位址

8048513:      e8 9c ff ff ff         call  80484b4 //

呼叫strcpy函式

8048518:      89 d8                  mov   %ebx,%eax //eax = result

,作為返回值

804851a:      8b 5d f4               mov   0xfffffff4(%ebp),%ebx

804851d:      8b 75 f8               mov   0xfffffff8(%ebp),%esi

8048520:      8b 7d fc               mov   0xfffffffc(%ebp),%edi

8048523:      89 ec                  mov   %ebp,%esp

8048525:      5d                     pop   %ebp

8048526:      c3                     ret    ……

df

(direction flag

)標誌位於

eflags

暫存器第

10bit

位,控制字串指令(

movs,cmps, scas, lods

和stos

)。設定

df標誌位,會引起字串指令自減(從高位元組到低位元組處理),清除

df標誌位,會引起字串指令自增(從低位元組到高位元組處理)。

std指令:用於設定

df標誌位。

cld指令:用於清除

df標誌位。

repnz

指令:當

ecx暫存器不是

0值時並且

zf標誌位是

0時迴圈。

scas

指令:掃瞄字串,與

repnz

聯合使用,每迴圈一次,

ecx減1。

es是段暫存器,儲存的是附加段(extra segment)的段號。

edi裝載的是

buf的位址偏移,通過

%es:(%edi)

,計算出

buf的虛擬記憶體位址(根據段號算出段起始位址,再加上edi儲存的位址偏移值),讀取buf的內容。

下圖是getline函式呼叫gets(buf);前的呼叫棧:

從圖中可以看出,如果gets函式寫buf超過8個位元組,就會導致緩衝區溢位,從而破壞棧上儲存的資料。

如果輸入的位元組小於等於23(加上字串結尾的0,小於等於24個位元組),破壞儲存包括ebp在內的幾個暫存器的儲存值,程式還能執行:

./bufovf

input>helloworld1234567890$$$

helloworld1234567890$$$

當輸入的位元組數達到24個(加上字串結尾的0,實際上是25個位元組),不僅破壞掉了舊ebp值,還破壞了函式的返回位址,程式崩潰:

./bufovf

input>helloworld1234567890$$$$

segmentation fault



32位組合語言學習筆記 4 移位操作

sal k,d d d k 左移。shl,與 sal相同。sar k,d d d k 算術右移。shr k,d d d l k 邏輯右移。算術右移是指左邊空出來的位填符號位。邏輯右移是指左邊空出來的位填0。示例 shift.c int shift left2 rightn int x,int n g...

32位組合語言學習筆記 6 設定條件碼

條件碼儲存在條件碼暫存器中,用於描述算術和最近邏輯操作的屬性。最常用的條件碼有 cf 進製標誌。zf 零標誌。sf 符號標誌。of 溢位標誌。算術和邏輯操作指令都會修改條件碼的值,但是 leal 指令不會修改條件碼的值。此外,cmp 指令和test 指令也會修改條件碼。cmp s2,s1 將s1 s...

組合語言學習筆記

學習參考資料 大灰狼 講彙編 資料匯流排,位址匯流排,控制匯流排。位址匯流排有多少條就決定了cpu最大的記憶體使用量。80386有32位位址匯流排,所以它的定址能力就是4g.暫存器 通用暫存器,段暫存器,ax暫存器 通用暫存器,存放資料。高位位元組ah,低位位元組al。實體地址表示方法 位址加法器,...