Table of Contents
1. TODO
2. 总结
2.1. 常用参数
-n
指定最大线程数
-f
原始输入种子文件目录
-W
有效变异种子文件输出目录
-e
指定输入文件扩展名 默认为*.fuzz
-d
Debug info
--mutate_cmd|-c
扩展变异规则以代替原有变异方式,
当你通过-f提供输入样本目录后,在fuzzing时,随机提取的文件会直接传递给-c参数指定的扩展命令作变异
input_prepareExternalFile or input_postProcessFile: bool input_prepareExternalFile(run_t* run) { // ... const char* const argv[] = {run->global->exe.externalCommand, fname, NULL}; if (subproc_System(run, argv) != 0) { LOG_E("Subprocess '%s' returned abnormally", run->global->exe.externalCommand); return false; } // ... } uint8_t subproc_System(run_t* run, const char* const argv[]) { // ... execv(argv[0], (char* const*)&argv[0]); // ... } 假如 run->global->exe.externalCommand = extcmd.py 则会执行 extcmd.py fname 在实现中可以通过open(argv[1])打开文件对数据进行处理
--mutations_per_run|-r
每个样例编译的最大次数 默认6
--pprocess_cmd
在原有的文件变异后再作处理
-P
persistent模式
-t
timeout
-F
Max File Size
-V
verifier 如果开启,则会验证崩溃样本(最大运行5次)
--exit_upon_crash
有崩溃直接退出fuzz
-R
生成报告文件
-E
ENV参数,如增加sanitizers: ASAN_OPTIONS=coverage=1
-S
sanitizer模式
参数放在 hfzz.exe.envs[] hfuzz->sanitizer.enable 如果启用: snprintf(buf, buflen, "%s=%s:%s:%s%s/%s", env, kASAN_OPTS, abortFlag, kSANLOGDIR, hfuzz->io.workDir, kLOGPREFIX); kASAN_OPTS = kASAN_COMMON_OPTS: "allow_user_segv_handler=1:" \ "handle_segv=0:" \ "allocator_may_return_null=1:" kSAN_COMMON ":exitcode=" HF_XSTR(HF_SAN_EXIT_CODE) #define kSAN_COMMON "symbolize=0" /* Exit code is common for all sanitizers */ #define HF_SAN_EXIT_CODE 103 即:ASAN_OPTIONS= "allow_user_segv_handler=1:handle_segv=0:allocator_may_return_null=1:symbolize=0:exitcode=103:abort_on_error=1:log_path=workDir/HF.sanitizer.log" 否则: snprintf(buf, buflen, "%s=%s", env, kSAN_REGULAR); /* If no sanitzer support was requested, simply make it use abort() on errors */ #define kSAN_REGULAR \ "abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:" \ "handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:" \ "symbolize=1:detect_leaks=0:disable_coredump=0:" \ "detect_odr_violation=0"
-x
static mode(_HF_DYNFILE_NONE) 不使用任何feedback.
--instrument|-z
使用编译时的feedback 默认 _HF_DYNFILE_SOFT
-w
字典,针对特殊格式的解析,如xml:
https://github.com/rc0r/afl-fuzz/blob/master/dictionaries/xml.dict
实际变异中,命中字典格式变异存在随机性,如果需要只指定字典变异,需要修改源码 mangle_Dictionary -> mangle_DictionaryNoCheck mangle_DictionaryInsert -> mangle_DictionaryInsertNoCheck 取随机数N,遍历标签取到内容,覆写/插入随机位置。
__FILE__
相当于AFL中的@@,
在实际的运行中会被input_dir中的输入所替换,替换为文件句柄,可以通过open(fd)打开进行操作,参考honggfuzz/examples/badcode/targets/badcode1.c
bool arch_launchChild(run_t* run) { //... int x = 0; for (x = 0; x < ARGS_MAX && x < run->global->exe.argc; x++) { if (run->global->exe.persistent || run->global->exe.fuzzStdin) { args[x] = run->global->exe.cmdline[x]; } else if (!strcmp(run->global->exe.cmdline[x], _HF_FILE_PLACEHOLDER)) { args[x] = inputFile; } else if (strstr(run->global->exe.cmdline[x], _HF_FILE_PLACEHOLDER)) { const char* off = strstr(run->global->exe.cmdline[x], _HF_FILE_PLACEHOLDER); snprintf(argData, sizeof(argData), "%.*s%s", (int)(off - run->global->exe.cmdline[x]), run->global->exe.cmdline[x], inputFile); args[x] = argData; } else { args[x] = run->global->exe.cmdline[x]; } } // ... } ___FILE___: 必须在非persistent模式(-P)下,且没有指定stdin(-s)的情况下使用, -s: run->global->exe.fuzzStdin -P: run->global->exe.persistent 比如 ./badcode1 这个程序的 第1个参数是要处理的文件的名称,那么相应的 fuzz 的命令就是: /honggfuzz -S -W ./outputs -f ./corpus -- ./badcode1 __FILE__ 实际fuzz过程中,会将__FILE__替换成文件句柄传入,作为第一个参数, 即argv[1]=file_fd
--sancov|-C
使用ASAN_OPTIONS="coverage=1",
clang-4使用,慢,已经废除(commit:
8267c77c0bfee82a528290c5e86c297291922dc6)。
--monitor_sigabrt
: 默认是true,在=-S=模式下会设置ASAN标志
abort_on_error=1, 发生错误会调 abort() 返回错误代码,替代_exit()函数
2.2. 关于coverage计算模式
run->global->feedback.dynFileMethod字段记录着Trace方式
typedef enum { _HF_DYNFILE_NONE = 0x0, // -x 命令指定 static mode _HF_DYNFILE_INSTR_COUNT = 0x1, // --linux_perf_instr _HF_DYNFILE_BRANCH_COUNT = 0x2, // --linux_perf_branch _HF_DYNFILE_BTS_EDGE = 0x10, // --linux_perf_bts_edge _HF_DYNFILE_IPT_BLOCK = 0x20, // --linux_perf_ipt_block _HF_DYNFILE_SOFT = 0x40, // -z 编译时模式,初始化默认 -fsanitize-coverage } dynFileMethod_t;
2.2.1. 1. SanitizerCoverage 模式
需要编译源码
编译添加CFLAGS: -fsanitize-coverage=trace-pc,trace-pc-guard,trace-cmp,trace-div,indirect-calls
默认方式_HF_DYNFILE_SOFT,通过重定义 SanitizerCoverage 中的函数来实现累加
Pc: __sanitizer_cov_trace_pc_guard
Edge: __sanitizer_cov_trace_pc_guard
Cmp: __sanitizer_cov_trace_cmpN, __sanitizer_cov_trace_switch, __sanitizer_cov_trace_divN, N=(1,2,4,8)
参考:
https://bcain-llvm.readthedocs.io/projects/clang/en/release_39/SanitizerCoverage/
https://github.com/google/sanitizers/wiki/SanitizerCommonFlags
2.2.2. 2. perf模式
不需要编译源码
fuzz时候通过添加参数实现
arch_perfCreate 创建 fd
perf_event_open(&pe, pid, -1, -1, PERF_FLAG_FD_CLOEXEC); dynFileMethod_t perf config fd _HF_DYNFILE_INSTR_COUNT: pe.config = PERF_COUNT_HW_INSTRUCTIONS &run->linux.cpuInstrFd _HF_DYNFILE_BRANCH_COUNT: pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS &run->linux.cpuBranchFd _HF_DYNFILE_BTS_EDGE: pe.type = /sys/bus/event_source/devices/intel_bts/type &run->linux.cpuIptBtsFd _HF_DYNFILE_IPT_BLOCK: pe.type = /sys/bus/event_source/devices/intel_pt/type, pe.config = RTIT_CTL_DISRETC; &run->linux.cpuIptBtsFd PERF_COUNT_HW_INSTRUCTIONS 完整执行的指令数 PERF_COUNT_HW_BRANCH_INSTRUCTIONS 完整执行的分支数
该模式需要硬件支持,简单验证:
在host运行perf命令即可得倒相应数据
./perf stat pwd /home/secret/work Performance counter stats for 'pwd': 0.277524 task-clock (msec) # 0.017 CPUs utilized 1 context-switches # 0.004 M/sec 0 cpu-migrations # 0.000 K/sec 56 page-faults # 0.202 M/sec 989,977 cycles # 3.567 GHz <not supported> stalled-cycles-frontend <not supported> stalled-cycles-backend 656,001 instructions # 0.66 insns per cycle 135,672 branches # 488.866 M/sec 7,481 branch-misses # 5.51% of all branches 0.016769350 seconds time elapsed
instructions 记录着指令数
参考:
http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html
https://software.intel.com/en-us/vtune-amplifier-help-instructions-retired-event
2.3. 关于fuzz运行三种状态
hfuzz->feedback.state
typedef enum { _HF_STATE_UNSET = 0, // 初始化默认值 _HF_STATE_STATIC = 1, // hfuzz->feedback.dynFileMethod == _HF_DYNFILE_NONE _HF_STATE_DYNAMIC_DRY_RUN = 2, // hfuzz->feedback.dynFileMethod != _HF_DYNFILE_NONE _HF_STATE_DYNAMIC_MAIN = 3, // hfuzz->socketFuzzer.enabled == true } fuzzState_t;
2.3.1. 1. socket模式
hfuzz->feedback.state = _HF_STATE_DYNAMIC_MAIN
该模式用于fuzz socket服务
2.3.2. 2. persistent模式(常规模式)
正常设置语料库模式下,状态为
hfuzz->feedback.state = _HF_STATE_DYNAMIC_DRY_RUN
,
执行所有语料库文件且不变异(run->mutationsPerRun = 0 不变异);
之后通过函数 fuzz_setDynamicMainState() 设置状态
hfuzz->feedback.state = _HF_STATE_DYNAMIC_MAIN
(run->mutationsPerRun =
-r指定变异次数,默认6),进入正常fuzz流程。
2.3.3. 3. -x 静态模式
hfuzz->feedback.state = _HF_STATE_STATIC
该模式会设置 hfuzz->feedback.dynFileMethod = _HF_DYNFILE_NONE, 不会使用perf模式,不会产生feedback,主要用于验证样本
如复现某个崩溃样本
./honggfuzz -f crash_dir -x -R ./bug_report --exit_upon_crash -- ./honggfuzz-example/bin/persistent-bin
2.4. 覆盖率报告生成
2.5. 整个fuzz函数流
main -> fuzz_threadsStart -> fuzz_threadNew -> fuzz_fuzzLoop -> subproc_Run -> subproc_New -> arch_launchChild(子进程中执行) bool subproc_Run(run_t* run) { run->timeStartedMillis = util_timeNowMillis(); /* fork子进程,通过ptrace attach 打开perf,用于记录完整执行的指令数 execve执行fuzz实例 */ if (!subproc_New(run)) { LOG_E("subproc_New()"); return false; } /* arch_perfEnable 启用perf,记录执行的指令数 */ arch_prepareParent(run); /* arch_checkWait() -> arch_traceAnalyze()/arch_perfAnalyze() ptrace/perf结果分析 崩溃记录,记录 cpuInstrCnt 和 cpuBranchCnt,关闭perf */ arch_reapChild(run); return true; } static bool subproc_New(run_t* run) { // ... run->pid = arch_fork(run); if (run->pid == -1) { PLOG_E("Couldn't fork"); run->pid = 0; return false; } /* The child process */ if (!run->pid) { // ... /* 系统资源和文件初始化 setrlimit -E fsanitizer参数放入环境变量 putenv */ if (!subproc_PrepareExecv(run)) { LOG_E("subproc_PrepareExecv() failed"); exit(EXIT_FAILURE); } /* 子进程执行 1. prctl(PR_SET_DUMPABLE), 设置可以被attach 2. 关闭ASLR 3. 格式化fuzz实例参数,等待父进程attach,然后调用execve(args[0], (char* const*)args, environ); */ if (!arch_launchChild(run)) { LOG_E("Error launching child process"); kill(run->global->threads.mainPid, SIGTERM); _exit(1); } abort(); } // ... /* 1. fcntl(%d, F_SETOWN_EX),开启perf,用于记录完整执行的指令数 2. arch_attachToNewPid(): ptrace attatch fork子进程 (PTRACE_SEIZE方式,具体实现arch_traceAttach), 并通过 ptrace(PTRACE_CONT) Restart the stopped tracee process */ arch_prepareParentAfterFork(run); // ... return true; }
2.6. trace跟踪子进程
arch_reapChild() -> arch_checkWait() -> arch_traceAnalyze()
通过ptrace挂载子进程,捕获WIFSTOPPED状态,该状态表明目标进程退出,
之后通过 PTRACE_GETEVENTMSG 标志获取退出状态,进行退出状态码判断:
run->mainWorker=true(默认模式下): arch_traceSaveData run->mainWorker=false(Verifier模式下): arch_traceAnalyzeData HF_SAN_EXIT_CODE: arch_traceExitAnalyze
相关API:
long int ptrace(enum __ptrace_request request, pid_t pid, void * addr, void * data) request决定ptrace做什么,pid是被跟踪进程的ID,data存储从进程空间偏移量为addr的地方开始将被读取/写入的数据. pid_t wait4(pid_t pid,int *status,int options,struct rusage *rusage); 获得指定子进程的资源使用信息,通过参数 rusage 获得 PTRACE_SEIZE(since Linux 3.4) Attach to the process specified in pid 相对于 PTRACE_ATTACH, 该方式不会停止目标进程 PTRACE_CONT 让子进程继续运行 PTRACE_GETEVENTMSG (since Linux 2.5.46) 取回数据 arch_traceAnalyze()
3. xcode 调试
需要修改honggfuzz源码目录下的Makefile文件添加调试选项
diff --git a/Makefile b/Makefile index fc5ea74..c6e1fdc 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,8 @@ HFUZZ_CC_SRCS := hfuzz_cc/hfuzz-cc.c COMMON_CFLAGS := -D_GNU_SOURCE -Wall -Werror -Wno-format-truncation -I. COMMON_LDFLAGS := -lm libhfcommon/libhfcommon.a COMMON_SRCS := $(sort $(wildcard *.c)) -CFLAGS ?= -O3 -mtune=native +# CFLAGS ?= -O3 -mtune=native +CFLAGS ?= -g -mtune=native LDFLAGS ?= LIBS_CFLAGS ?= -fPIC -fno-stack-protector GREP_COLOR ?=
之后参考文章 https://blog.csdn.net/kubibo/article/details/25902703
4. 源码分析
4.1. honggfuzz-clang编译器
honggfuzz/hfuzz_cc/hfuzz-cc.c
通过编译器名字(hfuzz-clang, hfuzz-clang++, hfuzz-g++, hfuzz-gcc)来判断使用哪种编译器编译。
hfuzz-clang -> clang hfuzz-clang++ -> clang++ hfuzz-g++ -> g++ hfuzz-gcc -> gcc
之后是参数拼接,主要添加的优化参数列表(clang):
"-Wno-unused-command-line-argument"; "-fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,indirect-calls"; "-mllvm"; "-sanitizer-coverage-prune-blocks=0"; "-mllvm"; "-sanitizer-coverage-level=3"; /* * Make the execution flow more explicit, allowing for more code blocks * (and better code coverage estimates) */ "-fno-inline"; "-fno-builtin"; "-fno-omit-frame-pointer"; "-D__NO_STRING_INLINES"; /* Make it possible to use the libhfnetdriver */ "-DHFND_FUZZING_ENTRY_FUNCTION_CXX(x,y)=" "extern \"C\" int HonggfuzzNetDriver_main(x,y);" "extern const char* LIBHFNETDRIVER_module_netdriver;" "const char** LIBHFNETDRIVER_module_main = &LIBHFNETDRIVER_module_netdriver;" "int HonggfuzzNetDriver_main(x,y)"; "-DHFND_FUZZING_ENTRY_FUNCTION(x,y)=" "int HonggfuzzNetDriver_main(x,y);" "extern const char* LIBHFNETDRIVER_module_netdriver;" "const char** LIBHFNETDRIVER_module_main = &LIBHFNETDRIVER_module_netdriver;" "int HonggfuzzNetDriver_main(x,y)"; /* Intercept common *cmp functions */ "-Wl,--wrap=strcmp"; "-Wl,--wrap=strcasecmp"; "-Wl,--wrap=strncmp"; "-Wl,--wrap=strncasecmp"; "-Wl,--wrap=strstr"; "-Wl,--wrap=strcasestr"; "-Wl,--wrap=memcmp"; "-Wl,--wrap=bcmp"; "-Wl,--wrap=memmem"; "-Wl,--wrap=strcpy"; /* Apache's httpd mem/str cmp functions */ "-Wl,--wrap=ap_cstr_casecmp"; "-Wl,--wrap=ap_cstr_casecmpn"; "-Wl,--wrap=ap_strcasestr"; "-Wl,--wrap=apr_cstr_casecmp"; "-Wl,--wrap=apr_cstr_casecmpn"; /* Frequently used time-constant *SSL functions */ "-Wl,--wrap=CRYPTO_memcmp"; "-Wl,--wrap=OPENSSL_memcmp"; "-Wl,--wrap=OPENSSL_strcasecmp"; "-Wl,--wrap=OPENSSL_strncasecmp"; "-Wl,--wrap=memcmpct"; /* Frequently used libXML2 functions */ "-Wl,--wrap=xmlStrncmp"; "-Wl,--wrap=xmlStrcmp"; "-Wl,--wrap=xmlStrEqual"; "-Wl,--wrap=xmlStrcasecmp"; "-Wl,--wrap=xmlStrncasecmp"; "-Wl,--wrap=xmlStrstr"; "-Wl,--wrap=xmlStrcasestr"; /* Some Samba functions */ "-Wl,--wrap=memcmp_const_time"; "-Wl,--wrap=strcsequal"; /* Pull modules defining the following symbols (if they exist) */ args[j++] = "-Wl,-u,LIBHFNETDRIVER_module_main", args[j++] = "-Wl,-u,LIBHFUZZ_module_instrument"; args[j++] = "-Wl,-u,LIBHFUZZ_module_memorycmp"; "/tmp/libhfnetdriver.uid.crc64.a"; // eg: /tmp/libhfnetdriver.1000.9a0f6dce36be32e.a, libhfnetdriver/libhfnetdriver.a "/tmp/libhfuzz.uid.crc64.a" // eg: /tmp/libhfuzz.1000.cb422fcd8679a683.a, libhfuzz/libhfuzz.a
-fsanitize参数
ASAN(AddressSanitizer) -fsanitize=address: 打开asan内存错误检查 -fno-omit-frame-pointer: 保留函数调用的帧信息,以便分析函数调用关系 UBSAN(UndefinedBehaviorSanitizer) -fsanitize=undefined: 未定义行为检测
4.2. 结构体说明
typedef struct { struct { size_t threadsMax; // -n 指定最大线程数 size_t threadsFinished; uint32_t threadsActiveCnt; pthread_t mainThread; pid_t mainPid; pthread_t threads[_HF_THREAD_MAX]; } threads; struct { const char* inputDir; // -f 原始种子文件目录 DIR* inputDirPtr; // fdopendir(dir_fd) 打开的原始种子目录指针 size_t fileCnt; // 原始种子文件个数 const char* fileExtn; // 文件扩展名, 不能包含 / bool fileCntDone; const char* workDir; // -W 有效变异种子文件输出目录 const char* crashDir; const char* covDirAll; // 默认值为-f指定目录 const char* covDirNew; bool saveUnique; size_t dynfileqCnt; pthread_rwlock_t dynfileq_mutex; TAILQ_HEAD(dyns_t, dynfile_t) dynfileq; } io; struct { int argc; const char* const* cmdline; // -- 后边跟的fuzz样例 bool nullifyStdio; bool fuzzStdin; const char* externalCommand; // -c fuzz样例参数 const char* postExternalCommand; bool netDriver; bool persistent; // -P persistent模式 uint64_t asLimit; uint64_t rssLimit; uint64_t dataLimit; uint64_t coreLimit; bool clearEnv; char* envs[128]; // -E ENV参数,如sanitizers sigset_t waitSigSet; } exe; struct { time_t timeStart; time_t runEndTime; time_t tmOut; // -t timeout time_t lastCovUpdate; bool tmoutVTALRM; } timing; struct { const char* dictionaryFile; TAILQ_HEAD(strq_t, strings_t) dictq; size_t dictionaryCnt; size_t mutationsMax; unsigned mutationsPerRun; size_t maxFileSz; // -F Max File Size } mutate; struct { bool useScreen; char cmdline_txt[65]; int64_t lastDisplayMillis; } display; struct { bool useVerifier; // -V verifier 如果开启,则会验证崩溃样本(最大运行5次) bool exitUponCrash; // --exit_upon_crash 有崩溃直接退出fuzz const char* reportFile; // -R 生成报告文件 pthread_mutex_t report_mutex; bool monitorSIGABRT; size_t dynFileIterExpire; bool only_printable; } cfg; struct { bool enable; // -S sanitizer } sanitizer; struct { fuzzState_t state; feedback_t* feedbackMap; int bbFd; pthread_mutex_t feedback_mutex; const char* blacklistFile; uint64_t* blacklist; size_t blacklistCnt; bool skipFeedbackOnTimeout; dynFileMethod_t dynFileMethod; // -x static mode, feedback 默认 _HF_DYNFILE_SOFT } feedback; struct { size_t mutationsCnt; size_t crashesCnt; size_t uniqueCrashesCnt; size_t verifiedCrashesCnt; size_t blCrashesCnt; size_t timeoutedCnt; } cnts; struct { bool enabled; int serverSocket; int clientSocket; } socketFuzzer; /* For the Linux code */ struct { int exeFd; hwcnt_t hwCnts; // 记录所有fuzz实例的代码覆盖数总和 edge pc cmp uint64_t dynamicCutOffAddr; bool disableRandomization; void* ignoreAddr; size_t numMajorFrames; const char* symsBlFile; char** symsBl; size_t symsBlCnt; const char* symsWlFile; char** symsWl; size_t symsWlCnt; uintptr_t cloneFlags; bool kernelOnly; bool useClone; } linux; /* For the NetBSD code */ struct { void* ignoreAddr; size_t numMajorFrames; const char* symsBlFile; char** symsBl; size_t symsBlCnt; const char* symsWlFile; char** symsWl; size_t symsWlCnt; } netbsd; } honggfuzz_t; fuzzing thread: typedef struct { honggfuzz_t* global; // hfuzz实例 pid_t pid; // 当前fuzz种子线程pid int64_t timeStartedMillis; char origFileName[PATH_MAX]; char crashFileName[PATH_MAX]; uint64_t pc; uint64_t backtrace; uint64_t access; int exception; char report[_HF_REPORT_SIZE]; bool mainWorker; unsigned mutationsPerRun; struct dynfile_t* dynfileqCurrent; // {data: 种子文件内容,size: 长度, pointers: 文件队列} uint8_t* dynamicFile; // 指向name=hfuzz-input的buf, 该buff接受mangle变异的数据 size_t dynamicFileSz; // 种子文件size int dynamicFileFd; // 通过memfd_create创建name=hfuzz-input的匿名文件句柄 int dynamicFileCopyFd; // fuzz种子句柄,执行时会用过/dev/fd/%d方式打开并获取内容 uint32_t fuzzNo; // 编号 int persistentSock; bool waitingForReady; runState_t runState; bool tmOutSignaled; #if !defined(_HF_ARCH_DARWIN) timer_t timerId; #endif // !defined(_HF_ARCH_DARWIN) struct { /* For Linux code */ uint8_t* perfMmapBuf; uint8_t* perfMmapAux; hwcnt_t hwCnts; // 记录当前fuzz实例的代码覆盖数 edge pc cmp int cpuInstrFd; int cpuBranchFd; int cpuIptBtsFd; } linux; struct { /* For NetBSD code */ uint8_t* perfMmapBuf; uint8_t* perfMmapAux; hwcnt_t hwCnts; int cpuInstrFd; int cpuBranchFd; int cpuIptBtsFd; } netbsd; } run_t;
(lldb) print *hfuzz (honggfuzz_t) $5 = { threads = { threadsMax = 2 threadsFinished = 0 threadsActiveCnt = 0 mainThread = 0x000000013f19f380 mainPid = 48586 threads = { [0] = 0x0000000000000000 [1] = 0x0000000000000000 [2] = 0x0000000000000000 [3] = 0x0000000000000000 ... [255] = 0x0000000000000000 ... } } io = { inputDir = 0x00007ffeefbffa3d "/Users/idhyt/Work/sec.ret/gitlab/opensourcefuzz/honggfuzz-example/bin/corpus_2019-02-28_13-48-20/" inputDirPtr = 0x000000013f601af0 fileCnt = 5 fileExtn = 0x000000010002cffb "fuzz" fileCntDone = false workDir = 0x00007ffeefbff9d8 "/Users/idhyt/Work/sec.ret/gitlab/opensourcefuzz/honggfuzz-example/bin/outputs_2019-02-28_13-48-20" crashDir = 0x00007ffeefbff9d8 "/Users/idhyt/Work/sec.ret/gitlab/opensourcefuzz/honggfuzz-example/bin/outputs_2019-02-28_13-48-20" covDirAll = 0x00007ffeefbffa3d "/Users/idhyt/Work/sec.ret/gitlab/opensourcefuzz/honggfuzz-example/bin/corpus_2019-02-28_13-48-20/" covDirNew = 0x0000000000000000 <no value available> saveUnique = true dynfileqCnt = 0 dynfileq_mutex = (__sig = 766030772, __opaque = char [192] @ 0x00007fb4a533fa88) dynfileq = { tqh_first = 0x0000000000000000 tqh_last = 0x0000000100128c68 } } exe = { argc = 1 cmdline = 0x000000013f302e68 nullifyStdio = true fuzzStdin = false externalCommand = 0x0000000000000000 <no value available> postExternalCommand = 0x0000000000000000 <no value available> netDriver = false persistent = true asLimit = 0 rssLimit = 0 dataLimit = 0 coreLimit = 0 clearEnv = false envs = { [0] = 0x000000010005f5f0 "ASAN_OPTIONS=abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:symbolize=1:detect_leaks=0:disable_coredump=0:detect_odr_violation=0" [1] = 0x00000001000605f0 "UBSAN_OPTIONS=abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:symbolize=1:detect_leaks=0:disable_coredump=0:detect_odr_violation=0" [2] = 0x00000001000615f0 "MSAN_OPTIONS=abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:symbolize=1:detect_leaks=0:disable_coredump=0:detect_odr_violation=0" [3] = 0x00000001000625f0 "LSAN_OPTIONS=abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:symbolize=1:detect_leaks=0:disable_coredump=0:detect_odr_violation=0" [4] = 0x0000000000000000 <no value available> [5] = 0x0000000000000000 <no value available> ... [127] = 0x0000000000000000 <no value available> } waitSigSet = 541065216 } timing = (timeStart = 1551337933, runEndTime = 0, tmOut = 10, lastCovUpdate = 1551337933, tmoutVTALRM = false) mutate = { dictionaryFile = 0x0000000000000000 <no value available> dictq = { tqh_first = 0x0000000000000000 tqh_last = 0x0000000100129108 } dictionaryCnt = 0 mutationsMax = 0 mutationsPerRun = 6 maxFileSz = 8192 } display = (useScreen = true, cmdline_txt = char [65] @ 0x00007fb4a5340019, lastDisplayMillis = 1551337933633) cfg = { useVerifier = false exitUponCrash = false reportFile = 0x0000000000000000 <no value available> report_mutex = (__sig = 850045863, __opaque = char [56] @ 0x00007fb4a5340080) monitorSIGABRT = true dynFileIterExpire = 0 only_printable = false } sanitizer = (enable = false) feedback = { state = _HF_STATE_UNSET feedbackMap = 0x0000000142180000 bbFd = 5 feedback_mutex = (__sig = 850045863, __opaque = char [56] @ 0x00007fb4a53400f8) blacklistFile = 0x0000000000000000 <no value available> blacklist = 0x0000000000000000 blacklistCnt = 0 skipFeedbackOnTimeout = false dynFileMethod = _HF_DYNFILE_SOFT } cnts = { mutationsCnt = 0 crashesCnt = 0 uniqueCrashesCnt = 0 verifiedCrashesCnt = 0 blCrashesCnt = 0 timeoutedCnt = 0 } socketFuzzer = (enabled = false, serverSocket = -1, clientSocket = -1) linux = { exeFd = -1 hwCnts = { cpuInstrCnt = 0 cpuBranchCnt = 0 bbCnt = 0 newBBCnt = 0 softCntPc = 0 softCntEdge = 0 softCntCmp = 0 } dynamicCutOffAddr = 18446744073709551615 disableRandomization = true ignoreAddr = 0x0000000000000000 numMajorFrames = 7 symsBlFile = 0x0000000000000000 <no value available> symsBl = 0x0000000000000000 symsBlCnt = 0 symsWlFile = 0x0000000000000000 <no value available> symsWl = 0x0000000000000000 symsWlCnt = 0 cloneFlags = 0 kernelOnly = false useClone = true } netbsd = { ignoreAddr = 0x0000000000000000 numMajorFrames = 7 symsBlFile = 0x0000000000000000 <no value available> symsBl = 0x0000000000000000 symsBlCnt = 0 symsWlFile = 0x0000000000000000 <no value available> symsWl = 0x0000000000000000 symsWlCnt = 0 } }
5. 编译
5.1. 1. 依赖库
sudo apt-get install libbfd-dev libunwind8-dev
### 2. GCC
sudo add-apt-repository ppa:jonathonf/gcc-7.1 sudo apt-get update sudo apt-get install gcc-7 g++-7 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70
5.2. 3. clang
要求 5.0+
sudo apt install clang-6.0
最新版
wget https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/master/checkout_build_install_llvm.sh ./checkout_build_install_llvm.sh
5.3. 4. 编译
git clone https://github.com/google/honggfuzz.git cd honggfuzz make
6. fuzz libxml2
6.1. 1. 依赖库
sudo apt install autoconf libtool liblzma-dev python-dev
6.2. 2. 编译libxml2
git clone https://github.com/GNOME/libxml2.git cd libxml2/ git checkout f8a8c1f59db355b46962577e7b74f1a1e8149dc6 git branch libxml2-2.9.9 git checkout libxml2-2.9.9 ./autogen.sh hfuzz_cc_dir=/path/to/honggfuzz/hfuzz_cc CFLAGS="-g -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-coverage=trace-pc-guard" CC="$hfuzz_cc_dir/hfuzz-clang $CFLAGS" CXX="$hfuzz_cc_dir/hfuzz-clang++ $CFLAGS" CCLD="$hfuzz_cc_dir/hfuzz-clang $CFLAGS" ./configure make -j4 ls .libs/libxml2.a
6.3. 编译测试样例
测试样例: persistent-xml2
cd /path/to/honggfuzz/examples/libxml2 CFLAGS="-g -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-coverage=trace-pc-guard" ./path/to/honggfuzz/hfuzz_cc/hfuzz-clang persistent-xml2.c $CFLAGS -I/path/to/libxml2/include -I/path/to/libxml2 /path/to/libxml2/.libs/libxml2.a /path/to/honggfuzz/libhfuzz/libhfuzz.a -o persistent-xml2
6.4. 执行
mkdir output_dir mkdir corpus_dir echo "test" > ./corpus_dir/origin ./path/to/honggfuzz/honggfuzz -P -S -W ./output_dir -f ./corpus_dir -- ./persistent-xml2 使用字典: ./path/to/honggfuzz/honggfuzz -P -S -w ./xml.dict -W ./output_dir -f ./corpus_dir -- ./persistent-xml2
6.5. issue
- Did you mean '-sanitizer-coverage-level=0'…
clang-5.0
- ASAN
==84373==LeakSanitizer has encountered a fatal error. ==84373==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1 ==84373==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
fuzz去掉 -S 参数
- ubuntu 16.04 apt
Reading package lists... Done E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi' E: Sub-process returned an error code
sudo pkill -KILL appstreamcli wget -P /tmp https://launchpad.net/ubuntu/+archive/primary/+files/appstream_0.9.4-1ubuntu1_amd64.deb https://launchpad.net/ubuntu/+archive/primary/+files/libappstream3_0.9.4-1ubuntu1_amd64.deb sudo dpkg -i /tmp/appstream_0.9.4-1ubuntu1_amd64.deb /tmp/libappstream3_0.9.4-1ubuntu1_amd64.deb
Created: 2017-03-02 Thu 15:53
没有评论:
发表评论