摘自:https://blog.csdn.net/qq_33508087/article/details/102798362
Sanitizers簡介
Sanitizers是谷歌發起的開源工具集,包括了AddressSanitizer, MemorySanitizer, ThreadSanitizer, LeakSanitizer,Sanitizers項目本是LLVM項目的一部分,但GNU也將該系列工具加入到了自家的GCC編譯器中。GCC從4.8版本開始支持Address和Thread Sanitizer,4.9版本開始支持Leak Sanitizer和UB Sanitizer,這些都是查找隱藏Bug的利器。
valgrind特點:
這個工具相對簡單,對於一些復雜的內存泄露可能無法解析出來而且有一個問題就是只有檢測的進程退出后才會輸出內存泄露信息。
sanitize特點:
sanitize可以在檢測到內存泄露第一時間立刻終止進程,並且它可以深入檢測(隨應用進程一起編譯)。
sanitize的使用方法:
1,內存訪問錯誤是模糊測試通常能夠發現的一類錯誤,其主要是由於程序對不該進行讀寫操作的內存進行了操作,從而導致了應用程序的崩潰。
2,實際上並不是所有的內存訪問錯誤都能發生崩潰。
test.c來作為一個例子:
-
-
int main()
-
{
-
int a[2] = {1, 0};
-
int b = a[2];
-
return 0;
-
}
3,我們可以看出這是一個經典的 off-by-one-error錯誤:定義一個有兩個元素的數組,訪問該數組的元素時需從0開始,因此該數組的兩個元素分別為a[0]、a[1]。然后將a[2]賦值給b,但實際上a[2]不是數組的一部分,是個無效的數值。所以b最終就成了一個任意的數值,它只是從堆棧和內存中未被定義的部分中讀取了“一些”內存。
4,然而和其他的內存訪問錯誤所不同的是,它並不會造成崩潰,即使是強大的 valgrind 也無法告訴我們具體問題在哪里。而在最新版本的 llvm和gcc中有一款工具卻可以發現這種錯誤,它就是Address Sanitizer (ASan) ,它可以直接在編譯的時候進行使用。
不過要注意的是,在使用前我們需要在編譯器標志中增加一個參數-fsanitize=address。另外,為了使調試更為輕松,我們還需要增加 -ggdb.
zhangsan@PC:~$ gcc -fsanitize=address -ggdb -o test test.c
現在,我們再去運行之前的那個例子,我們會得到一個彩色的錯誤信息:
-
==7402==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff2971ab88 at pc 0x400904 bp 0x7fff2971ab40 sp 0x7fff2971ab30READ of size 4 at 0x7fff2971ab88 thread T0
-
#0 0x400903 in main /tmp/test.c:5
-
#1 0x7fd7e2601f9f in __libc_start_main (/lib64/libc.so.6+0x1ff9f)
-
#2 0x400778 (/tmp/a.out+0x400778)
-
Address 0x7fff2971ab88 is located in stack of thread T0 at offset 40 in frame
-
#0 0x400855 in main /tmp/test.c:1
-
-
This frame has 1 object(s):
-
[ 32, 40) 'a' <== Memory access at offset 40 overflows this variable
-
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
-
(longjmp and C++ exceptions *are* supported)
-
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/test.c:3 main
5,我選擇了其中最為有趣的一部分,相信這部分已經完全足夠說明發生了什么——測試代碼的第三行中由於一個大小為4的無效讀取導致出現了棧溢出(一個整數的大小)。
使用Address Sanitizer進行軟件開發
1,我們在進行模糊測試時,通常對象不會是一個簡單的C文件,因此我們必須要把address sanitizer添加到編譯器的標志寄存器中。而軟件所使用的正常配置腳本則如下所示:
-
zhangsan@PC :~$ ./configure --disable-shared CFLAGS="-fsanitize=address -ggdb" CXXFLAGS="-fsanitize=address -ggdb"
-
zhangsan@PC :~$ make
2,為了獲得更多的調試信息,我們需要再一次的添加-ggdb。如果可能的話我們還可以禁用共享庫並設置C和C++編譯器的標志。
3,然后,我們就可以像第一部分所說的那樣對運行中的軟件進行畸形輸入了。而當我們將輸出重定向到日志文件時,我們就不得不考慮到我們不能夠對分段錯誤進行grep,而是需要我們去grep Address Sanitizer的消息:
grep AddressSanitizer fuzzing.log
在使用Address Sanitizer時,我們還必須要考慮到一些事:
1、ASan發現內存訪問違規的時,應用程序並不會自動崩潰。這是由於在使用模糊測試工具時,它們通常都是通過檢查返回碼來檢測這種錯誤。當然,我們也可以在模糊測試進行之前通過將環境變量 ASAN_OPTIONS修改成如下形式來迫使軟件崩潰:
export ASAN_OPTIONS='abort_on_error=1'/
2、 ASan需要相當大的虛擬內存(大約20TB),不用擔心,這個只是虛擬內存,你仍可以使用你的應用程序。但像 american fuzzy lop這樣的模糊測試工具就會對模糊化的軟件使用內存進行限制,不過你仍可以通過禁用內存限制來解決該問題。唯一需要注意的就是,這會帶來一些風險:測試樣本可能會導致應用程序分配大量的內存進而導致系統不穩定或者其他應用程序崩潰。因此在進行一些重要的模糊測試時,不要去嘗試在同一個系統上禁用內存限制。
3、 Zzuf目前並不能和 ASan協同工作, 但你仍可以使用zzuf手動去創建一些測試樣本將他們輸入ASan的編譯軟件中。
4、還有就是,ASan會顯著的延緩執行,其所發現的bug往往沒有那么嚴重(當然也有例外),不過它能發現更多的bug是毋庸置疑的。