自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

常見(jiàn)緩沖區(qū)溢出函數(shù)

開(kāi)發(fā) 開(kāi)發(fā)工具
C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的許多字符串處理和IO流讀取函數(shù)是導(dǎo)致緩沖區(qū)溢出的罪魁禍?zhǔn)住N覀冇斜匾私膺@些函數(shù),在編程中多加小心。

C 和 C++ 不能夠自動(dòng)地做邊界檢查,邊界檢查的代價(jià)是效率。一般來(lái)講,C 在大多數(shù)情況下注重效率。然而,獲得效率的代價(jià)是,C 程序員必須十分警覺(jué)以避免緩沖區(qū)溢出問(wèn)題。

[[181110]]

C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的許多字符串處理和IO流讀取函數(shù)是導(dǎo)致緩沖區(qū)溢出的罪魁禍?zhǔn)?。我們有必要了解這些函數(shù),在編程中多加小心。

一、字符串處理函數(shù)

1. strcpy()

strcpy()函數(shù)將源字符串復(fù)制到緩沖區(qū)。沒(méi)有指定要復(fù)制字符的具體數(shù)目!如果源字符串碰巧來(lái)自用戶(hù)輸入,且沒(méi)有專(zhuān)門(mén)限制其大小,則有可能會(huì)造成緩沖區(qū)溢出!

我們也可以使用strncpy來(lái)完成同樣的目的:

  1. strncpy(dst, src, dst_size-1); 

如果 src 比 dst 大,則該函數(shù)不會(huì)拋出一個(gè)錯(cuò)誤;當(dāng)達(dá)到最大尺寸時(shí),它只是停止復(fù)制字符。注意上面調(diào)用 strncpy() 中的 -1。如果 src 比 dst 長(zhǎng),則那給我們留有空間,將一個(gè)空字符放在 dst 數(shù)組的末尾。

但是! strncpy()也不完全安全,也有可能把事情搞糟。即使“安全”的調(diào)用有時(shí)會(huì)留下未終止的字符串,或者會(huì)發(fā)生微妙的相差一位錯(cuò)誤。

確保 strcpy() 不會(huì)溢出的另一種方式是,在需要它時(shí)就分配空間,確保通過(guò)在源字符串上調(diào)用 strlen() 來(lái)分配足夠的空間。

  1. dst = (char *)malloc(strlen(src));   
  2. strcpy(dst, src); 

2. strcat()

strcat()函數(shù)非常類(lèi)似于 strcpy(),除了它可以將一個(gè)字符串合并到緩沖區(qū)末尾。它也有一個(gè)類(lèi)似的、更安全的替代方法 strncat()。如果可能,使用 strncat() 而不要使用 strcat()。

3. sprintf()、vsprintf()

函數(shù) sprintf()和 vsprintf()是用來(lái)格式化文本和將其存入緩沖區(qū)的通用函數(shù)。它們可以用直接的方式模仿 strcpy() 行為。換句話(huà)說(shuō),使用 sprintf() 和 vsprintf() 與使用 strcpy() 一樣,都很容易對(duì)程序造成緩沖區(qū)溢出。

sprintf() 的許多版本帶有使用這種函數(shù)的更安全的方法??梢灾付ǜ袷阶址旧砻總€(gè)自變量的精度。sprintf 采用”*”來(lái)占用一個(gè)本來(lái)需要一個(gè)指定寬度或精度的常數(shù)數(shù)字的位置,而實(shí)際的寬度或精度就可以和其它被打印的變量一樣被提供出來(lái)。

例如:

  1. sprintf(usage, "USAGE: %*s\n", BUF_SIZE, argv[0]); 

二、字符讀取函數(shù)

1. gets()

永遠(yuǎn)不要使用 gets()。該函數(shù)從標(biāo)準(zhǔn)輸入讀入用戶(hù)輸入的一行文本,它在遇到 EOF 字符或換行字符之前,不會(huì)停止讀入文本。也就是:gets() 根本不執(zhí)行邊界檢查。因此,使用 gets() 總是有可能使任何緩沖區(qū)溢出。

作為一個(gè)替代方法,可以使用方法 fgets()。它可以做與 gets() 所做的同樣的事情,但它接受用來(lái)限制讀入字符數(shù)目的大小參數(shù),因此,提供了一種防止緩沖區(qū)溢出的方法。

2. getchar()、fgetc()、getc()、read()

如果在循環(huán)中使用這些函數(shù),確保檢查緩沖區(qū)邊界

3. scanf()系列

sscanf()、fscanf()、vfscanf()、vscanf()、vsscanf()

scanf系列的函數(shù)也設(shè)計(jì)得很差。目的地緩沖區(qū)也可能會(huì)發(fā)生溢出。

同樣地,我們用設(shè)置寬度也可以解決這個(gè)問(wèn)題。

4. getenv()

使用系統(tǒng)調(diào)用getenv() 的最大問(wèn)題是您從來(lái)不能假定特殊環(huán)境變量是任何特定長(zhǎng)度的。

三、使用安全版本的代碼庫(kù)

微軟對(duì)于有緩沖溢出危險(xiǎn)的API使用其開(kāi)發(fā)的安全版本的庫(kù)來(lái)替代。

SafeCRT自Visual Studio 2005起開(kāi)始支持。當(dāng)代碼中使用了禁用的危險(xiǎn)的CRT函數(shù),Visual Studio 2005編譯時(shí)會(huì)報(bào)告相應(yīng)警告信息,以提醒開(kāi)發(fā)人員考慮將其替代為Safe CRT中更為安全。

1. 有關(guān)字符串拷貝的API

    例如:strcpy, wcscpy等

    替代的Safe CRT函數(shù):strcpy_s

2. 有關(guān)字符串合并的API

    例如:strcat, wcscat等

    替代的Safe CRT函數(shù):strcat_s

3. 有關(guān)sprintf的API

    例如:sprintf, swprintf等

    替代的Safe CRT函數(shù):

  1. _snprintf_s  
  2. _snwprintf_s 

其它被禁用的API還有scanf, strtok, gets, itoa等等。 ”n”系列的字符串處理函數(shù),例如strncpy等,也在被禁用之列。

舉個(gè)栗子

破解下面的密碼防護(hù)代碼:

  1. #include <stdio.h>int main(int argc, char *argv[]) 
  2.     int flag = 0
  3.     char passwd[10]; 
  4.  
  5.     memset(passwd,0,sizeof(passwd)); 
  6.     strcpy(passwd, argv[1]); 
  7.      if(0 == strcmp("LinuxGeek", passwd)) 
  8.     { 
  9.         flag = 1
  10.     } 
  11.  
  12.     if(flag) 
  13.     { 
  14.         printf("\n Password cracked \n"); 
  15.     } 
  16.     else    { 
  17.         printf("\n Incorrect passwd \n"); 
  18.     } 
  19.     return 0; 

如果把命令行輸入的文字當(dāng)作密碼的話(huà),會(huì)有很大的漏洞:

首先如果我輸入11個(gè)字符且最后一個(gè)字符是大于0的話(huà),就慘了,strcpy是要copy到’/0’的。他會(huì)一直把這11個(gè)字符都copy到passwd數(shù)組中,此時(shí)數(shù)組越界了,最后一個(gè)字符就把flag標(biāo)志位個(gè)賦值了,if條件就滿(mǎn)足了,密碼就被破解了!

經(jīng)過(guò)上面我們的討論,我們可以對(duì)用戶(hù)輸入動(dòng)態(tài)分配同樣大小的空間,而不是提前分配固定的空間。

  1. passwd = (char *)malloc(strlen(argv[1]));  
  2.  
  3. strcpy(passwd, argv[1]);  

注意:

不要用strncpy(),它會(huì)造成最后一位的丟失,造成隱藏的錯(cuò)誤。

四、關(guān)于緩沖區(qū)溢出問(wèn)題

由于函數(shù)調(diào)用棧頭部會(huì)保存其調(diào)用者棧的基地址%ebp,如果破壞了存儲(chǔ)%ebp的值,那么基址寄存器就不能正確地恢復(fù),因此調(diào)用者就不能正確地引用它的局部變量或參數(shù)。

如果破壞了存儲(chǔ)的返回地址,那么ret指令會(huì)使程序跳轉(zhuǎn)到完全意想不到的地方。

緩沖區(qū)溢出的一個(gè)更加致命的使用就是讓程序執(zhí)行它本來(lái)不愿意執(zhí)行的函數(shù)。這是一種最常見(jiàn)的通過(guò)計(jì)算機(jī)網(wǎng)絡(luò)攻擊系統(tǒng)安全的方法。通常,輸入給程序一個(gè)字符串,這個(gè)字符串包含一些可執(zhí)行代碼的字節(jié)編碼,稱(chēng)為攻擊代碼,另外還有一些字節(jié)會(huì)用一個(gè)指向攻擊代碼的指針覆蓋返回地址。那么,執(zhí)行ret指令的效果就是跳轉(zhuǎn)到攻擊代碼。

五、對(duì)抗緩沖區(qū)溢出攻擊

1. 棧隨機(jī)化

為了在系統(tǒng)中插入攻擊代碼,攻擊者不但要插入代碼,還要插入指向這段代碼的指針,這個(gè)指針也是攻擊字符串的一部分。產(chǎn)生這個(gè)指針需要知道這個(gè)字符串放置的棧地址。在過(guò)去,程序的棧地址非常容易預(yù)測(cè),在不同的機(jī)器之間,棧的位置是相當(dāng)固定的。

棧隨機(jī)化的思想使得棧的位置在程序每次運(yùn)行時(shí)都有變化。因此,即使許多機(jī)器都運(yùn)行相同的代碼。它們的棧地址都是不同的。

實(shí)現(xiàn)的方式是:程序開(kāi)始時(shí),在棧上分配一段0--n字節(jié)之間的隨機(jī)大小空間。程序不使用這段空間,但是它會(huì)導(dǎo)致程序每次執(zhí)行時(shí)后續(xù)的棧位置發(fā)生了變化。

在Linux系統(tǒng)中,棧隨機(jī)化已經(jīng)變成了標(biāo)準(zhǔn)行為。(在linux上每次運(yùn)行相同的程序,其同一局部變量的地址都不相同)

2. 棧破壞檢測(cè)

在C語(yǔ)言中,沒(méi)有可靠的方法來(lái)防止對(duì)數(shù)組的越界寫(xiě),但是,我們能夠在發(fā)生了越界寫(xiě)的時(shí)候,在沒(méi)有造成任何有害結(jié)果之前,嘗試檢測(cè)到它。

最近的GCC版本在產(chǎn)生的代碼中加入了一種棧保護(hù)者機(jī)制,用來(lái)檢測(cè)緩沖區(qū)越界,其思想是在棧中任何局部緩沖區(qū)與棧狀態(tài)之間存儲(chǔ)一個(gè)特殊的金絲雀值。這個(gè)金絲雀值是在程序每次運(yùn)行時(shí)隨機(jī)產(chǎn)生的,因此,攻擊者沒(méi)有簡(jiǎn)單的辦法知道它是什么。

在恢復(fù)寄存器狀態(tài)和從函數(shù)返回之前,程序檢查這個(gè)金絲雀值是否被該函數(shù)的某個(gè)操作或者函數(shù)調(diào)用的某個(gè)操作改變了。如果是,那么程序異常終止。

3. 限制可執(zhí)行代碼區(qū)域

限制那些能夠存放可執(zhí)行代碼的存儲(chǔ)器區(qū)域。在典型的程序中,只有保存編譯器產(chǎn)生的代碼的那部分存儲(chǔ)器才需要是可執(zhí)行的,其他部分可以被限制為只允許讀和寫(xiě)。

現(xiàn)在的64位處理器的內(nèi)存保護(hù)引入了”NX”(不執(zhí)行)位。有了這個(gè)特性,??梢员粯?biāo)記為可讀和可寫(xiě),但是不可執(zhí)行,檢查頁(yè)是否可執(zhí)行由硬件來(lái)完成,效率上沒(méi)有損失。

【本文是51CTO專(zhuān)欄作者elknot的原創(chuàng)文章,轉(zhuǎn)載請(qǐng)通過(guò)51CTO獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專(zhuān)欄
相關(guān)推薦

2019-02-27 13:58:29

漏洞緩沖區(qū)溢出系統(tǒng)安全

2018-01-26 14:52:43

2022-08-09 08:31:40

C -gets函數(shù)漏洞

2014-07-30 11:21:46

2009-09-24 18:16:40

2010-12-27 10:21:21

2010-09-08 15:43:18

2011-03-23 12:39:44

2018-11-01 08:31:05

2011-11-15 16:00:42

2022-05-07 08:27:42

緩沖區(qū)溢出堆棧

2010-10-09 14:45:48

2015-03-06 17:09:10

2020-08-10 08:37:32

漏洞安全數(shù)據(jù)

2011-03-23 11:35:00

2015-09-02 09:01:03

2010-09-29 15:10:58

2019-01-11 09:00:00

2020-10-27 09:51:18

漏洞

2009-05-13 09:21:48

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)