新聞中心
什么是C語言緩沖區(qū)溢出漏洞?怎么利用?誰可以提供詳細的資料
緩沖區(qū)溢出漏洞入門介紹
成都創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站設計、網(wǎng)站建設與策劃設計,名山網(wǎng)站建設哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設10多年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:名山等地區(qū)。名山做網(wǎng)站價格咨詢:18982081108
文/hokersome
一、引言
不管你是否相信,幾十年來,緩沖區(qū)溢出一直引起許多嚴重的安全性問題。甚至毫不夸張的說,當前網(wǎng)絡種種安全問題至少有50%源自緩沖區(qū)溢出的問題。遠的不說,一個沖擊波病毒已經令人談溢出色變了。而作為一名黑客,了解緩沖區(qū)溢出漏洞則是一門必修課。網(wǎng)上關于溢出的漏洞的文章有很多,但是大多太深或者集中在一個主題,不適合初學者做一般性了解。為此,我寫了這篇文章,主要是針對初學者,對緩沖區(qū)溢出漏洞進行一般性的介紹。
緩沖區(qū)溢出漏洞是之所以這么多,是在于它的產生是如此的簡單。只要C/C++程序員稍微放松警惕,他的代碼里面可能就出現(xiàn)了一個緩沖區(qū)溢出漏洞,甚至即使經過仔細檢查的代碼,也會存在緩沖區(qū)溢出漏洞。
二、溢出
聽我說了這些廢話,你一定很想知道究竟什么緩沖區(qū)溢出漏洞,溢出究竟是怎么發(fā)生的。好,現(xiàn)在我們來先弄清楚什么是溢出。以下的我將假設你對C語言編程有一點了解,一點點就夠了,當然,越多越好。
盡管緩沖區(qū)溢出也會發(fā)生在非C/C++語言上,但考慮到各種語言的運用程度,我們可以在某種程度上說,緩沖區(qū)溢出是C/C++的專利。相信我,如果你在一個用VB寫的程序里面找溢出漏洞,你將會很出名。回到說C/C++,在這兩種使用非常廣泛的語言里面,并沒有邊界來檢查數(shù)組和指針的引用,這樣做的目的是為了提高效率,而不幸的是,這也留下了嚴重的安全問題。先看下面一段簡單的代碼:
#includestdio.h
void main()
{
char buf[8];
gets(buf);
}
程序運行的時候,如果你輸入“Hello”,或者“Kitty”,那么一切正常,但是如果輸入“Today is a good day”,那么我得通知你,程序發(fā)生溢出了。很顯然,buf這個數(shù)組只申請到8個字節(jié)的內存空間,而輸入的字符卻超過了這個數(shù)目,于是,多余的字符將會占領程序中不屬于自己的內存。因為C/C++語言并不檢查邊界,于是,程序將看似正常繼續(xù)運行。如果被溢出部分占領的內存并不重要,或者是一塊沒有使用的內存,那么,程序將會繼續(xù)看似正常的運行到結束。但是,如果溢出部分占領的正好的是存放了程序重要數(shù)據(jù)的內存,那么一切將會不堪設想。
實際上,緩沖區(qū)溢出通常有兩種,堆溢出和堆棧溢出。盡管兩者實質都是一樣,但由于利用的方式不同,我將在下面分開介紹。不過在介紹之前,還是來做一些必要的知識預備。
三、知識預備
要理解大多數(shù)緩沖區(qū)溢出的本質,首先需要理解當程序運行時機器中的內存是如何分配的。在許多系統(tǒng)上,每個進程都有其自己的虛擬地址空間,它們以某種方式映射到實際內存。我們不必關心描述用來將虛擬地址空間映射成基本體系結構的確切機制,而只關心理論上允許尋址大塊連續(xù)內存的進程。
程序運行時,其內存里面一般都包含這些部分:1)程序參數(shù)和程序環(huán)境;2)程序堆棧,它通常在程序執(zhí)行時增長,一般情況下,它向下朝堆增長。3)堆,它也在程序執(zhí)行時增長,相反,它向上朝堆棧增長;4)BSS 段,它包含未初始化的全局可用的數(shù)據(jù)(例如,全局變量); 5)數(shù)據(jù)段,它包含初始化的全局可用的數(shù)據(jù)(通常是全局變量);6)文本段,它包含只讀程序代碼。BSS、數(shù)據(jù)和文本段組成靜態(tài)內存:在程序運行之前這些段的大小已經固定。程序運行時雖然可以更改個別變量,但不能將數(shù)據(jù)分配到這些段中。下面以一個簡單的例子來說明以上的看起來讓人頭暈的東西:
#includestdio.h
char buf[3]="abc";
int i;
void main()
{
i=1
return;
}
其中,i屬于BBS段,而buf屬于數(shù)據(jù)段。兩者都屬于靜態(tài)內存,因為他們在程序中雖然可以改變值,但是其分配的內存大小是固定的,如buf的數(shù)據(jù)大于三個字符,將會覆蓋其他數(shù)據(jù)。
與靜態(tài)內存形成對比,堆和堆棧是動態(tài)的,可以在程序運行的時候改變大小。堆的程序員接口因語言而異。在C語言中,堆是經由 malloc() 和其它相關函數(shù)來訪問的,而C++中的new運算符則是堆的程序員接口。堆棧則比較特殊,主要是在調用函數(shù)時來保存現(xiàn)場,以便函數(shù)返回之后能繼續(xù)運行。
四、堆溢出
堆溢出的思路很簡單,覆蓋重要的變量以達到自己的目的。而在實際操作的時候,這顯得比較困難,尤其是源代碼不可見的時候。第一,你必須確定哪個變量是重要的變量;第二,你必須找到一個內存地址比目標變量低的溢出點;第三,在特定目的下,你還必須讓在為了覆蓋目標變量而在中途覆蓋了其他變量之后,程序依然能運行下去。下面以一個源代碼看見的程序來舉例演示一次簡單的堆溢出是如何發(fā)生的:
#include "malloc.h"
#include "string.h"
#include "stdio.h"
void main()
{
char *large_str = (char *)malloc(sizeof(char)*1024);
char *important = (char *)malloc(sizeof(char)*6);
char *str = (char *)malloc(sizeof(char)*4);
strcpy(important,"abcdef");//給important賦初值
//下面兩行代碼是為了看str和important的地址
printf("%d/n",str);
printf("%d/n",important);
gets(large_str);//輸入一個字符串
strcpy(str, large_str);//代碼本意是將輸入的字符串拷貝到str
printf("%s/n",important);
}
在實際應用中,這樣的代碼當然是不存在的,這只是一個最簡單的實驗程序。現(xiàn)在我們的目標是important這個字符串變成"hacker"。str和important的地址在不同的環(huán)境中并不是一定的,我這里是7868032和7868080。很好,important的地址比str大,這就為溢出創(chuàng)造了可能。計算一下可以知道,兩者中間隔了48個字節(jié),因此在輸入溢出字符串時候,可以先輸入48個任意字符,然后再輸入hakcer回車,哈哈,出來了,important成了"hacker"。
五、堆棧溢出
堆溢出的一個關鍵問題是很難找到所謂的重要變量,而堆棧溢出則不存在這個問題,因為它將覆蓋一個非常重要的東西----函數(shù)的返回地址。在進行函數(shù)調用的時候,斷點或者說返回地址將保存到堆棧里面,以便函數(shù)結束之后繼續(xù)運行。而堆棧溢出的思路就是在函數(shù)里面找到一個溢出點,把堆棧里面的返回地址覆蓋,替換成一個自己指定的地方,而在那個地方,我們將把一些精心設計了的攻擊代碼。由于攻擊代碼的編寫需要一些匯編知識,這里我將不打算涉及。我們這里的目標是寫出一個通過覆蓋堆棧返回地址而讓程序執(zhí)行到另一個函數(shù)的堆棧溢出演示程序。
因為堆棧是往下增加的,因此,先進入堆棧的地址反而要大,這為在函數(shù)中找到溢出點提供了可能。試想,而堆棧是往上增加的,我們將永遠無法在函數(shù)里面找到一個溢出點去覆蓋返回地址。還是先從一個最簡單的例子開始:
void test(int i)
{
char buf[12];
}
void main()
{
test(1);
}
test 函數(shù)具有一個局部參數(shù)和一個靜態(tài)分配的緩沖區(qū)。為了查看這兩個變量所在的內存地址(彼此相對的地址),我們將對代碼略作修改:
void test(int i)
{
char buf[12];
printf("i = %d/n", i);
printf("buf[0] = %d/n", buf);
}
void main()
{
test(1);
}
需要說明的是,由于個人習慣的原因,我把地址結果輸出成10進制形式,但愿這并不影響文章的敘述。在我這里,產生下列輸出:i = 6684072 buf[0] = 6684052。這里我補充一下,當調用一個函數(shù)的時候,首先是參數(shù)入棧,然后是返回地址。并且,這些數(shù)據(jù)都是倒著表示的,因為返回地址是4個字節(jié),所以可以知道,返回地址應該是保存在從6684068到6684071。因為數(shù)據(jù)是倒著表示的,所以實際上返回地址就是:buf[19]*256*256*256+buf[18]*256*256+buf[17]*256+buf[16]。
我們的目標還沒有達到,下面我們繼續(xù)。在上面程序的基礎,修改成:
#include stdio.h
void main()
{
void test(int i);
test(1);
}
void test(int i)
{
void come();
char buf[12];//用于發(fā)生溢出的數(shù)組
int addr[4];
int k=(int)i-(int)buf;//計算參數(shù)到溢出數(shù)組之間的距離
int go=(int)come;
//由于EIP地址是倒著表示的,所以首先把come()函數(shù)的地址分離成字節(jié)
addr[0]=(go 24)24;
addr[1]=(go 16)24;
addr[2]=(go 8)24;
addr[3]=go24;
//用come()函數(shù)的地址覆蓋EIP
for(int j=0;j4;j++)
{
buf[k-j-1]=addr[3-j];
}
}
void come()
{
printf("Success!");
}
一切搞定!運行之后,"Success!"成功打印出來!不過,由于這個程序破壞了堆棧,所以系統(tǒng)會提示程序遇到問題需要關閉。但這并不要緊,因為至少我們已經邁出了萬里長征的第一步。
錯誤提示
我來解釋下.
運行某些程序的時候,有時會出現(xiàn)內存錯誤的提示,然后該程序就關閉。
“0x????????”指令引用的“0x????????”內存。該內存不能為“read”。
“0x????????”指令引用的“0x????????”內存,該內存不能為“written”。
以上的情況相信大家都應該見到過,甚至說一些網(wǎng)友因為不爽于這個經常出現(xiàn)的錯誤提示而屢次重裝系統(tǒng)。相信普通用戶應該不會理解那些復雜的十六進制代碼。
出現(xiàn)這個現(xiàn)象有方面的,一是硬件,即內存方面有問題,二是軟件,這就有多方面的問題了。
一:先說說硬件:
一般來說,電腦硬件是很不容易壞的。內存出現(xiàn)問題的可能性并不大(除非你的內存真的是雜牌的一塌徒地),主要方面是:1。內存條壞了(二手內存情況居多)、2。使用了有質量問題的內存,3。內存插在主板上的金手指部分灰塵太多。4。使用不同品牌不同容量的內存,從而出現(xiàn)不兼容的情況。5。超頻帶來的散熱問題。你可以使用MemTest 這個軟件來檢測一下內存,它可以徹底的檢測出內存的穩(wěn)定度。
二、如果都沒有,那就從軟件方面排除故障了。
先說原理:內存有個存放數(shù)據(jù)的地方叫緩沖區(qū),當程序把數(shù)據(jù)放在緩沖區(qū),需要操作系統(tǒng)提供的“功能函數(shù)”來申請,如果內存分配成功,函數(shù)就會將所新開辟的內存區(qū)地址返回給應用程序,應用程序就可以通過這個地址使用這塊內存。這就是“動態(tài)內存分配”,內存地址也就是編程中的“光標”。內存不是永遠都招之即來、用之不盡的,有時候內存分配也會失敗。當分配失敗時系統(tǒng)函數(shù)會返回一個0值,這時返回值“0”已不表示新啟用的光標,而是系統(tǒng)向應用程序發(fā)出的一個通知,告知出現(xiàn)了錯誤。
作為應用程序,在每一次申請內存后都應該檢查返回值是否為0,如果是,則意味著出現(xiàn)了故障,應該采取一些措施挽救,這就增強了程序的“健壯性”。若應用程序沒有檢查這個錯誤,它就會按照“思維慣性”認為這個值是給它分配的可用光標,繼續(xù)在之后的執(zhí)行中使用這塊內存。真正的0地址內存區(qū)儲存的是計算機系統(tǒng)中最重要的“中斷描述符表”,絕對不允許應用程序使用。在沒有保護機制的操作系統(tǒng)下(如DOS),寫數(shù)據(jù)到這個地址會導致立即當機,而在健壯的操作系統(tǒng)中,如Windows等,這個操作會馬上被系統(tǒng)的保護機制捕獲,其結果就是由操作系統(tǒng)強行關閉出錯的應用程序,以防止其錯誤擴大。這時候,就會出現(xiàn)上述的內存不能為“read”錯誤,并指出被引用的內存地址為“0x00000000“。
內存分配失敗故障的原因很多,內存不夠、系統(tǒng)函數(shù)的版本不匹配等都可能有影響。因此,這種分配失敗多見于操作系統(tǒng)使用很長時間后,安裝了多種應用程序(包括無意中“安裝”的病毒程序),更改了大量的系統(tǒng)參數(shù)和系統(tǒng)檔案之后。
在使用動態(tài)分配的應用程序中,有時會有這樣的情況出現(xiàn):程序試圖讀寫一塊“應該可用”的內存,但不知為什么,這個預料中可用的光標已經失效了。有可能是“忘記了”向操作系統(tǒng)要求分配,也可能是程序自己在某個時候已經注銷了這塊內存而“沒有留意”等等。注銷了的內存被系統(tǒng)回收,其訪問權已經不屬于該應用程序,因此讀寫操作也同樣會觸發(fā)系統(tǒng)的保護機制,企圖“違法”的程序唯一的下場就是被操作終止執(zhí)行,回收全部資源。計算機世界的法律還是要比人類有效和嚴厲得多啊!像這樣的情況都屬于程序自身的BUG,你往往可在特定的操作順序下重現(xiàn)錯誤。無效光標不一定總是0,因此錯誤提示中的內存地址也不一定為“0x00000000”,而是其它隨機數(shù)字。
首先建議:
1、 檢查系統(tǒng)中是否有木馬或病毒。這類程序為了控制系統(tǒng)往往不負責任地修改系統(tǒng),從而導致操作系統(tǒng)異常。平常應加強信息安全意識,對來源不明的可執(zhí)行程序絕不好奇。
2、 更新操作系統(tǒng),讓操作系統(tǒng)的安裝程序重新拷貝正確版本的系統(tǒng)檔案、修正系統(tǒng)參數(shù)。有時候操作系統(tǒng)本身也會有BUG,要注意安裝官方發(fā)行的升級程序。
3、 盡量使用最新正式版本的應用程序、Beta版、試用版都會有BUG。
4、 刪除然后重新創(chuàng)建 Winnt\System32\Wbem\Repository 文件夾中的文件:在桌面上右擊我的電腦,然后單擊管理。 在"服務和應用程序"下,單擊服務,然后關閉并停止 Windows Management Instrumentation 服務。 刪除 Winnt\System32\Wbem\Repository 文件夾中的所有文件。(在刪除前請創(chuàng)建這些文件的備份副本。) 打開"服務和應用程序",單擊服務,然后打開并啟動 Windows Management Instrumentation 服務。當服務重新啟動時,將基于以下注冊表項中所提供的信息重新創(chuàng)建這些文件: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\Autorecover MOFs
內存錯誤不能讀寫完全解決方案
運行某些程序的時候,有時會出現(xiàn)內存錯誤的提示,然后該程序就關閉。 “0x????????”指令引用的“0x????????”內存。該內存不能為“read”。
“0x????????”指令引用的“0x????????”內存,該內存不能為“written”。
不知你出現(xiàn)過類似這樣的故障嗎?(0x后面內容有可能不一樣。)
一般出現(xiàn)這個現(xiàn)象有方面的,一是硬件,即內存方面有問題,二是軟件,這就有多方面的問題了。
下面先說說硬件:
一般來說,內存出現(xiàn)問題的可能性并不大,主要方面是:內存條壞了、內存質量有問題,還有就是2個不同牌子不同容量的內存混插,也比較容易出現(xiàn)不兼容的情況,同時還要注意散熱問題,特別是超頻后。你可以使用MemTest 這個軟件來檢測一下內存,它可以徹底的檢測出內存的穩(wěn)定度。
假如你是雙內存,而且是不同品牌的內存條混插或者買了二手內存時,出現(xiàn)這個問題,這時,你就要檢查是不是內存出問題了或者和其它硬件不兼容。
如果都沒有,那就從軟件方面排除故障了。
先簡單說說原理:內存有個存放數(shù)據(jù)的地方叫緩沖區(qū),當程序把數(shù)據(jù)放在其一位置時,因為沒有足夠空間,就會發(fā)生溢出現(xiàn)象。舉個例子:一個桶子只能將一斤的水,當你放入兩斤的水進入時,就會溢出來。而系統(tǒng)則是在屏幕上表現(xiàn)出來。這個問題,經常出現(xiàn)在windows2000和XP系統(tǒng)上,Windows 2000/XP對硬件的要求是很苛刻的,一旦遇到資源死鎖、溢出或者類似Windows 98里的非法操作,系統(tǒng)為保持穩(wěn)定,就會出現(xiàn)上述情況。另外也可能是硬件設備之間的兼容性不好造成的。
下面我從幾個例子給大家分析:
例一:打開IE瀏覽器或者沒過幾分鐘就會出現(xiàn)\"0x70dcf39f\"指令引用的\"0x00000000\"內存。該內存不能為“read”。要終止程序,請單擊“確定”的信息框,單擊“確定”后,又出現(xiàn)“發(fā)生內部錯誤,您正在使用的其中一個窗口即將關閉”的信息框,關閉該提示信息后,IE瀏覽器也被關閉。 解決方法:修復或升級IE瀏覽器,同時打上補丁。看過其中一個修復方法是,Win2000自升級,也就是Win2000升級到Win2000,其實這種方法也就是把系統(tǒng)還原到系統(tǒng)初始的狀態(tài)下。比如你的IE升級到了6.0,自升級后,會被IE5.0代替。
例二:在windows xp下雙擊光盤里面的“AutoRun.exe”文件,顯示“0x77f745cc”指令引用的“0x00000078”內存。該內存不能為“written”,要終止程序,請單擊“確定”,而在Windows 98里運行卻正常。 解決方法:這可能是系統(tǒng)的兼容性問題,winXP的系統(tǒng),右鍵“AutoRun.exe”文件,屬性,兼容性,把“用兼容模式運行這個程序”項選擇上,并選擇“Windows 98/Me”。win2000如果打了SP的補丁后,只要開始,運行,輸入:regsvr32 c:\\winnt\\apppatch\\slayerui.dll。右鍵,屬性,也會出現(xiàn)兼容性的選項。
例三:RealOne Gold關閉時出現(xiàn)錯誤,以前一直使用正常,最近卻在每次關閉時出現(xiàn)“0xffffffff”指令引用的“0xffffffff”內存。該內存不能為“read” 的提示。 解決方法:當使用的輸入法為微軟拼音輸入法2003,并且隱藏語言欄時(不隱藏時沒問題)關閉RealOne就會出現(xiàn)這個問題,因此在關閉RealOne之前可以顯示語言欄或者將任意其他輸入法作為當前輸入法來解決這個問題。
例四:我的豪杰超級解霸自從上網(wǎng)后就不能播放了,每次都提示“Ox060692f6”(每次變化)指令引用的“Oxff000011”內存不能為“read”,終止程序請按確定。 解決方法:試試重裝豪杰超級解霸,如果重裝后還會,到官方網(wǎng)站下載相應版本的補丁試試。還不行,只好換就用別的播放器試試了。
例五:雙擊一個游戲的快捷方式,“Ox77f5cdO”指令引用“Oxffffffff”內 存,該內存不能為“read” ,并且提示Client.dat程序錯誤。 解決方法:重裝顯卡的最新驅動程序,然后下載并且安裝DirectX9.0。
例六:一個朋友發(fā)信息過來,我的電腦便出現(xiàn)了錯誤信息:“0*772b548f”指令引用的“0*00303033”內存,該內存不能為“written”,然后QQ自動下線,而再打開QQ,發(fā)現(xiàn)了他發(fā)過來的十幾條的信息。 解決方法:這是對方利用QQ的BUG,發(fā)送特殊的代碼,做QQ出錯,只要打上補丁或升級到最新版本,就沒事了。
如果將計算機上分頁文件Pagefile.sys的大小設置為小于系統(tǒng)推薦的大小加上物理內存的總和,這時系統(tǒng)可能創(chuàng)建一個臨時分頁文件Temppf.sys。如果臨時分頁文件Temppf.sys要使用大量的硬盤可用空間,而剩余的可用硬盤空間小于在“控制面板”中配置的分頁文件設置的初始大小,就可能出現(xiàn)此問題。解決的方法:
1.清理系統(tǒng)分區(qū)的垃圾文件,給臨時分頁文件騰出足夠的空間,以適應臨時分頁文件的大小。
2.用Win+Break組合鍵打開“系統(tǒng)屬性”,在“高級”選項卡中單擊“性能”欄中的“設置”按鈕,在彈出窗口的“高級”選項卡中點擊“虛擬內存”欄中的“更改”按鈕,將分頁文件的“初始大小”和“最大大小”的值均設置為0,然后重新啟動計算機。
3.根據(jù)上面的步驟將“初始大小”和“最大大小”值重置為Windows 2000的推薦(默認)值,再次重新啟動計算機。這樣為分頁文件配置了適當?shù)拇笮『螅R時分頁文件將被刪除,虛擬內存錯誤將不再發(fā)生。
不明白的話去我的網(wǎng)頁吧:
力扣(LeetCode)70爬樓梯Go語言實現(xiàn)報錯為啥?
應該是遞歸層次太多,導致溢出了,考慮這個轉變成循環(huán)吧,不然70級斐波那契遞歸層次太多了
我為什么要選擇Rust
你好,很高興為你解答。
專訪資深程序員莊曉立:我為什么要選擇Rust?
Rust是由Mozilla開發(fā)的注重安全、性能和并發(fā)性的編程語言。這門語言自推出以來就得到了國內外程序員的大力推崇。Rust聲稱解決了傳統(tǒng)C語言和C++語言幾十年來飽受責難的內存安全問題,同時還保持了極高的運行效率、極深的底層控制、極廣的應用范圍。但在國內有關Rust的學習文檔并不多見,不久前,筆者聯(lián)系上了Rust1.0版本代碼貢獻者莊曉立(精彩博文:為什么我說Rust是靠譜的編程語言),請他分享Rust語言特性以及學習經驗。
CSDN:你是從什么時候開始接觸Rust語言的?是什么地方吸引了你?
莊曉立:我大概從2013年后半年開始深入接觸Rust語言。它居然聲稱解決了傳統(tǒng)C語言和C++語言幾十年來飽受責難的內存安全問題,同時還保持了極高的運行效率、極深的底層控制、極廣的應用范圍。
其ownership機制令人眼前一亮,無虛擬機(VM)、無垃圾收集器(GC)、無運行時(Runtime)、無空指針/野指針/內存越界/緩沖區(qū)溢出/段錯誤、無數(shù)據(jù)競爭(Data Race)……所有這些,都深深地吸引了我——這個十多年以來深受C語言折磨的痛并快樂著的程序員。
CSDN:在你看來,Rust是怎樣的一門語言?它適合開發(fā)什么類型的項目?為何你會說Rust不懼怕任何競爭對手,它既能取代C語言地位;又可挑戰(zhàn)C++市場,還可向Java、Python分一杯羹?與這些語言相比,Rust有哪些優(yōu)越的特性?
莊曉立:Rust是一門系統(tǒng)編程語言,特別適合開發(fā)對CPU和內存占用十分敏感的系統(tǒng)軟件,例如虛擬機(VM)、容器(Container)、數(shù)據(jù)庫/游戲/網(wǎng)絡服務器、瀏覽器引擎、模擬器等,而這些向來主要都是C/C++的傳統(tǒng)領地。
此外,Rust在系統(tǒng)底層開發(fā)領域,如裸金屬(bare metal)、操作系統(tǒng)(OS)、內核(kernel)、內核模塊(mod)等,也有強勁的實力,足以挑戰(zhàn)此領域的傳統(tǒng)老大C語言。Rust豐富的語言特性、先進的設計理念、便捷的項目管理,令它在上層應用開發(fā)中也能大展拳腳,至少在運行性能上比帶VM和GC的語言要更勝一籌。無GC實現(xiàn)內存安全機制、無數(shù)據(jù)競爭的并發(fā)機制、無運行時開銷的抽象機制,是Rust獨特的優(yōu)越特性。
其他語言很難同時實現(xiàn)這些目標,例如傳統(tǒng)C/C++無法保證內存安全,Java/Python等無法消除運行時開銷。但Rust畢竟還是很年輕的項目,它釋放影響力需要時間,被世人廣泛接受需要時間;它的潛力能否爆發(fā)出來,需要時間去檢驗。我們只需耐心等待。
CSDN:Rust在國內有沒有具體的實際使用案例?
莊曉立:因為Rust1.0正式版剛剛發(fā)布不足一月,在國內影響力還不大,我們不能苛求它在國內有實際應用案例。但是在國外,一兩年前就已經有OpenDNS和Skylight把Rust應用在生產環(huán)境。還有瀏覽器引擎Servo、Rust編譯器和標準庫、項目管理器Cargo等“兩個半大型應用案例”。這些足夠說明Rust語言的成熟和實用。
CSDN:你參與了Rust1.0版本代碼貢獻,目前該版本正式版已經發(fā)布,對此你感覺如何?這門語言是否已經達到比較成熟的階段?
莊曉立:我積極參與了Rust語言開源項目,多次貢獻源代碼,曾連續(xù)三次出現(xiàn)在Rust官方博客公布的Rust 1.0 alpha、Rust 1.0 beta和Rust 1.0正式版的貢獻者名單中。在Rust 1.0正式版出臺的過程中及此前的很長一段時間,開發(fā)者付出了極大的努力,確保Rust 1.0正式版在Semver 2.0規(guī)范下,務必保持向后兼容性,除非遇到重大Bug不得不修復。
我認為,在1.0正式發(fā)布之后,Rust就已經進入了比較成熟的階段。而且,Rust還在快速迭代發(fā)展過程中,1.0發(fā)布6周后將發(fā)布1.1,再6周后將發(fā)布1.2,必然會一步一個臺階,越來越成熟穩(wěn)定。
CSDN:除了功能優(yōu)先級以外,在你看來,Rust正在朝什么方向發(fā)展?未來的Rust可以期待什么樣的特性?
莊曉立:Rust一定會沿著“確保內存安全、無運行開銷、高效實用”的既定方向持續(xù)發(fā)展。在短期內值得期待的語言特性有:動態(tài)Drop、偏特化、繼承、改進borrow checker、改進宏和語法擴展。短期內值得期待的其他特性有:增強文件系統(tǒng)API、提供內存申請釋放API、更好地支持Windows和ARM、更快的編譯速度、更方便的二進制分發(fā)機制(MUSL)、更實用的工具等等。
CSDN:據(jù)我了解,你之前也比較推崇Go語言,為何想到放棄Go轉向Rust?
莊曉立:推崇Go語言還談不上,不過我曾經嘗試努力接受Go語言,2011底年開始我曾經花費將近半年時間深度關注Go開發(fā)進程,提了很多具體的改進意見和建議,也曾經多次嘗試貢獻源代碼。后來考慮到Go語言的設計理念跟我偏差太大,其社區(qū)也不太友好,慢慢地疏遠了它。我曾經寫過一篇博客《我為什么放棄Go語言》,談到了很多具體的原因。
CSDN:國內,參與Rust代碼貢獻的開發(fā)者多嗎?有核心的人員嗎?有哪些社區(qū)在維護Rust?
莊曉立:國內參與Rust代碼貢獻的開發(fā)者并不多,但也不少,官方的貢獻者名單中也偶見幾個貌似國人的名字。Rust的核心開發(fā)人員基本上都是Mozilla公司的員工,他們專職負責開發(fā)維護Rust語言和相關的項目,Rust社區(qū)也主要是他們參與組織和管理的。社區(qū)人員討論主要集中在GitHub項目主頁RFC/PR/Issue官方、Discuss論壇/IRC、Reddit、HN、StackOverflow等。
GO語言(十六):模糊測試入門(上)
本教程介紹了 Go 中模糊測試的基礎知識。通過模糊測試,隨機數(shù)據(jù)會針對您的測試運行,以嘗試找出漏洞或導致崩潰的輸入。可以通過模糊測試發(fā)現(xiàn)的一些漏洞示例包括 SQL 注入、緩沖區(qū)溢出、拒絕服務和跨站點腳本攻擊。
在本教程中,您將為一個簡單的函數(shù)編寫一個模糊測試,運行 go 命令,并調試和修復代碼中的問題。
首先,為您要編寫的代碼創(chuàng)建一個文件夾。
1、打開命令提示符并切換到您的主目錄。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,為您的代碼創(chuàng)建一個名為 fuzz 的目錄。
3、創(chuàng)建一個模塊來保存您的代碼。
運行go mod init命令,為其提供新代碼的模塊路徑。
接下來,您將添加一些簡單的代碼來反轉字符串,稍后我們將對其進行模糊測試。
在此步驟中,您將添加一個函數(shù)來反轉字符串。
a.使用您的文本編輯器,在 fuzz 目錄中創(chuàng)建一個名為 main.go 的文件。
獨立程序(與庫相反)始終位于 package 中main。
此函數(shù)將接受string,使用byte進行循環(huán) ,并在最后返回反轉的字符串。
此函數(shù)將運行一些Reverse操作,然后將輸出打印到命令行。這有助于查看運行中的代碼,并可能有助于調試。
e.該main函數(shù)使用 fmt 包,因此您需要導入它。
第一行代碼應如下所示:
從包含 main.go 的目錄中的命令行,運行代碼。
可以看到原來的字符串,反轉它的結果,然后再反轉它的結果,就相當于原來的了。
現(xiàn)在代碼正在運行,是時候測試它了。
在這一步中,您將為Reverse函數(shù)編寫一個基本的單元測試。
a.使用您的文本編輯器,在 fuzz 目錄中創(chuàng)建一個名為 reverse_test.go 的文件。
b.將以下代碼粘貼到 reverse_test.go 中。
這個簡單的測試將斷言列出的輸入字符串將被正確反轉。
使用運行單元測試go test
接下來,您將單元測試更改為模糊測試。
單元測試有局限性,即每個輸入都必須由開發(fā)人員添加到測試中。模糊測試的一個好處是它可以為您的代碼提供輸入,并且可以識別您提出的測試用例沒有達到的邊緣用例。
在本節(jié)中,您將單元測試轉換為模糊測試,這樣您就可以用更少的工作生成更多的輸入!
請注意,您可以將單元測試、基準測試和模糊測試保存在同一個 *_test.go 文件中,但對于本示例,您將單元測試轉換為模糊測試。
在您的文本編輯器中,將 reverse_test.go 中的單元測試替換為以下模糊測試。
Fuzzing 也有一些限制。在您的單元測試中,您可以預測Reverse函數(shù)的預期輸出,并驗證實際輸出是否滿足這些預期。
例如,在測試用例Reverse("Hello, world")中,單元測試將返回指定為"dlrow ,olleH".
模糊測試時,您無法預測預期輸出,因為您無法控制輸入。
但是,Reverse您可以在模糊測試中驗證函數(shù)的一些屬性。在這個模糊測試中檢查的兩個屬性是:
(1)將字符串反轉兩次保留原始值
(2)反轉的字符串將其狀態(tài)保留為有效的 UTF-8。
注意單元測試和模糊測試之間的語法差異:
(3)確保新包unicode/utf8已導入。
隨著單元測試轉換為模糊測試,是時候再次運行測試了。
a.在不進行模糊測試的情況下運行模糊測試,以確保種子輸入通過。
如果您在該文件中有其他測試,您也可以運行go test -run=FuzzReverse,并且您只想運行模糊測試。
b.運行FuzzReverse模糊測試,查看是否有任何隨機生成的字符串輸入會導致失敗。這是使用go test新標志-fuzz執(zhí)行的。
模糊測試時發(fā)生故障,導致問題的輸入被寫入將在下次運行的種子語料庫文件中go test,即使沒有-fuzz標志也是如此。要查看導致失敗的輸入,請在文本編輯器中打開寫入 testdata/fuzz/FuzzReverse 目錄的語料庫文件。您的種子語料庫文件可能包含不同的字符串,但格式相同。
語料庫文件的第一行表示編碼版本。以下每一行代表構成語料庫條目的每種類型的值。由于 fuzz target 只需要 1 個輸入,因此版本之后只有 1 個值。
c.運行沒有-fuzz標志的go test; 新的失敗種子語料庫條目將被使用:
由于我們的測試失敗,是時候調試了。
文章名稱:go語言緩沖區(qū)溢出 golang 棧溢出
分享URL:http://www.ef60e0e.cn/article/hphgso.html