AFL模糊測試學(xué)習(xí)(三)AFL運行

? ? 以使用afl-gcc進行插樁后的AFL運行為例。我們來學(xué)習(xí)AFL的運行。main函數(shù)中首先識別參數(shù)opt?=?getopt(argc,?argv,?"+i:o:f:m:t:T:d:n:C:B:S:M:x:Q")。然后在setup_shm()這個函數(shù)中初始化MAP_SIZE(2^16)大小的map用來父進程子進程間的信息共享。然后perform_dry_run()這個函數(shù)把初始的種子跑一遍,觀察是否有問題。

先補充一些知識:

fd文件(File?descriptor)

????所有都可以抽象成文件,比如普通的文件、目錄、塊設(shè)備、字符設(shè)備、socket、管道等等。當通過一些系統(tǒng)調(diào)用(如open/socket等),會返回一個fd(就是一個數(shù)字)給你,然后根據(jù)這個fd對應(yīng)的文件進行操作,比如讀、寫。linux默認對每個進程最大能打開的fd的個數(shù)是1024(軟限制是1024,硬限制4096)。

管道PIPE

管道初始化函數(shù) int?pipe(int?pipefd[2]);?成功:0;失?。?1

fd[0]?→?r;?fd[1]?→?w,就像0對應(yīng)標準輸入,1對應(yīng)標準輸出一樣。向管道文件讀寫數(shù)據(jù)其實是在讀寫內(nèi)核緩沖區(qū)。在后面AFL的forkserer中父進程和子進程交互就使用了st_pipe[2],ctl_pipe[2]。


這里介紹幾個很重要的數(shù)據(jù)結(jié)構(gòu)和函數(shù):

cull_queue()

? ? 種子的數(shù)據(jù)結(jié)構(gòu)為:

struct?queue_entry?{

? ??u8*?fname;??????????????????????????/*?File?name?for?the?test?case??????*/

? ??u32?len;????????????????????????????/*?Input?length?????????????????????*/

? ??u8??cal_failed,?????????????????????/*?Calibration?failed???????????????*/

? ? trim_done,??????????????????????/*?Trimmed??????????????????????????*/

? ? was_fuzzed,?????????????????????/*?Had?any?fuzzing?done?yet?????????*/

? ? passed_det,?????????????????????/*?Deterministic?stages?passed??????*/

? ? has_new_cov,????????????????????/*?Triggers?new?coverage????????????*/

? ? var_behavior,???????????????????/*?Variable?behavior????????????????*/

? ? favored,????????????????????????/*?Currently?favored????????????????*/

? ? fs_redundant;???????????????????/*?Marked?as?redundant?in?the?fs????*/

? ? u32?bitmap_size,????????????????????/*?Number?of?bits?set?in?bitmap?????*/

? ? exec_cksum;?????????????????????/*?Checksum?of?the?execution?trace??*/

? ? u64?exec_us,????????????????????????/*?Execution?time?(us)??????????????*/

? ? handicap,???????????????????????/*?Number?of?queue?cycles?behind????*/

? ? depth;??????????????????????????/*?Path?depth???????????????????????*/

? ? u8*?trace_mini;?????????????????????/*?Trace?bytes,?if?kept?????????????*/

? ? u32?tc_ref;?????????????????????????/*?Trace?bytes?ref?count????????????*/

? ? struct?queue_entry?*next,???????????/*?Next?element,?if?any?????????????*/

?????????????????????*next_100;???????/*?100?elements?ahead???????????????*/

};

????我們知道種子是一系列的,每次通過程序運行該種子的時間、是否產(chǎn)生新路徑等信息對種子進行打分排序,對一些沒有貢獻的種子,pass_det這一項就置為表示循環(huán)fuzz的時候?qū)⑻^該種子。



run__target()

????不管是在一開始的perform_dry_run()還是后面測試過程中一直循環(huán)的fuzz_one(),這個是運行插樁程序的函數(shù)。在里面先是查詢有沒有forkserver這么一個子進程,如果沒有就建立一個forkserver,同時建立好管道。

????在init_forkserver這個環(huán)節(jié),會生成兩個管道ctl_pipe,?st_pipe,分別綁定fd?198,fd?199.然后開始運行程序并且進程間通信。一旦init了child進程就不會退出,每次有新的測試樣例,就直接運行,運行的時候child進程fork一個grandchild進程,這個進程一直運行_afl_store()這個函數(shù)對shm的bitmap進行修改。

????如果是第一次運行(一般在perform_dry_run()這個函數(shù)中),就會創(chuàng)建一個子進程。子進程會一直用testcase這個緩沖區(qū)中的種子運行程序,通過管道把執(zhí)行路徑交互給父進程。交互過程如下:



? ? 每次運行run_target()函數(shù)都會在ctl_pipe寫入值,喚醒卡死在read等待的子進程,子進程就可以fork一個孫進程,孫進程執(zhí)行程序,把所有程序塊中插樁的部分執(zhí)行一遍,把結(jié)果寫入共享的內(nèi)存區(qū),就實現(xiàn)了執(zhí)行路徑的記錄。

cur_location?=?<COMPILE_TIME_RANDOM>;

shared_mem[cur_location?^?prev_location]++;?

prev_location?=?cur_location?>>?1;

????這里的cur_location和prev_location都是程序塊的id,這里使用[cur_location?^?prev_location]意為記錄邊,因為如果一個程序有a、b、c三個基本塊,a->b->c 和a->c->b是不同的執(zhí)行路徑,但是只用基本塊記錄的話都是a、b、c,用邊記錄的話可以跟好比對運行路徑。

? ? 關(guān)于種子變異,這個是AFL的確定性變異(位翻轉(zhuǎn)、拼接等)和非確定性變異組合而成,在afl-fuzz.c中可以更好學(xué)習(xí),就不在這里贅述。

? ? 就先寫到這里,大家對AFL還有什么疑問,可以留言,我們可以寫四五六等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.目標明確、精力管理 一年有365天,有的人過了365天,有的人只過了一天,重復(fù)了365次??梢娔繕撕途Φ闹匾?..
    斯特董閱讀 123評論 0 2
  • 龍小糯閱讀 227評論 0 1
  • 重慶的南濱路位于重慶南岸。南濱路有重慶的外灘之稱,我于半晚到了。出現(xiàn)在
    牛德華12345閱讀 288評論 0 0
  • 豬年正月十五到, 雨水時節(jié)巧相邀。 夜賞燈彩吃元宵, 晨起甘霖潤綠嬌。 天地靈氣春光好, 阡陌碧連萌芳草。 不比花...
    天龍山閱讀 863評論 3 12

友情鏈接更多精彩內(nèi)容