現(xiàn)在的IMF只適用于mac系統(tǒng),應該是API_DEFS中的api都屬于mac系統(tǒng),如果要測試新的系統(tǒng)應該需要改動這個數(shù)組。
以下是根據(jù)github上使用步驟的順序進行源代碼閱讀。
1.Generate hooking library for APIs
$ ./gen-hook [output(hooking code) path]
$ clang? -Wall -dynamiclib -framework IOKit -framework CoreFoundation -arch i386 -arch x86_64 hook.c -o hook
gen-hook腳本把命令行的所有參數(shù)傳入hook.py,實際上就是調(diào)用hook.py
hook.py里首先判斷參數(shù)是否為空,如果不為空則創(chuàng)建一個Hooker類并調(diào)用其gen_hook()函數(shù)
Hooker類的__init__()函數(shù):調(diào)用了basic.load_apis(),這個函數(shù)返回了apis{},把const.API_DEFS里面的apis存到apis{}中,每個api用Api類存儲。const.API_DEFS是一個數(shù)組,每個元素代表一個api,記為data的話,data[0]為rtype和name(用,分開),data[1]為參數(shù)數(shù)組,每個參數(shù)是一個元組,元組的第一個元素是類型,第二個元素是名字,第三個元素沒有明白。
gen_hook()函數(shù):遍歷apis,調(diào)用ApiHook(api)對每個api進行插樁,把code寫到文件f里,文件f就是[output(hooking code) path]。code具體內(nèi)容還沒有懂。
hook.py到此結(jié)束。
2.Collect logs
$ DYLD_INSERT_LIBRARIES=[hooking library path] [program path] [program args]
這一步還沒看明白做了什么操作,DYLD_INSERT_LIBRARIES是一個動態(tài)hook庫?
3.Filter logs
$ ./filter-log [log dir] [output dir] [# of output(filtered log)] [# of core]
filter-log腳本把命令行參數(shù)傳給filter.py,并用pypy運行filter.py。參數(shù)1為log文件夾路徑,參數(shù)2為output文件夾路徑,參數(shù)3為?,參數(shù)4為core?。
filter.py首先把參數(shù)3存到n,把參數(shù)4存到core,然后調(diào)用do_filter()函數(shù)。
do_filter(log_path, out_path, n, core)函數(shù)首先調(diào)用list_dir(log_path),把返回的files數(shù)組存到log_names,files數(shù)組里是log_path路徑里的所有文件路徑;然后調(diào)用utils.multiproc(loader, log_names, core)函數(shù)(utils.py是自己實現(xiàn)的,用了multiprocessing中的Pool),返回logs,這一步我猜是多核多線程地運行l(wèi)oader,loader()類的作用是對每個文件,按行讀取存到data中然后提取name、selector,依次存到數(shù)組ret中并返回ret,name和selector具體是什么內(nèi)容還沒有仔細研究,而且多個線程中的ret是怎么連接成一個logs的?;然后調(diào)用find_best([logs], n),返回最佳group和idx,其中調(diào)用了categorize()函數(shù)和pick_best()函數(shù),這一步不明白;最后save_best(),寫到out_path(即第二個參數(shù))里。
我猜這一步是從logs中選擇“最佳的”n個logs。
4.Infer a model and generate a fuzzer.
$ ./gen-fuzz [filtered logs path] [output(fuzzer code) path] [# of core]
gen-fuzz腳本把命令行參數(shù)傳給apifuzz.py,并用pypy運行apifuzz.py。
apifuzz.py首先創(chuàng)建一個ApiFuzz類記為fuzz,數(shù)組logs存放參數(shù)1里的文件路徑,調(diào)用get_limit(logs)函數(shù)(這個函數(shù)的作用還沒搞清),最后調(diào)用make_model(logs, limit, sys.argv[2], core)函數(shù)。
make_model函數(shù)調(diào)用了utils.multiproc()函數(shù),在這個函數(shù)中多線程地跑load_apilog()函數(shù)(這個函數(shù)的作用也還沒搞清),返回值存在apilogs中,然后創(chuàng)建了model類,調(diào)用model.fuzz()函數(shù),把code寫到文件中。
model這個類還沒有看。
我猜這一步是生成用于fuzz的model的c文件。
5.Compile the fuzzer
$ clang -framework IOKit -framework CoreFoundation -arch i386 fuzz.c -o fuzz
我猜這一步是用clang編譯上一步得到的c文件。
6.Run the fuzzer
$ ./fuzz -f [log path] -s [seed] -b [bitlen] -r [rate] -l [# of max loops]
這一步就是fuzzing了。
7.You may want to run the generated fuzzer within a while loop.