新聞中心
本文主要內(nèi)容包括:WinAFL介紹與安裝、以ABC看圖程序?yàn)槔龢?gòu)建Fuzz最小案例庫(kù)、執(zhí)行Fuzz跑出Crash,以及最終利用Bugid對(duì)Crash分類

創(chuàng)新互聯(lián)專注于坪山網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供坪山營(yíng)銷型網(wǎng)站建設(shè),坪山網(wǎng)站制作、坪山網(wǎng)頁(yè)設(shè)計(jì)、坪山網(wǎng)站官網(wǎng)定制、小程序開(kāi)發(fā)服務(wù),打造坪山網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供坪山網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
WinAFL介紹與安裝
WinAFL,是Ivan Fratric基于lcumtuf的AFL創(chuàng)建的大型Fuzzing程序,由于AFL無(wú)法在windows下直接使用,Winafl彌補(bǔ)了這一空白,使用DynamoRIO來(lái)插樁&測(cè)量代碼覆蓋率,并使用Windows API進(jìn)行內(nèi)存和進(jìn)程創(chuàng)建。
WinAFL 項(xiàng)目地址:https://github.com/ivanfratric/winafl
請(qǐng)注意:Windows 10 1809及更高版本的最新Windows版本要使用DynamoRIO 8.0.0以上版本
此時(shí)如果直接進(jìn)行操作可能會(huì)出現(xiàn)以下報(bào)錯(cuò)
需要re-compiled ,這個(gè)過(guò)程為:
(1) 下載安裝DynamoRio源碼,或者直接下載DynamoRio Windows版的二進(jìn)制包(https://github.com/DynamoRIO/dynamorio/wiki/Downloads)
(2) 打開(kāi)Visual Studio命令提示工具,如果要安裝成64位版本的則打開(kāi)Visual Studio x64命令提示工具(一般在【開(kāi)始—所有程序—Visual Stdio—Visual Studio Tools】中可找到)。因?yàn)樵趯?duì)64位程序進(jìn)行fuzz時(shí),需要有64-bit的winafl.dll,所以安裝時(shí)要選擇好版本
(3)在命令提示工具中進(jìn)入WinAFL的目錄下
(4) 在Visual Studio命令提示工具中輸入如下命令進(jìn)行WinAFL編譯安裝(需將-DDynamoRIO_DIR參數(shù)設(shè)置為你的DynamoRIO cmake文件所在位置)
32-bit build:
mkdir build32
cd build32
cmake -G"Visual Studio 16 2019" -A Win32 .. -DDynamoRIO_DIR=..\path\to\DynamoRIO\cmake
cmake --build . --config Release64-bit build:
mkdir build64
cd build64
cmake -G"Visual Studio 16 2019" -A x64 .. -DDynamoRIO_DIR=..\path\to\DynamoRIO\cmake
cmake --build . --config Release這里需要注意一下-G選擇平臺(tái)時(shí)VS16與之前版本默認(rèn)目標(biāo)平臺(tái)架構(gòu)是有些區(qū)別的:
cmake -G "Visual Studio 16 2019" -A Win32 ;x32
cmake -G "Visual Studio 16 2019" -A x64 ;x64 默認(rèn)目標(biāo)平臺(tái)名稱(架構(gòu))為Win64
cmake -G "Visual Studio 15 2017" ;x32 默認(rèn)目標(biāo)平臺(tái)名稱(架構(gòu))為Win32
cmake -G "Visual Studio 15 2017 Win64" ;x64winafl 命令行參數(shù),主要分為三段,(afl執(zhí)行參數(shù)–dynamoRIO執(zhí)行參數(shù)–程序執(zhí)行參數(shù))
- afl執(zhí)行參數(shù)主要包括
-i -o指定輸入和輸出文件夾
-D指定DynamoRIO根目錄
-t每一次樣本執(zhí)行的超時(shí)時(shí)限
-ffuzz 程序讀取的位置
-M \ -S分布式模式
-x可選的fuzz字典
- dynamRIO執(zhí)行參數(shù)主要包括
-coverage_module計(jì)算覆蓋率的模塊
-fuzz_iterations在重新啟動(dòng)目標(biāo)進(jìn)程之前,目標(biāo)函數(shù)要運(yùn)行的最大迭代次數(shù)。
-target_module包含目標(biāo)函數(shù)的模塊(一個(gè)可執(zhí)行文件鏡像)需要與該選項(xiàng)一起指定-target_method或-target_offset
-target_method目標(biāo)函數(shù),需要export或者帶符號(hào)
-target_offset目標(biāo)偏移,相對(duì)于target_module的偏移,在method無(wú)法導(dǎo)出的時(shí)候使用
-nargs程序執(zhí)行所需要的參數(shù)個(gè)數(shù)
-debug調(diào)試模式。不要嘗試連接到服務(wù)器。輸出包含已加載模塊,打開(kāi)的文件和覆蓋率信息的日志文件
-logdir指定將日志文件寫入哪個(gè)目錄(僅與-debug一起使用)
- 程序執(zhí)行參數(shù)就是要fuzz的程序的命令行
構(gòu)建Fuzz最小案例庫(kù)
現(xiàn)在我們從網(wǎng)上搜集一堆ABC看圖支持的格式,包括tif、jpg、png、ico等,github上有許多Fuzz的案例庫(kù),這樣的案例庫(kù)中包含大量的文件,運(yùn)行起來(lái)效率會(huì)很差。根據(jù)學(xué)長(zhǎng)博客,AFL是存在語(yǔ)料庫(kù)蒸餾(Corpus Distillation)工具的,afl-cmin和afl-tmin。
- 移除執(zhí)行相同代碼的輸入文件——AFL-CMINafl-cmin的核心思想是:嘗試找到與語(yǔ)料庫(kù)全集具有相同覆蓋范圍的最小子集。舉個(gè)例子:假設(shè)有多個(gè)文件,都覆蓋了相同的代碼,那么就丟掉多余的文件。
- 減小單個(gè)輸入文件的大小——AFL-TMIN整體的大小得到了改善,接下來(lái)還要對(duì)每個(gè)文件進(jìn)行更細(xì)化的處理。afl-tmin盡量縮減文件體積。
在winafl中,他們存在于 winafl-cmin.py,對(duì)輸入的樣本文件進(jìn)行最小化處理,以用來(lái)提高 WinAFL 的執(zhí)行效率。
篩選命令
python winafl-cmin.py --working-dir C:\Users\test\Desktop\winafl-master\build32\bin\Release -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 100000 -i C:\Users\test\Desktop\jpg -o C:\Users\test\Desktop\jpg\out -coverage_module FreeImage.dll -target_module Project1.exe -target_method main -nargs 2 -- C:\Users\test\source\repos\Project1\Release\Project1.exe @@此時(shí)可能出現(xiàn)[!] Dry-run failed, 2 executions resulted differently:Tuples matching? False的報(bào)錯(cuò)
看來(lái)測(cè)試用例中存在一些壞的用例,導(dǎo)致不能正確精簡(jiǎn),在語(yǔ)料庫(kù)所在文件夾可以利用以下bash腳本簡(jiǎn)單判斷一下
λ for file in *; do printf "==== FILE: $file =====\n";/c/Users/test/source/repos/Project1/Release/Project1.exe $file ;echo $?; done正常運(yùn)行的文件返回值都是0,有問(wèn)題的文件返回結(jié)果都不太正常
把這些返回結(jié)果不太正常的刪除之后,再運(yùn)行一次語(yǔ)料庫(kù)蒸餾,發(fā)現(xiàn)運(yùn)行成功了
可以看到原本429張被精簡(jiǎn)到了148張,確實(shí)少了不少,根據(jù)參考教程中的提示,Winafl在處理大于4Kb的圖片時(shí),速度會(huì)變得很慢,因此再刪除一波,最終語(yǔ)料庫(kù)就剩下這么點(diǎn)了。
開(kāi)始運(yùn)行
經(jīng)過(guò)動(dòng)態(tài)和靜態(tài)的簡(jiǎn)單分析后,發(fā)現(xiàn)ABC看圖主要調(diào)用Freeimage.dll進(jìn)行圖片解析的,決定對(duì) FreeImage 庫(kù)的載入函數(shù)進(jìn)行模糊測(cè)試,針對(duì) FreeImage_LoadU 函數(shù)編寫測(cè)試程序
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
using namespace std;
extern "C" __declspec(dllexport) int main(int argc, char** argv);
void test(HINSTANCE hinstLib, wchar_t* PathName);
wchar_t* charToWChar(const char* text);
typedef DWORD(__stdcall* FreeImage_GetFileTypeU)(const wchar_t* lpszPathName, int flag);
typedef DWORD(__stdcall* FreeImage_Initialise)(BOOL load_local_plugins_only);
typedef DWORD(__stdcall* FreeImage_DeInitialise)();
typedef DWORD(__stdcall* FreeImage_LoadU)(DWORD format, const wchar_t* lpszPathName, int flag);
typedef DWORD(__stdcall* FreeImage_UnLoad)(DWORD dib);
FreeImage_Initialise Initialise;
FreeImage_GetFileTypeU LoadFileType;
FreeImage_LoadU LoadU; DWORD load;
FreeImage_UnLoad UnLoad;
FreeImage_DeInitialise DeInitialise;
int main(int argc, char** argv)
{
if (argc < 2) {
printf("Usage: %s < file>\n", argv[0]);
return 0;
}
wchar_t* PathName = charToWChar(argv[1]);
HINSTANCE hinstLib; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; DWORD Error = NULL;
hinstLib = LoadLibrary(TEXT("C:\\FreeImage.dll"));
if (hinstLib != NULL)
{
fRunTimeLinkSuccess = TRUE;
Initialise = (FreeImage_Initialise)GetProcAddress(hinstLib, (LPCSTR)163); // 初始化 FreeImage 庫(kù)
LoadFileType = (FreeImage_GetFileTypeU)GetProcAddress(hinstLib, (LPCSTR)126);// 獲取位圖文件類型
LoadU = (FreeImage_LoadU)GetProcAddress(hinstLib, (LPCSTR)181); // 加載位圖
UnLoad = (FreeImage_UnLoad)GetProcAddress(hinstLib, (LPCSTR)242);// 卸載位圖
DeInitialise = (FreeImage_DeInitialise)GetProcAddress(hinstLib, (LPCSTR)83);//卸載 FreeImage 庫(kù)
test(hinstLib, PathName);
fFreeResult = FreeLibrary(hinstLib);
}
if (!fRunTimeLinkSuccess)
cout << "加載函數(shù)失敗, Error: " << Error << endl;
return 0;
}
void test(HINSTANCE hinstLib, wchar_t* PathName)
{
DWORD FileType = (LoadFileType)(PathName, 0);
load = (LoadU)(FileType, PathName, 0);
return;
}
wchar_t* charToWChar(const char* text)
{
size_t size = strlen(text) + 1;
wchar_t* wa = new wchar_t[size];
mbstowcs(wa, text, size);
return wa;
} 在對(duì)該程序進(jìn)行編譯之后,可以先簡(jiǎn)單測(cè)試一下WinAFL 是否可以正常使用。-debug 表示設(shè)置為調(diào)試模式。
\winafl\bin32> C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32\drrun.exe -c winafl.dll -debug -coverage_module FreeImage.dll -target_module Project1.exe -target_method main -fuzz_iterations 10 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe C:\Users\test\Desktop\jpg\1x1-low.jpg如下圖所示,日志文件當(dāng)中模塊加載正常并沒(méi)有錯(cuò)誤顯示
下面就要開(kāi)始模糊測(cè)試了,按照教程進(jìn)行的,但是它的目標(biāo)函數(shù)是main,我們來(lái)看看結(jié)果如何。
afl-fuzz.exe -i C:\Users\test\Desktop\jpg\out -o C:\Users\test\Desktop\jpg\re -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 9000 -- -coverage_module FreeImage.dll -target_module Project1.exe -target_method main -fuzz_iterations 5000 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe @@如圖所示,可以跑是可以跑,但是這個(gè)速度實(shí)在太慢了,執(zhí)行main函數(shù)浪費(fèi)了太多時(shí)間,實(shí)際上我們的load函數(shù)只測(cè)test函數(shù)就可以,我們將-target_method改為test嘗試一下
afl-fuzz.exe -i C:\Users\test\Desktop\jpg\out -o C:\Users\test\Desktop\jpg\re -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 9000 -- -coverage_module FreeImage.dll -target_module Project1.exe -target_method test -fuzz_iterations 5000 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe @@然后就蹦框了,看起來(lái)是沒(méi)有找到我們寫的test函數(shù),忘了在vs里把test函數(shù)也導(dǎo)出
這里導(dǎo)出后再編譯一遍,再嘗試一下,成功了,這速度明顯提升了好幾倍啊
為了讓fuzz效率更高一點(diǎn),充分利用cpu的多核,進(jìn)行多核系統(tǒng)的并行測(cè)試
afl-fuzz.exe -i C:\Users\test\Desktop\jpg\out -o C:\Users\test\Desktop\jpg\re -M master -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 9000 -- -coverage_module FreeImage.dll -target_module Project1.exe -target_method test -fuzz_iterations 5000 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe @@
afl-fuzz.exe -i C:\Users\test\Desktop\jpg\out -o C:\Users\test\Desktop\jpg\re -S slaver01 -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 9000 -- -coverage_module FreeImage.dll -target_module Project1.exe -target_method test -fuzz_iterations 5000 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe @@
afl-fuzz.exe -i C:\Users\test\Desktop\jpg\out -o C:\Users\test\Desktop\jpg\re -S slaver02 -D C:\Users\test\Desktop\DynamoRIO-Windows-8.0.0-1\bin32 -t 9000 -- -coverage_module FreeImage.dll -target_module Project1.exe -target_method test -fuzz_iterations 5000 -nargs 2 -- C:\Users\test\source\repos\Project1\Debug\Project1.exe @@因?yàn)槲业呐渲帽容^垃圾只有四核,所以就開(kāi)這么多了,我們先試一下
扔到ABC看圖里,發(fā)現(xiàn)真的崩潰了
利用Bugid對(duì)Crash分類
這樣一堆crash,里面肯定有不少重復(fù)的,原因也有各不相同,如何對(duì)他們進(jìn)行快速分類并找到問(wèn)題點(diǎn)呢?
在這里我使用了BugID,它可以反饋崩潰和死機(jī)的可利用性的詳細(xì)報(bào)告,BugID安裝所需要的環(huán)境如下:
- 最新的Python 2.7.14
- Windows的最新調(diào)試工具
- 最新的BugId版本
如果使用默認(rèn)設(shè)置安裝Windows的Python和調(diào)試工具,則BugId應(yīng)該能夠運(yùn)行而無(wú)需調(diào)整任何設(shè)置。您可以在本地文件系統(tǒng)上任意位置解壓縮BugId
但是理論上BugID需要一個(gè)一個(gè)進(jìn)行文件分析,而Crash這么多,只是就可以寫一個(gè)Python腳本來(lái)幫助我們
import sys
import os
sys.path.append(r"C:\Users\test\Desktop\BugId-master")
testcases = []
for root, dirs, files in os.walk(r"C:\Users\test\Desktop\jpg\re\slaver01\crashes", topdown=False):
for name in files:
testcase = os.path.abspath(os.path.join(root, name))
testcases.append(testcase)
for testcase in testcases:
print ("[*] Gonna run: ", testcase)
os.system(r'PageHeap.cmd "Project1.exe" ON')
os.system(r'python C:\Users\test\Desktop\BugId-master\BugId.py C:\Users\test\source\repos\Project1\Debug\Project1.exe --isa= x86 -- %s' % testcase)請(qǐng)注意在最后的程序后面加上--isa= x86哦,不加默認(rèn)作為64位調(diào)試會(huì)報(bào)錯(cuò)
運(yùn)行腳本之后,我們就看到源源不斷的bug信息出來(lái)了
最后可以寫到一個(gè)文檔里保存下來(lái),看起來(lái)字符好像有點(diǎn)問(wèn)題,不過(guò)問(wèn)題不大
這只是簡(jiǎn)要信息,BugID在運(yùn)行時(shí)已經(jīng)自動(dòng)生成了較為詳細(xì)的分析報(bào)告,打開(kāi)BugID目錄就可以看到
隨便打開(kāi)一個(gè)看看,很詳細(xì)
參考文獻(xiàn)
winafl使用 http://www.simp1e.site/2020/04/18/winafl/
模糊測(cè)試工具WinAFL使用指南 https://www.freebuf.com/articles/system/216437.html
初識(shí) Fuzzing 工具 WinAFL https://paper.seebug.org/323/
Fuzz 工具 WinAFL 的使用感受 https://bbs.pediy.com/thread-255162.htm
Fuzzing the MSXML6 library with WinAFL https://symeonp.github.io/2017/09/17/fuzzing-winafl.html
標(biāo)題名稱:WinAFL小白踩坑指南,你學(xué)會(huì)了嗎?
鏈接URL:http://m.fisionsoft.com.cn/article/dpjjhjc.html


咨詢
建站咨詢
