精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

安全漏洞是如何造成的:緩沖區溢出

責任編輯:editor007

2015-09-08 17:40:45

摘自:51CTO

自1988年莫里斯蠕蟲誕生以來,緩沖區溢出漏洞就威脅著從Linux到Windows的各類系統環境。在計算機制發展的早期階段,處理器與操作系統使用的是物理內存地址:每個內存地址都會直接與RAM中的特定位置相對應。

自1988年莫里斯蠕蟲誕生以來,緩沖區溢出漏洞就威脅著從Linux到Windows的各類系統環境。

緩沖區溢出漏洞長久以來一直是計算機安全領域的一大特例。事實上,世界上首個能夠自我傳播的互聯網蠕蟲——誕生于1988年的莫里斯蠕蟲——就是通過Unix系統中的守護進程利用緩沖區溢出實現傳播的。而在二十七年后的今天,緩沖區溢出仍然在一系列安全隱患當中扮演著關鍵性角色。聲威顯赫的Windows家族就曾在2000年初遭遇過兩次基于緩沖區溢出的成規模安全侵襲。而就在今年5月,某款Linux驅動程序中遺留的潛在緩沖區溢出漏洞更是讓數百萬臺家庭及小型辦公區路由設備身陷風險之中。

安全漏洞是如何造成的:緩沖區溢出

但頗為諷刺的是,作為一種肆虐多年的安全隱患,緩沖區溢出漏洞的核心卻只是由一種實踐性結果衍生出的簡單bug。計算機程序會頻繁使用多組讀取自某個文件、網絡甚至是源自鍵盤輸入的數據。程序為這些數據分配一定量的內存塊——也就是緩沖區——作為存儲資源。而所謂緩沖區漏洞的產生原理就是,寫入或者讀取自特定緩沖區的數據總量超出了該緩沖區所能容納量的上限。

事實上,這聽起來像是一種相當愚蠢、毫無技術含量的錯誤。畢竟程序本身很清楚緩沖區的具體大小,因此我們似乎能夠很輕松地確保程序只向緩沖區發送不超出上限的數據量。這么想確實沒錯,但緩沖區溢出仍在不斷出現,并始終成為眾多安全攻擊活動的導火線。

為了了解緩沖區溢出問題的發生原因——以及為何其影響如此嚴重——我們需要首先談談程序是如何使用內存資源以及程序員是如何編寫代碼的。(需要注意的是,我們將以堆棧緩沖區溢出作為主要著眼對象。雖然這并不是惟一一種溢出問題,但卻擁有著典型性地位以及極高的知名度。)

堆疊起來

緩沖區溢出只會給原生代碼造成影響——也就是那些直接利用處理器指令集編寫而成的程序,而不會影響到利用Java或者Python等中間開發機制構建的代碼。不同操作系統有著自己的特殊處理方式,但目前各類常用系統平臺則普遍遵循基本一致的運作模式。要了解這些攻擊是如何出現的,進而著手阻止此類攻擊活動,我們首先要了解內存資源的使用機制。

在這方面,最重要的核心概念就是內存地址。內存當中每個獨立的字節都擁有一個與之對應的數值地址。當處理器從主內存(也就是RAM)中加載或者向其中寫稿數據時,它會利用內存地址來確定讀取或寫入所指向的位置。系統內存并不單純用于承載數據,它同時也被用于執行那些構建軟件的可執行代碼。這意味著處于運行中的程序,其每項功能都會擁有對應的地址。

在計算機制發展的早期階段,處理器與操作系統使用的是物理內存地址:每個內存地址都會直接與RAM中的特定位置相對應。盡管目前某些現代操作系統仍然會有某些組成部分繼續使用這類物理內存地址,但現在所有操作系統都會在廣義層面采用另一種機制——也就是虛擬內存。

在虛擬內存機制的幫助下,內存地址與RAM中物理位置直接對應的方式被徹底打破。相反,軟件與處理器會利用虛擬內存地址保證自身運轉。操作系統與處理器配合起來共同維護著一套虛擬機內存地址與物理內存地址之間的映射機制。

這種虛擬化方式帶來了一系列非常重要的特性。首先也是最重要的,即“受保護內存”。具體而言,每項獨立進程都擁有屬于自己的地址集合。對于一個32位進程而言,這部分對應地址從0開始(作為首個字節)一直到4294967295(在十六進制下表示為0xffff'ffff; 232 - 1)。而對于64位進程,其能夠使用的地址則進一步增加至18446744073709551615(十六進制中的0xffff'ffff'ffff'ffff, 264 - 1)。也就是說,每個進程都擁有自己的地址0,自己的地址1、地址2并以此類推。

(在文章的后續部分,除非另行強調,否則我將主要針對32位系統進行講解。其實32位與64位系統的工作機理是完全相同的,因此單獨著眼于前者不會造成任何影響,這只是為了盡量讓大家將注意力集中在單一對象身上。)

由于每個進程都擁有自己的一套地址,而這種規劃就以一種非常簡單的方式防止了不同進程之間相互干擾:一個進程所能使用的全部參考內存地址都將直接歸屬于該進程。在這種情況下,進程也能夠更輕松地完成對物理內存地址的管理。值得一提的是,雖然物理內存地址幾乎遵循同樣的工作原理(即以0為起始字節),但實際使用中可能帶來某些問題。舉例來說,物理內存地址通常是非連續的;地址0x1ff8'0000被用于處理器的系統管理模式,而另有一小部分物理內存地址會作為保留而無法被普通軟件所使用。除此之外,由PCIe卡提供的內存資源一般也要占用一部分地址空間。而在虛擬地址機制中,這些限制都將不復存在。

那么進程會在自己對應的地址空間中藏進什么小秘密呢?總體來講,大致有四種覺類別,我們會著重討論其中三種。這惟一一種不值得探討的也就是大多數操作系統所必不可少的“操作系統內核”。出于性能方面的考量,內存地址空間通常會被拆分為兩半,其中下半部分為程序所使用、上半部分由作為系統內核的專用地址空間。內核所占用的這一半內存無法訪問程序那一半的內容,但內核自身卻可以讀取程序內存,這也正是數據向內核功能傳輸的實現原理。

我們首先需要關注的就是構建程序的各類可執行代碼與庫。主可執行代碼及其全部配套庫都會被載入到對應進程的地址空間當中,而且所有組成部分都擁有自己的對應內存地址。

其次就是程序用于存儲自身數據的內存,這部分內存資源通常被稱為heap、也就是內存堆。舉例來說,內存堆可以用于存儲當前正在編輯的文檔、瀏覽的網頁(包括其中的全部JavaScript對象、CSS等等)或者當前游戲的地圖資源等等。

第三也是最重要的一項概念即call stack,即調用堆——也簡稱為棧。內存棧可以說是最復雜的相關概念了。進程中的每個分線程都擁有自己的內存棧。棧其實就是一個內存塊,用于追蹤某個線程當前正在運行的函數以及所有前趨函數——所謂前趨函數,是指那些當前函數需要調用的其它函數。舉例來說,如果函數a調用函數b,而函數b又調用函數c,那么棧內所包含的信息則依次為a、b和c。

安全漏洞是如何造成的:緩沖區溢出

在這里我們可以看到棧的基本布局,首先是名為name的64字符緩沖區,接下來依次為幀指針以及返回地址。esp擁有此內存棧的上半部分地址,ebp則擁有內存棧的下半部分地址。

調用堆棧屬于通用型“棧”數據結構的一個特殊版本。棧是一種用于存儲對象且大小可變的結構。新對象能夠被加入到(即’push‘)該棧的一端(一般為對應內存棧的’top‘端,即頂端),也可從棧中進行移除(即’pop’)。只有內存棧頂端的部分能夠通過push或者pop進行修改,因此棧會強制執行一種排序機制:最近添加進入的項目也會被首先移除。而首個添加進入的項目則會被最后移除。

調用堆棧最為重要的任務就是存儲返回地址。在大多數情況下,當一款程序調用某項函數時,該函數會按照既定設計發生作用(包括調用其它函數),并隨后返回至調用它的函數處。為了能夠切實返回至正確的調用函數,必須存在一套記錄系統來注明進行調用的源函數:即應當在函數調用指令執行之后從指令中恢復回來。這條指令所對應的地址就被稱為返回地址。棧用于維護這些返回地址,就是說每當有函數被調用時,返回地址都會被push到其內存棧當中。而在函數返回之后,對應返回地址則從內存棧中被移除,處理器隨后開始在該地址上執行指令。

棧的功能非常重要,甚至可以說是整個流程的核心所在,而處理器也會以內置方式支持這些處理概念。以x86處理器為例,在x86所定義的各個寄存器當中(所謂寄存器,是指處理器內的小型存儲位置,其能夠直接由處理器指令進行訪問),最為重要的兩類就是eip(即指令指針)以及esp(即棧指針)。

esp始終容納有棧頂端的對應地址。每一次有數據被添加到該棧中時,esp中的值都會降低。而每當有數據從棧中被移除時,esp的值則相應增加。這意味著該棧的值出現“下降”時,則代表有更多數據被添加到了該棧當中,而esp中的存儲地址則會不斷向下方移動。不過盡管如此,esp所使用的參考內存位置仍然被稱為該內存棧的“頂端”。

eip 為現有執行指令提供內存地址,而處理器則負責維護eip本身的正常運作。處理器會從內存當中根據eip增量讀取指令流,從而保證始終能夠獲得正確的指令地址。x86擁有一項用于函數調用的指令,名為call,另一項用于從函數處返回的指令則名為ret。

call 會獲取一個操作數,也就是欲調用函數的地址(當然,我們也可以利用其它方式來獲取欲調用函數的地址)。當執行call指令時,棧指針esp會通過4個字節(32位)來表現,而緊隨call之后的指令地址——也就是返回地址——則會被寫入至當前esp的參考內存位置。換句話說,返回地址會被添加至內存棧中。接下來,eip會將該地址指定為call的操作數,并以該地址為起始位置進行后續操作。

ret 的作用則完全相反。簡單的ret指令不會獲取任何操作數。處理器首先從esp當中的內存地址處讀取值,而后對esp進行4字節的數值增量——這意味著其將返回地址從內存棧中移除出去。這時eip接受值設定,并以此為起始位置進行后續操作。

鏈接已復制,快去分享吧

企業網版權所有?2010-2024 京ICP備09108050號-6京公網安備 11010502049343號

  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 乌兰县| 遂平县| 灯塔市| 汝南县| 西乌珠穆沁旗| 凉城县| 新晃| 山东| 松原市| 广德县| 洮南市| 搜索| 囊谦县| 剑河县| 龙海市| 准格尔旗| 潞城市| 芒康县| 广东省| 临泽县| 晋宁县| 微博| 广宗县| 汤原县| 阆中市| 昂仁县| 竹溪县| 成都市| 册亨县| 鄂州市| 怀安县| 礼泉县| 无棣县| 建水县| 寿光市| 读书| 东台市| 上高县| 襄樊市| 自贡市| 泸溪县|