From 89af2ef7a9f1ae1de57a1cdbb7ff2da1de7a943c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Feb 2021 11:15:59 +0100 Subject: update honggfuzz custom mutator --- custom_mutators/honggfuzz/common.h | 3 + custom_mutators/honggfuzz/honggfuzz.h | 7 +- custom_mutators/honggfuzz/mangle.c | 1174 +++++++++++++++------------------ 3 files changed, 529 insertions(+), 655 deletions(-) diff --git a/custom_mutators/honggfuzz/common.h b/custom_mutators/honggfuzz/common.h index e69de29b..c8cf1329 100644 --- a/custom_mutators/honggfuzz/common.h +++ b/custom_mutators/honggfuzz/common.h @@ -0,0 +1,3 @@ +#ifndef LOG_E + #define LOG_E LOG_F +#endif diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h index 9d07fdf4..eb6a3f11 100644 --- a/custom_mutators/honggfuzz/honggfuzz.h +++ b/custom_mutators/honggfuzz/honggfuzz.h @@ -208,6 +208,7 @@ typedef struct { const char* crashDir; const char* covDirNew; bool saveUnique; + bool saveSmaller; size_t dynfileqMaxSz; size_t dynfileqCnt; dynfile_t* dynfileqCurrent; @@ -279,9 +280,9 @@ typedef struct { cmpfeedback_t* cmpFeedbackMap; int cmpFeedbackFd; bool cmpFeedback; - const char* blacklistFile; - uint64_t* blacklist; - size_t blacklistCnt; + const char* blocklistFile; + uint64_t* blocklist; + size_t blocklistCnt; bool skipFeedbackOnTimeout; uint64_t maxCov[4]; dynFileMethod_t dynFileMethod; diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c index 9c3d1ed4..637d428d 100644 --- a/custom_mutators/honggfuzz/mangle.c +++ b/custom_mutators/honggfuzz/mangle.c @@ -39,252 +39,208 @@ #include "libhfcommon/log.h" #include "libhfcommon/util.h" -static inline size_t mangle_LenLeft(run_t *run, size_t off) { - - if (off >= run->dynfile->size) { - - LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); - - } - - return (run->dynfile->size - off - 1); - +static inline size_t mangle_LenLeft(run_t* run, size_t off) { + if (off >= run->dynfile->size) { + LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); + } + return (run->dynfile->size - off - 1); } -/* Get a random value <1:max>, but prefer smaller ones - up to 4KiB */ +/* + * Get a random value <1:max>, but prefer smaller ones + * Based on an idea by https://twitter.com/gamozolabs + */ static inline size_t mangle_getLen(size_t max) { + if (max > _HF_INPUT_MAX_SIZE) { + LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE); + } + if (max == 0) { + LOG_F("max == 0"); + } + if (max == 1) { + return 1; + } - if (max > _HF_INPUT_MAX_SIZE) { - - LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, - (size_t)_HF_INPUT_MAX_SIZE); - - } - - if (max == 0) { LOG_F("max == 0"); } - if (max == 1) { return 1; } - - /* Give 50% chance the the uniform distribution */ - switch (util_rndGet(0, 9)) { - - case 0: - return (size_t)util_rndGet(1, HF_MIN(16, max)); - case 1: - return (size_t)util_rndGet(1, HF_MIN(64, max)); - case 2: - return (size_t)util_rndGet(1, HF_MIN(256, max)); - case 3: - return (size_t)util_rndGet(1, HF_MIN(1024, max)); - case 4: - return (size_t)util_rndGet(1, HF_MIN(4096, max)); - default: - break; - - } - - return (size_t)util_rndGet(1, max); + /* Give 50% chance the the uniform distribution */ + if (util_rnd64() & 1) { + return (size_t)util_rndGet(1, max); + } + /* effectively exprand() */ + return (size_t)util_rndGet(1, util_rndGet(1, max)); } /* Prefer smaller values here, so use mangle_getLen() */ -static inline size_t mangle_getOffSet(run_t *run) { - - return mangle_getLen(run->dynfile->size) - 1; - +static inline size_t mangle_getOffSet(run_t* run) { + return mangle_getLen(run->dynfile->size) - 1; } /* Offset which can be equal to the file size */ -static inline size_t mangle_getOffSetPlus1(run_t *run) { - - size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); - return mangle_getLen(reqlen) - 1; - +static inline size_t mangle_getOffSetPlus1(run_t* run) { + size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); + return mangle_getLen(reqlen) - 1; } -static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to, - size_t len) { - - if (off_from >= run->dynfile->size) { return; } - if (off_to >= run->dynfile->size) { return; } - if (off_from == off_to) { return; } - - size_t len_from = run->dynfile->size - off_from; - len = HF_MIN(len, len_from); +static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) { + if (off_from >= run->dynfile->size) { + return; + } + if (off_to >= run->dynfile->size) { + return; + } + if (off_from == off_to) { + return; + } - size_t len_to = run->dynfile->size - off_to; - len = HF_MIN(len, len_to); + size_t len_from = run->dynfile->size - off_from; + len = HF_MIN(len, len_from); - memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len); + size_t len_to = run->dynfile->size - off_to; + len = HF_MIN(len, len_to); + memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len); } -static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src, - size_t len, bool printable) { - - if (len == 0) { return; } - size_t maxToCopy = run->dynfile->size - off; - if (len > maxToCopy) { len = maxToCopy; } - - memmove(&run->dynfile->data[off], src, len); - if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); } +static inline void mangle_Overwrite( + run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) { + if (len == 0) { + return; + } + size_t maxToCopy = run->dynfile->size - off; + if (len > maxToCopy) { + len = maxToCopy; + } + memmove(&run->dynfile->data[off], src, len); + if (printable) { + util_turnToPrintable(&run->dynfile->data[off], len); + } } -static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len, - bool printable) { - - if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; } - if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { - - len = run->global->mutate.maxInputSz - run->dynfile->size; - - } - - input_setSize(run, run->dynfile->size + len); - mangle_Move(run, off, off + len, run->dynfile->size); - if (printable) { memset(&run->dynfile->data[off], ' ', len); } +static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) { + if (run->dynfile->size >= run->global->mutate.maxInputSz) { + return 0; + } + if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { + len = run->global->mutate.maxInputSz - run->dynfile->size; + } - return len; + input_setSize(run, run->dynfile->size + len); + mangle_Move(run, off, off + len, run->dynfile->size); + if (printable) { + memset(&run->dynfile->data[off], ' ', len); + } + return len; } -static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val, - size_t len, bool printable) { - - len = mangle_Inflate(run, off, len, printable); - mangle_Overwrite(run, off, val, len, printable); - +static inline void mangle_Insert( + run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) { + len = mangle_Inflate(run, off, len, printable); + mangle_Overwrite(run, off, val, len, printable); } -static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len, - bool printable) { - - if (util_rnd64() % 2) { - - mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable); - - } else { - - mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable); - - } - +static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) { + if (util_rnd64() & 1) { + mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable); + } else { + mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable); + } } -static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) { - - size_t off1 = mangle_getOffSet(run); - size_t maxlen1 = run->dynfile->size - off1; - - size_t off2 = mangle_getOffSet(run); - size_t maxlen2 = run->dynfile->size - off2; - - size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); - uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); - defer { - - free(tmpbuf); - - }; - - memcpy(tmpbuf, &run->dynfile->data[off1], len); - memmove(&run->dynfile->data[off1], &run->dynfile->data[off2], len); - memcpy(&run->dynfile->data[off2], tmpbuf, len); - +static inline void mangle_UseValueAt( + run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) { + if (util_rnd64() & 1) { + mangle_Overwrite(run, off, val, len, printable); + } else { + mangle_Insert(run, off, val, len, printable); + } } -static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) { - - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - - /* Use a temp buf, as Insert/Inflate can change source bytes */ - uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); - defer { +static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) { + /* No big deal if those two are overlapping */ + size_t off1 = mangle_getOffSet(run); + size_t maxlen1 = run->dynfile->size - off1; + size_t off2 = mangle_getOffSet(run); + size_t maxlen2 = run->dynfile->size - off2; + size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); - free(tmpbuf); - - }; - - memcpy(tmpbuf, &run->dynfile->data[off], len); - - mangle_UseValue(run, tmpbuf, len, printable); + if (off1 == off2) { + return; + } + for (size_t i = 0; i < (len / 2); i++) { + /* + * First - from the head, next from the tail. Don't worry about layout of the overlapping + * part - there's no good solution to that, and it can be left somewhat scrambled, + * while still preserving the entropy + */ + const uint8_t tmp1 = run->dynfile->data[off2 + i]; + run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i]; + run->dynfile->data[off1 + i] = tmp1; + const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i]; + run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i]; + run->dynfile->data[off1 + (len - 1) - i] = tmp2; + } } -static void mangle_Bytes(run_t *run, bool printable) { - - uint16_t buf; - if (printable) { - - util_rndBufPrintable((uint8_t *)&buf, sizeof(buf)); - - } else { +static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) { + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); - buf = util_rnd64(); - - } - - /* Overwrite with random 1-2-byte values */ - size_t toCopy = util_rndGet(1, 2); - mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable); + /* Use a temp buf, as Insert/Inflate can change source bytes */ + uint8_t* tmpbuf = (uint8_t*)util_Malloc(len); + defer { + free(tmpbuf); + }; + memmove(tmpbuf, &run->dynfile->data[off], len); + mangle_UseValue(run, tmpbuf, len, printable); } -static void mangle_ByteRepeatOverwrite(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t destOff = off + 1; - size_t maxSz = run->dynfile->size - destOff; - - /* No space to repeat */ - if (!maxSz) { - - mangle_Bytes(run, printable); - return; - - } - - size_t len = mangle_getLen(maxSz); - memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); +static void mangle_Bytes(run_t* run, bool printable) { + uint16_t buf; + if (printable) { + util_rndBufPrintable((uint8_t*)&buf, sizeof(buf)); + } else { + buf = util_rnd64(); + } + /* Overwrite with random 1-2-byte values */ + size_t toCopy = util_rndGet(1, 2); + mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable); } -static void mangle_ByteRepeatInsert(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t destOff = off + 1; - size_t maxSz = run->dynfile->size - destOff; +static void mangle_ByteRepeat(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + size_t destOff = off + 1; + size_t maxSz = run->dynfile->size - destOff; - /* No space to repeat */ - if (!maxSz) { - - mangle_Bytes(run, printable); - return; - - } - - size_t len = mangle_getLen(maxSz); - len = mangle_Inflate(run, destOff, len, printable); - memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); + /* No space to repeat */ + if (!maxSz) { + mangle_Bytes(run, printable); + return; + } + size_t len = mangle_getLen(maxSz); + if (util_rnd64() & 0x1) { + len = mangle_Inflate(run, destOff, len, printable); + } + memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); } -static void mangle_Bit(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); - if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); } - +static void mangle_Bit(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); + if (printable) { + util_turnToPrintable(&(run->dynfile->data[off]), 1); + } } static const struct { - - const uint8_t val[8]; - const size_t size; - + const uint8_t val[8]; + const size_t size; } mangleMagicVals[] = { - /* 1B - No endianness */ {"\x00\x00\x00\x00\x00\x00\x00\x00", 1}, {"\x01\x00\x00\x00\x00\x00\x00\x00", 1}, @@ -516,522 +472,436 @@ static const struct { {"\x00\x00\x00\x00\x00\x00\x00\x80", 8}, {"\x01\x00\x00\x00\x00\x00\x00\x80", 8}, {"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, - }; -static void mangle_Magic(run_t *run, bool printable) { - - uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); - mangle_UseValue(run, mangleMagicVals[choice].val, - mangleMagicVals[choice].size, printable); - -} - -static void mangle_StaticDict(run_t *run, bool printable) { - - if (run->global->mutate.dictionaryCnt == 0) { - - mangle_Bytes(run, printable); - return; - - } - - uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); - mangle_UseValue(run, run->global->mutate.dictionary[choice].val, - run->global->mutate.dictionary[choice].len, printable); - +static void mangle_Magic(run_t* run, bool printable) { + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); + mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable); } -static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) { - - if (!run->global->feedback.cmpFeedback) { return NULL; } - cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap; - uint32_t cnt = ATOMIC_GET(cmpf->cnt); - if (cnt == 0) { return NULL; } - if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); } - uint32_t choice = util_rndGet(0, cnt - 1); - *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); - if (*len == 0) { return NULL; } - return cmpf->valArr[choice].val; - +static void mangle_StaticDict(run_t* run, bool printable) { + if (run->global->mutate.dictionaryCnt == 0) { + mangle_Bytes(run, printable); + return; + } + uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); + mangle_UseValue(run, run->global->mutate.dictionary[choice].val, + run->global->mutate.dictionary[choice].len, printable); } -static void mangle_ConstFeedbackDict(run_t *run, bool printable) { - - size_t len; - const uint8_t *val = mangle_FeedbackDict(run, &len); - if (val == NULL) { - - mangle_Bytes(run, printable); - return; - - } - - mangle_UseValue(run, val, len, printable); - +static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) { + if (!run->global->feedback.cmpFeedback) { + return NULL; + } + cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap; + uint32_t cnt = ATOMIC_GET(cmpf->cnt); + if (cnt == 0) { + return NULL; + } + if (cnt > ARRAYSIZE(cmpf->valArr)) { + cnt = ARRAYSIZE(cmpf->valArr); + } + uint32_t choice = util_rndGet(0, cnt - 1); + *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); + if (*len == 0) { + return NULL; + } + return cmpf->valArr[choice].val; } -static void mangle_MemSet(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - int val = - printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX); - - memset(&run->dynfile->data[off], val, len); - +static void mangle_ConstFeedbackDict(run_t* run, bool printable) { + size_t len; + const uint8_t* val = mangle_FeedbackDict(run, &len); + if (val == NULL) { + mangle_Bytes(run, printable); + return; + } + mangle_UseValue(run, val, len, printable); } -static void mangle_RandomOverwrite(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - if (printable) { - - util_rndBufPrintable(&run->dynfile->data[off], len); - - } else { - - util_rndBuf(&run->dynfile->data[off], len); +static void mangle_MemSet(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX); - } + if (util_rnd64() & 1) { + len = mangle_Inflate(run, off, len, printable); + } + memset(&run->dynfile->data[off], val, len); } -static void mangle_RandomInsert(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - - len = mangle_Inflate(run, off, len, printable); - - if (printable) { +static void mangle_MemClr(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + int val = printable ? ' ' : 0; - util_rndBufPrintable(&run->dynfile->data[off], len); - - } else { - - util_rndBuf(&run->dynfile->data[off], len); - - } + if (util_rnd64() & 1) { + len = mangle_Inflate(run, off, len, printable); + } + memset(&run->dynfile->data[off], val, len); } -static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen, - uint64_t range, bool printable) { - - int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range; - - switch (varLen) { - - case 1: { - - run->dynfile->data[off] += delta; - break; +static void mangle_RandomBuf(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + if (util_rnd64() & 1) { + len = mangle_Inflate(run, off, len, printable); } - case 2: { - - int16_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - - val += delta; - - } else { - - /* Foreign endianess */ - val = __builtin_bswap16(val); - val += delta; - val = __builtin_bswap16(val); - - } - - mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); - break; - + if (printable) { + util_rndBufPrintable(&run->dynfile->data[off], len); + } else { + util_rndBuf(&run->dynfile->data[off], len); } +} - case 4: { - - int32_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - - val += delta; - - } else { - - /* Foreign endianess */ - val = __builtin_bswap32(val); - val += delta; - val = __builtin_bswap32(val); - - } - - mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); - break; - +static inline void mangle_AddSubWithRange( + run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) { + int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range; + + switch (varLen) { + case 1: { + run->dynfile->data[off] += delta; + break; + } + case 2: { + int16_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + val += delta; + } else { + /* Foreign endianess */ + val = __builtin_bswap16(val); + val += delta; + val = __builtin_bswap16(val); + } + mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); + break; + } + case 4: { + int32_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + val += delta; + } else { + /* Foreign endianess */ + val = __builtin_bswap32(val); + val += delta; + val = __builtin_bswap32(val); + } + mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); + break; + } + case 8: { + int64_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + val += delta; + } else { + /* Foreign endianess */ + val = __builtin_bswap64(val); + val += delta; + val = __builtin_bswap64(val); + } + mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); + break; + } + default: { + LOG_F("Unknown variable length size: %zu", varLen); + } } +} - case 8: { - - int64_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - - val += delta; - - } else { - - /* Foreign endianess */ - val = __builtin_bswap64(val); - val += delta; - val = __builtin_bswap64(val); - - } - - mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); - break; +static void mangle_AddSub(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + /* 1,2,4,8 */ + size_t varLen = 1U << util_rndGet(0, 3); + if ((run->dynfile->size - off) < varLen) { + varLen = 1; } - default: { - - LOG_F("Unknown variable length size: %zu", varLen); - + uint64_t range; + switch (varLen) { + case 1: + range = 16; + break; + case 2: + range = 4096; + break; + case 4: + range = 1048576; + break; + case 8: + range = 268435456; + break; + default: + LOG_F("Invalid operand size: %zu", varLen); } - } - -} - -static void mangle_AddSub(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - - /* 1,2,4,8 */ - size_t varLen = 1U << util_rndGet(0, 3); - if ((run->dynfile->size - off) < varLen) { varLen = 1; } - - uint64_t range; - switch (varLen) { - - case 1: - range = 16; - break; - case 2: - range = 4096; - break; - case 4: - range = 1048576; - break; - case 8: - range = 268435456; - break; - default: - LOG_F("Invalid operand size: %zu", varLen); - - } - - mangle_AddSubWithRange(run, off, varLen, range, printable); - -} - -static void mangle_IncByte(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - if (printable) { - - run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; - - } else { - - run->dynfile->data[off] += (uint8_t)1UL; - - } - + mangle_AddSubWithRange(run, off, varLen, range, printable); } -static void mangle_DecByte(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - if (printable) { - - run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; - - } else { - - run->dynfile->data[off] -= (uint8_t)1UL; - - } - -} - -static void mangle_NegByte(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - if (printable) { - - run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; - - } else { - - run->dynfile->data[off] = ~(run->dynfile->data[off]); - - } - +static void mangle_IncByte(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + if (printable) { + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; + } else { + run->dynfile->data[off] += (uint8_t)1UL; + } } -static void mangle_Expand(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - size_t len; - if (util_rnd64() % 16) { - - len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); - - } else { - - len = mangle_getLen(run->global->mutate.maxInputSz - off); - - } - - mangle_Inflate(run, off, len, printable); - +static void mangle_DecByte(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + if (printable) { + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; + } else { + run->dynfile->data[off] -= (uint8_t)1UL; + } } -static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) { - - if (run->dynfile->size <= 2U) { return; } - - size_t off_start = mangle_getOffSet(run); - size_t len = mangle_LenLeft(run, off_start); - if (len == 0) { return; } - if (util_rnd64() % 16) { - - len = mangle_getLen(HF_MIN(16, len)); - - } else { - - len = mangle_getLen(len); - - } - - size_t off_end = off_start + len; - size_t len_to_move = run->dynfile->size - off_end; - - mangle_Move(run, off_end, off_start, len_to_move); - input_setSize(run, run->dynfile->size - len); - +static void mangle_NegByte(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + if (printable) { + run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; + } else { + run->dynfile->data[off] = ~(run->dynfile->data[off]); + } } -static void mangle_ASCIINum(run_t *run, bool printable) { - - size_t len = util_rndGet(2, 8); - - char buf[20]; - snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); - - mangle_UseValue(run, (const uint8_t *)buf, len, printable); +static void mangle_Expand(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); + size_t len; + if (util_rnd64() % 16) { + len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); + } else { + len = mangle_getLen(run->global->mutate.maxInputSz - off); + } + mangle_Inflate(run, off, len, printable); } -static void mangle_ASCIINumChange(run_t *run, bool printable) { - - size_t off = mangle_getOffSet(run); - - /* Find a digit */ - for (; off < run->dynfile->size; off++) { - - if (isdigit(run->dynfile->data[off])) { break; } - - } - - if (off == run->dynfile->size) { - - mangle_Bytes(run, printable); - return; - - } - - size_t len = HF_MIN(20, run->dynfile->size - off); - char numbuf[21] = {}; - strncpy(numbuf, (const char *)&run->dynfile->data[off], len); - uint64_t val = (uint64_t)strtoull(numbuf, NULL, 10); - - switch (util_rndGet(0, 5)) { - - case 0: - val += util_rndGet(1, 256); - break; - case 1: - val -= util_rndGet(1, 256); - break; - case 2: - val *= util_rndGet(1, 256); - break; - case 3: - val /= util_rndGet(1, 256); - break; - case 4: - val = ~(val); - break; - case 5: - val = util_rnd64(); - break; - default: - LOG_F("Invalid choice"); - - }; +static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) { + if (run->dynfile->size <= 2U) { + return; + } - len = HF_MIN((size_t)snprintf(numbuf, sizeof(numbuf), "%" PRIu64, val), len); - mangle_Overwrite(run, off, (const uint8_t *)numbuf, len, printable); + size_t off_start = mangle_getOffSet(run); + size_t len = mangle_LenLeft(run, off_start); + if (len == 0) { + return; + } + if (util_rnd64() % 16) { + len = mangle_getLen(HF_MIN(16, len)); + } else { + len = mangle_getLen(len); + } + size_t off_end = off_start + len; + size_t len_to_move = run->dynfile->size - off_end; + mangle_Move(run, off_end, off_start, len_to_move); + input_setSize(run, run->dynfile->size - len); } +static void mangle_ASCIINum(run_t* run, bool printable) { + size_t len = util_rndGet(2, 8); -static void mangle_Splice(run_t *run, bool printable) { - - const uint8_t *buf; - size_t sz = input_getRandomInputAsBuf(run, &buf); - if (!sz) { - - mangle_Bytes(run, printable); - return; - - } - - size_t remoteOff = mangle_getLen(sz) - 1; - size_t len = mangle_getLen(sz - remoteOff); - mangle_UseValue(run, &buf[remoteOff], len, printable); + char buf[20]; + snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); + mangle_UseValue(run, (const uint8_t*)buf, len, printable); } -static void mangle_Resize(run_t *run, bool printable) { - - ssize_t oldsz = run->dynfile->size; - ssize_t newsz = 0; - - uint64_t choice = util_rndGet(0, 32); - switch (choice) { +static void mangle_ASCIINumChange(run_t* run, bool printable) { + size_t off = mangle_getOffSet(run); - case 0: /* Set new size arbitrarily */ - newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); - break; - case 1 ... 4: /* Increase size by a small value */ - newsz = oldsz + (ssize_t)util_rndGet(0, 8); - break; - case 5: /* Increase size by a larger value */ - newsz = oldsz + (ssize_t)util_rndGet(9, 128); - break; - case 6 ... 9: /* Decrease size by a small value */ - newsz = oldsz - (ssize_t)util_rndGet(0, 8); - break; - case 10: /* Decrease size by a larger value */ - newsz = oldsz - (ssize_t)util_rndGet(9, 128); - break; - case 11 ... 32: /* Do nothing */ - newsz = oldsz; - break; - default: - LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); - break; - - } - - if (newsz < 1) { newsz = 1; } - if (newsz > (ssize_t)run->global->mutate.maxInputSz) { - - newsz = run->global->mutate.maxInputSz; + /* Find a digit */ + for (; off < run->dynfile->size; off++) { + if (isdigit(run->dynfile->data[off])) { + break; + } + } + size_t left = run->dynfile->size - off; + if (left == 0) { + return; + } - } + size_t len = 0; + uint64_t val = 0; + /* 20 is maximum lenght of a string representing a 64-bit unsigned value */ + for (len = 0; (len < 20) && (len < left); len++) { + char c = run->dynfile->data[off + len]; + if (!isdigit(c)) { + break; + } + val *= 10; + val += (c - '0'); + } - input_setSize(run, (size_t)newsz); - if (newsz > oldsz) { + switch (util_rndGet(0, 7)) { + case 0: + val++; + break; + case 1: + val--; + break; + case 2: + val *= 2; + break; + case 3: + val /= 2; + break; + case 4: + val = util_rnd64(); + break; + case 5: + val += util_rndGet(1, 256); + break; + case 6: + val -= util_rndGet(1, 256); + break; + case 7: + val = ~(val); + break; + default: + LOG_F("Invalid choice"); + }; + + char buf[20]; + snprintf(buf, sizeof(buf), "%-19" PRIu64, val); + + mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable); +} + +static void mangle_Splice(run_t* run, bool printable) { + if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) { + mangle_Bytes(run, printable); + return; + } - if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); } + size_t sz = 0; + const uint8_t* buf = input_getRandomInputAsBuf(run, &sz); + if (!buf) { + LOG_E("input_getRandomInputAsBuf() returned no input"); + mangle_Bytes(run, printable); + return; + } + if (!sz) { + mangle_Bytes(run, printable); + return; + } - } + size_t remoteOff = mangle_getLen(sz) - 1; + size_t len = mangle_getLen(sz - remoteOff); + mangle_UseValue(run, &buf[remoteOff], len, printable); +} + +static void mangle_Resize(run_t* run, bool printable) { + ssize_t oldsz = run->dynfile->size; + ssize_t newsz = 0; + + uint64_t choice = util_rndGet(0, 32); + switch (choice) { + case 0: /* Set new size arbitrarily */ + newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); + break; + case 1 ... 4: /* Increase size by a small value */ + newsz = oldsz + (ssize_t)util_rndGet(0, 8); + break; + case 5: /* Increase size by a larger value */ + newsz = oldsz + (ssize_t)util_rndGet(9, 128); + break; + case 6 ... 9: /* Decrease size by a small value */ + newsz = oldsz - (ssize_t)util_rndGet(0, 8); + break; + case 10: /* Decrease size by a larger value */ + newsz = oldsz - (ssize_t)util_rndGet(9, 128); + break; + case 11 ... 32: /* Do nothing */ + newsz = oldsz; + break; + default: + LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); + break; + } + if (newsz < 1) { + newsz = 1; + } + if (newsz > (ssize_t)run->global->mutate.maxInputSz) { + newsz = run->global->mutate.maxInputSz; + } + input_setSize(run, (size_t)newsz); + if (newsz > oldsz) { + if (printable) { + memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); + } + } } -void mangle_mangleContent(run_t *run, int speed_factor) { - - static void (*const mangleFuncs[])(run_t * run, bool printable) = { - - /* Every *Insert or Expand expands file, so add more Shrink's */ - mangle_Shrink, - mangle_Shrink, - mangle_Shrink, - mangle_Shrink, - mangle_Expand, - mangle_Bit, - mangle_IncByte, - mangle_DecByte, - mangle_NegByte, - mangle_AddSub, - mangle_MemSet, - mangle_MemSwap, - mangle_MemCopy, - mangle_Bytes, - mangle_ASCIINum, - mangle_ASCIINumChange, - mangle_ByteRepeatOverwrite, - mangle_ByteRepeatInsert, - mangle_Magic, - mangle_StaticDict, - mangle_ConstFeedbackDict, - mangle_RandomOverwrite, - mangle_RandomInsert, - mangle_Splice, - - }; - - if (run->mutationsPerRun == 0U) { return; } - if (run->dynfile->size == 0U) { - - mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); - - } - - uint64_t changesCnt; - - if (speed_factor < 5) { - - changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); - - } else if (speed_factor < 10) { - - changesCnt = run->global->mutate.mutationsPerRun; - - } else { - - changesCnt = HF_MIN(speed_factor, 12); - changesCnt = HF_MAX(changesCnt, run->global->mutate.mutationsPerRun); - - } - - /* If last coverage acquisition was more than 5 secs ago, use splicing more - * frequently */ - if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { - - if (util_rnd64() % 2) { - - mangle_Splice(run, run->global->cfg.only_printable); - +void mangle_mangleContent(run_t* run, int speed_factor) { + static void (*const mangleFuncs[])(run_t * run, bool printable) = { + mangle_Shrink, + mangle_Expand, + mangle_Bit, + mangle_IncByte, + mangle_DecByte, + mangle_NegByte, + mangle_AddSub, + mangle_MemSet, + mangle_MemClr, + mangle_MemSwap, + mangle_MemCopy, + mangle_Bytes, + mangle_ASCIINum, + mangle_ASCIINumChange, + mangle_ByteRepeat, + mangle_Magic, + mangle_StaticDict, + mangle_ConstFeedbackDict, + mangle_RandomBuf, + mangle_Splice, + }; + + if (run->mutationsPerRun == 0U) { + return; + } + if (run->dynfile->size == 0U) { + mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); } - } - - for (uint64_t x = 0; x < changesCnt; x++) { + uint64_t changesCnt = run->global->mutate.mutationsPerRun; - uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); - mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable); + if (speed_factor < 5) { + changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); + } else if (speed_factor < 10) { + changesCnt = run->global->mutate.mutationsPerRun; + } else { + changesCnt = HF_MIN(speed_factor, 10); + changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5)); + } - } + /* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */ + if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { + if (util_rnd64() & 0x1) { + mangle_Splice(run, run->global->cfg.only_printable); + } + } - wmb(); + for (uint64_t x = 0; x < changesCnt; x++) { + if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) { + /* + * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary + * exists. If so, give it 50% chance of being used among all mangling functions. + */ + mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable); + } else { + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); + mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable); + } + } + wmb(); } - -- cgit 1.4.1 From 1a713ff4205672bf1bb6f444e9e8ada39472471c Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Thu, 18 Feb 2021 19:39:46 +0100 Subject: fix qemu AFL_ENTRYPOINT for arm 32 and 64 bit --- test/test-qemu-mode.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh index 0cd6ef40..85578d55 100755 --- a/test/test-qemu-mode.sh +++ b/test/test-qemu-mode.sh @@ -39,14 +39,7 @@ test -e ../afl-qemu-trace && { $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds" { { - if file test-instr | grep -q "32-bit"; then - # for 32-bit reduce 8 nibbles to the lower 7 nibbles - ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'` - else - # for 64-bit reduce 16 nibbles to the lower 9 nibbles - ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'` - fi - export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}` + export AFL_ENTRYPOINT=`printf 1 | AFL_DEBUG=1 ../afl-qemu-trace ./test-instr 2>&1 >/dev/null | awk '/forkserver/{print $4; exit}'` $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr) ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr unset AFL_ENTRYPOINT -- cgit 1.4.1 From d6fe6b953758de193815ebcdd3d9ce825e3ffd27 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 10:49:36 +0100 Subject: qemuafl --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index b0d4fd45..b9e8fe7e 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -213f3b27dd +3e13e0ed44 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 213f3b27..3e13e0ed 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 213f3b27dd099ef352181c48cd75c0f20a73e3f0 +Subproject commit 3e13e0ed4437de0ff62385420504414bd7b14a96 -- cgit 1.4.1 From 3195119dada6cfb35b52bd2a4d8bc5fe9f5d560d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 15:03:10 +0100 Subject: pointer to cite in readme --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 00095390..394193d2 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ mutations, more and better instrumentation, custom module support, etc. If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/) - on the website. + on the website. To cite our work, look at the [Cite](#cite) section. ## Major changes in afl++ 3.0 @@ -1167,6 +1167,11 @@ Thank you! ## Cite If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20: + ++ Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020. + +Bibtex: + ``` @inproceedings {AFLplusplus-Woot20, author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse}, -- cgit 1.4.1 From 5edfb7ba85965d05f73ee8c50614cc9fdb3932d6 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 15:04:53 +0100 Subject: nicer bib --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 394193d2..aacae1b5 100644 --- a/README.md +++ b/README.md @@ -1172,7 +1172,7 @@ If you use AFLplusplus in scientific work, consider citing [our paper](https://w Bibtex: -``` +```bibtex @inproceedings {AFLplusplus-Woot20, author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse}, title = {{AFL++}: Combining Incremental Steps of Fuzzing Research}, -- cgit 1.4.1 From aaf5fcd98a7c713ab8b6ae554babbf74bd92374b Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 19 Feb 2021 09:18:59 -0500 Subject: Remove self-referential symlink --- custom_mutators/honggfuzz/honggfuzz.h | 2 +- custom_mutators/honggfuzz/libhfcommon | 1 - custom_mutators/honggfuzz/mangle.c | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) delete mode 120000 custom_mutators/honggfuzz/libhfcommon diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h index 9d07fdf4..88f5e47c 100644 --- a/custom_mutators/honggfuzz/honggfuzz.h +++ b/custom_mutators/honggfuzz/honggfuzz.h @@ -36,7 +36,7 @@ #include #include -#include "libhfcommon/util.h" +#include "util.h" #define PROG_NAME "honggfuzz" #define PROG_VERSION "2.3" diff --git a/custom_mutators/honggfuzz/libhfcommon b/custom_mutators/honggfuzz/libhfcommon deleted file mode 120000 index 945c9b46..00000000 --- a/custom_mutators/honggfuzz/libhfcommon +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c index 9c3d1ed4..91d885a1 100644 --- a/custom_mutators/honggfuzz/mangle.c +++ b/custom_mutators/honggfuzz/mangle.c @@ -35,9 +35,9 @@ #include #include "input.h" -#include "libhfcommon/common.h" -#include "libhfcommon/log.h" -#include "libhfcommon/util.h" +#include "common.h" +#include "log.h" +#include "util.h" static inline size_t mangle_LenLeft(run_t *run, size_t off) { -- cgit 1.4.1 From 4290cb587763b334c7fb1213bc50dada8d62765d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 16:07:47 +0100 Subject: fix hongg mutator API change --- custom_mutators/honggfuzz/input.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_mutators/honggfuzz/input.h b/custom_mutators/honggfuzz/input.h index 7b0c55ae..09712f54 100644 --- a/custom_mutators/honggfuzz/input.h +++ b/custom_mutators/honggfuzz/input.h @@ -77,11 +77,11 @@ static inline uint64_t util_rndGet(uint64_t min, uint64_t max) { } static inline uint64_t util_rnd64() { return rand_below(afl_struct, 1 << 30); } -static inline size_t input_getRandomInputAsBuf(run_t *run, const uint8_t **buf) { - *buf = queue_input; +static inline const uint8_t* input_getRandomInputAsBuf(run_t* run, size_t* len) { + *len = queue_input_size; run->dynfile->data = queue_input; run->dynfile->size = queue_input_size; - return queue_input_size; + return queue_input; } static inline void input_setSize(run_t* run, size_t sz) { run->dynfile->size = sz; -- cgit 1.4.1 From 6998489b26fc87461e1036903ffa7e6496e2b2e9 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 18:21:10 +0100 Subject: Revert "Remove self-referential symlink" This reverts commit aaf5fcd98a7c713ab8b6ae554babbf74bd92374b. --- custom_mutators/honggfuzz/honggfuzz.h | 2 +- custom_mutators/honggfuzz/libhfcommon | 1 + custom_mutators/honggfuzz/mangle.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) create mode 120000 custom_mutators/honggfuzz/libhfcommon diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h index 62c30f2f..eb6a3f11 100644 --- a/custom_mutators/honggfuzz/honggfuzz.h +++ b/custom_mutators/honggfuzz/honggfuzz.h @@ -36,7 +36,7 @@ #include #include -#include "util.h" +#include "libhfcommon/util.h" #define PROG_NAME "honggfuzz" #define PROG_VERSION "2.3" diff --git a/custom_mutators/honggfuzz/libhfcommon b/custom_mutators/honggfuzz/libhfcommon new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/custom_mutators/honggfuzz/libhfcommon @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c index db339305..637d428d 100644 --- a/custom_mutators/honggfuzz/mangle.c +++ b/custom_mutators/honggfuzz/mangle.c @@ -35,9 +35,9 @@ #include #include "input.h" -#include "common.h" -#include "log.h" -#include "util.h" +#include "libhfcommon/common.h" +#include "libhfcommon/log.h" +#include "libhfcommon/util.h" static inline size_t mangle_LenLeft(run_t* run, size_t off) { if (off >= run->dynfile->size) { -- cgit 1.4.1 From 17211253b2298958dfbd9dae79acf96a4d9ca32d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 18:25:24 +0100 Subject: libhfcommon not anymore a symlink --- custom_mutators/honggfuzz/common.h | 3 --- custom_mutators/honggfuzz/libhfcommon | 1 - custom_mutators/honggfuzz/libhfcommon/common.h | 3 +++ custom_mutators/honggfuzz/libhfcommon/log.h | 1 + custom_mutators/honggfuzz/libhfcommon/util.h | 1 + custom_mutators/honggfuzz/log.h | 1 - custom_mutators/honggfuzz/util.h | 1 - 7 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 custom_mutators/honggfuzz/common.h delete mode 120000 custom_mutators/honggfuzz/libhfcommon create mode 100644 custom_mutators/honggfuzz/libhfcommon/common.h create mode 120000 custom_mutators/honggfuzz/libhfcommon/log.h create mode 120000 custom_mutators/honggfuzz/libhfcommon/util.h delete mode 120000 custom_mutators/honggfuzz/log.h delete mode 120000 custom_mutators/honggfuzz/util.h diff --git a/custom_mutators/honggfuzz/common.h b/custom_mutators/honggfuzz/common.h deleted file mode 100644 index c8cf1329..00000000 --- a/custom_mutators/honggfuzz/common.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef LOG_E - #define LOG_E LOG_F -#endif diff --git a/custom_mutators/honggfuzz/libhfcommon b/custom_mutators/honggfuzz/libhfcommon deleted file mode 120000 index 945c9b46..00000000 --- a/custom_mutators/honggfuzz/libhfcommon +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/custom_mutators/honggfuzz/libhfcommon/common.h b/custom_mutators/honggfuzz/libhfcommon/common.h new file mode 100644 index 00000000..c8cf1329 --- /dev/null +++ b/custom_mutators/honggfuzz/libhfcommon/common.h @@ -0,0 +1,3 @@ +#ifndef LOG_E + #define LOG_E LOG_F +#endif diff --git a/custom_mutators/honggfuzz/libhfcommon/log.h b/custom_mutators/honggfuzz/libhfcommon/log.h new file mode 120000 index 00000000..51e19654 --- /dev/null +++ b/custom_mutators/honggfuzz/libhfcommon/log.h @@ -0,0 +1 @@ +common.h \ No newline at end of file diff --git a/custom_mutators/honggfuzz/libhfcommon/util.h b/custom_mutators/honggfuzz/libhfcommon/util.h new file mode 120000 index 00000000..51e19654 --- /dev/null +++ b/custom_mutators/honggfuzz/libhfcommon/util.h @@ -0,0 +1 @@ +common.h \ No newline at end of file diff --git a/custom_mutators/honggfuzz/log.h b/custom_mutators/honggfuzz/log.h deleted file mode 120000 index 51e19654..00000000 --- a/custom_mutators/honggfuzz/log.h +++ /dev/null @@ -1 +0,0 @@ -common.h \ No newline at end of file diff --git a/custom_mutators/honggfuzz/util.h b/custom_mutators/honggfuzz/util.h deleted file mode 120000 index 51e19654..00000000 --- a/custom_mutators/honggfuzz/util.h +++ /dev/null @@ -1 +0,0 @@ -common.h \ No newline at end of file -- cgit 1.4.1 From 89cf94f0e6afd4d360f7f139f16a6730a07b478d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 20:33:12 +0100 Subject: suggested env vars for lazy ppl --- include/common.h | 1 + qemu_mode/libqasan/dlmalloc.c | 5 ++ src/afl-common.c | 116 ++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 2 + 4 files changed, 124 insertions(+) diff --git a/include/common.h b/include/common.h index bb8831f2..cd728536 100644 --- a/include/common.h +++ b/include/common.h @@ -39,6 +39,7 @@ #define STRINGIFY_VAL_SIZE_MAX (16) void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); +void print_suggested_envs(char *mispelled_env); void check_environment_vars(char **env); char **argv_cpy_dup(int argc, char **argv); diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index bace0ff6..aff58ad5 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3917,6 +3917,7 @@ static void internal_malloc_stats(mstate m) { \ } else if (RTCHECK(B == smallbin_at(M, I) || \ \ + \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4128,6 +4129,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4144,6 +4146,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4156,12 +4159,14 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-common.c b/src/afl-common.c index 589aac71..0b38b222 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -518,6 +518,120 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) { } +#define HELPER_MIN3(a, b, c) \ + ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) + +// from +// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C +static int string_distance_levenshtein(char *s1, char *s2) { + + unsigned int s1len, s2len, x, y, lastdiag, olddiag; + s1len = strlen(s1); + s2len = strlen(s2); + unsigned int column[s1len + 1]; + for (y = 1; y <= s1len; y++) + column[y] = y; + for (x = 1; x <= s2len; x++) { + + column[0] = x; + for (y = 1, lastdiag = x - 1; y <= s1len; y++) { + + olddiag = column[y]; + column[y] = HELPER_MIN3(column[y] + 1, column[y - 1] + 1, + lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1)); + lastdiag = olddiag; + + } + + } + + return column[s1len]; + +} + +#undef HELPER_MIN3 + +void print_suggested_envs(char *mispelled_env) { + + size_t env_name_len = + strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix + char *env_name = ck_alloc(env_name_len + 1); + memcpy(env_name, mispelled_env + 4, env_name_len); + + char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); + + int j; + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + + char *afl_env = afl_environment_variables[j] + 4; + + int distance = string_distance_levenshtein(afl_env, env_name); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + size_t afl_env_len = strlen(afl_env); + char * reduced = ck_alloc(afl_env_len + 1); + + size_t start = 0; + while (start < afl_env_len) { + + size_t end = start + strcspn(afl_env + start, "_") + 1; + memcpy(reduced, afl_env, start); + if (end < afl_env_len) + memcpy(reduced + start, afl_env + end, afl_env_len - end); + reduced[afl_env_len - end + start] = 0; + + int distance = string_distance_levenshtein(reduced, env_name); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + start = end; + + }; + + } + + char * reduced = ck_alloc(env_name_len + 1); + size_t start = 0; + while (start < env_name_len) { + + size_t end = start + strcspn(env_name + start, "_") + 1; + memcpy(reduced, env_name, start); + if (end < env_name_len) + memcpy(reduced + start, env_name + end, env_name_len - end); + reduced[env_name_len - end + start] = 0; + + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + + int distance = string_distance_levenshtein( + afl_environment_variables[j] + 4, reduced); + if (distance <= 3 && seen[j] == 0) { + + SAYF("Did you mean %s?\n", afl_environment_variables[j]); + seen[j] = 1; + + } + + } + + start = end; + + }; + + ck_free(env_name); + ck_free(reduced); + ck_free(seen); + +} + void check_environment_vars(char **envp) { if (be_quiet) { return; } @@ -587,6 +701,8 @@ void check_environment_vars(char **envp) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; + print_suggested_envs(env); + } } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 5040e3ef..3d36e712 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -486,6 +486,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; + print_suggested_envs(env); + } } -- cgit 1.4.1 From 62767a42dc2101a67eeb723ca94f5bf853525d60 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 20:40:38 +0100 Subject: improved env suggestions --- src/afl-common.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index 0b38b222..531753c2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -551,6 +551,8 @@ static int string_distance_levenshtein(char *s1, char *s2) { #undef HELPER_MIN3 +#define ENV_SIMILARITY_TRESHOLD 3 + void print_suggested_envs(char *mispelled_env) { size_t env_name_len = @@ -559,20 +561,28 @@ void print_suggested_envs(char *mispelled_env) { memcpy(env_name, mispelled_env + 4, env_name_len); char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); + int found = 0; int j; for (j = 0; afl_environment_variables[j] != NULL; ++j) { char *afl_env = afl_environment_variables[j] + 4; - int distance = string_distance_levenshtein(afl_env, env_name); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; + found = 1; } + + } + + if (found) goto cleanup; + + for (j = 0; afl_environment_variables[j] != NULL; ++j) { + char *afl_env = afl_environment_variables[j] + 4; size_t afl_env_len = strlen(afl_env); char * reduced = ck_alloc(afl_env_len + 1); @@ -586,10 +596,11 @@ void print_suggested_envs(char *mispelled_env) { reduced[afl_env_len - end + start] = 0; int distance = string_distance_levenshtein(reduced, env_name); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; + found = 1; } @@ -599,6 +610,8 @@ void print_suggested_envs(char *mispelled_env) { } + if (found) goto cleanup; + char * reduced = ck_alloc(env_name_len + 1); size_t start = 0; while (start < env_name_len) { @@ -613,7 +626,7 @@ void print_suggested_envs(char *mispelled_env) { int distance = string_distance_levenshtein( afl_environment_variables[j] + 4, reduced); - if (distance <= 3 && seen[j] == 0) { + if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); seen[j] = 1; @@ -626,8 +639,10 @@ void print_suggested_envs(char *mispelled_env) { }; - ck_free(env_name); ck_free(reduced); + +cleanup: + ck_free(env_name); ck_free(seen); } -- cgit 1.4.1 From d941da33aebd04d4552e9d4313b946e41234aa52 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 19 Feb 2021 21:20:33 +0100 Subject: qemuafl --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index b9e8fe7e..1152380c 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -3e13e0ed44 +e36a30ebca diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 3e13e0ed..e36a30eb 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 3e13e0ed4437de0ff62385420504414bd7b14a96 +Subproject commit e36a30ebca57ca433a5d6e20b1a32975aabb761b -- cgit 1.4.1 From 100aac4dd39012750036b2fd71eed5b21959f693 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 20 Feb 2021 14:15:38 +0100 Subject: -t help --- qemu_mode/qemuafl | 2 +- src/afl-fuzz.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index e36a30eb..213f3b27 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit e36a30ebca57ca433a5d6e20b1a32975aabb761b +Subproject commit 213f3b27dd099ef352181c48cd75c0f20a73e3f0 diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8eb3625b..e3e9007d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -103,7 +103,8 @@ static void usage(u8 *argv0, int more_help) { " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" + " -t msec - timeout for each run (auto-scaled, 50-... ms, default %u ms)\n" + " add a '+' to skip over seeds running longer.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" " -Q - use binary-only instrumentation (QEMU mode)\n" -- cgit 1.4.1 From 871c3c91ec7c462cf3024e48a5ae0d35770fc153 Mon Sep 17 00:00:00 2001 From: "R. Elliott Childre" Date: Sat, 20 Feb 2021 19:24:28 -0500 Subject: Improve LLVM build instructions * Enable shell highlighting on code block * Shallow clone of source due to extensive history * Line break and sort the CMake options for visibility * Disable most extraneous options (e.g. docs, tests, benchmarks, clang-tools-extra, OpenCL interface) * Only build for the host architecture by default * Support other sub-make interfaces, like the recommended Ninja Build System * Harden against paths with spaces * Prefer linking against the newly built LLVM libraries by prepending to LD_LIBRARY_PATH --- instrumentation/README.lto.md | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index a2814173..81c82c4b 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -88,16 +88,35 @@ apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \ ### Building llvm yourself (version 12) Building llvm from github takes quite some long time and is not painless: -``` +```sh sudo apt install binutils-dev # this is *essential*! -git clone https://github.com/llvm/llvm-project +git clone --depth=1 https://github.com/llvm/llvm-project cd llvm-project mkdir build cd build -cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DCMAKE_BUILD_TYPE=Release -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/ -make -j $(nproc) -export PATH=`pwd`/bin:$PATH -export LLVM_CONFIG=`pwd`/bin/llvm-config + +# Add -G Ninja if ninja-build installed +# "Building with ninja significantly improves your build time, especially with +# incremental builds, and improves your memory usage." +cmake \ + -DCLANG_INCLUDE_DOCS="OFF" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_BINUTILS_INCDIR=/usr/include/ \ + -DLLVM_BUILD_LLVM_DYLIB="ON" \ + -DLLVM_ENABLE_BINDINGS="OFF" \ + -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;libcxx;libcxxabi;libunwind;lld' \ + -DLLVM_ENABLE_WARNINGS="OFF" \ + -DLLVM_INCLUDE_BENCHMARKS="OFF" \ + -DLLVM_INCLUDE_DOCS="OFF" \ + -DLLVM_INCLUDE_EXAMPLES="OFF" \ + -DLLVM_INCLUDE_TESTS="OFF" \ + -DLLVM_LINK_LLVM_DYLIB="ON" \ + -DLLVM_TARGETS_TO_BUILD="host" \ + ../llvm/ +cmake --build . --parallel +export PATH="$(pwd)/bin:$PATH" +export LLVM_CONFIG="$(pwd)/bin/llvm-config" +export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" cd /path/to/AFLplusplus/ make sudo make install -- cgit 1.4.1 From b957218a3aad95af02a4da8207c7dabb893d4dc8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 11:29:54 +0100 Subject: more attuned colorize repace --- TODO.md | 5 +---- src/afl-fuzz-redqueen.c | 31 ++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/TODO.md b/TODO.md index 890a481a..4615c456 100644 --- a/TODO.md +++ b/TODO.md @@ -6,16 +6,13 @@ - CPU affinity for many cores? There seems to be an issue > 96 cores - afl-plot to support multiple plot_data - afl_custom_fuzz_splice_optin() + - afl_custom_splice() - intel-pt tracer ## Further down the road afl-fuzz: - setting min_len/max_len/start_offset/end_offset limits for mutation output - - add __sanitizer_cov_trace_cmp* support via shmem - -llvm_mode: - - add __sanitizer_cov_trace_cmp* support qemu_mode: - non colliding instrumentation diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 3ac7ba11..d77baf25 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -205,14 +205,31 @@ static void type_replace(afl_state_t *afl, u8 *buf, u32 len) { case '\t': c = ' '; break; - /* - case '\r': - case '\n': - // nothing ... - break; - */ + case '\r': + c = '\n'; + break; + case '\n': + c = '\r'; + break; + case 0: + c = 1; + break; + case 1: + c = 0; + break; + case 0xff: + c = 0; + break; default: - c = (buf[i] ^ 0xff); + if (buf[i] < 32) { + + c = (buf[i] ^ 0x1f); + + } else { + + c = (buf[i] ^ 0x7f); // we keep the highest bit + + } } -- cgit 1.4.1 From 974aab6cf6aa4ae34ee73bdceed1bd44a212fc5e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 17:53:09 +0100 Subject: cmplog config.h -> -l option --- include/afl-fuzz.h | 1 + include/config.h | 9 ++---- src/afl-common.c | 8 ++--- src/afl-fuzz-redqueen.c | 83 +++++++++++++++++++++++++------------------------ src/afl-fuzz.c | 46 ++++++++++++++++++++------- 5 files changed, 85 insertions(+), 62 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1d5ec1f0..10d94fed 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -649,6 +649,7 @@ typedef struct afl_state { u32 cmplog_max_filesize; u32 cmplog_lvl; u32 colorize_success; + u8 cmplog_enable_arith, cmplog_enable_transform; struct afl_pass_stat *pass_stats; struct cmp_map * orig_cmp_map; diff --git a/include/config.h b/include/config.h index 9f7db04d..535ce0d3 100644 --- a/include/config.h +++ b/include/config.h @@ -42,13 +42,8 @@ * */ -/* Enable arithmetic compare solving for both branches */ -#define CMPLOG_SOLVE_ARITHMETIC - -/* Enable transform following (XOR/ADD/SUB manipulations, hex en/decoding) */ -#define CMPLOG_SOLVE_TRANSFORM - -/* if TRANSFORM is enabled, this additionally enables base64 en/decoding */ +/* if TRANSFORM is enabled with '-l T', this additionally enables base64 + encoding/decoding */ // #define CMPLOG_SOLVE_TRANSFORM_BASE64 /* If a redqueen pass finds more than one solution, try to combine them? */ diff --git a/src/afl-common.c b/src/afl-common.c index 531753c2..ce63c262 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -561,13 +561,13 @@ void print_suggested_envs(char *mispelled_env) { memcpy(env_name, mispelled_env + 4, env_name_len); char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *)); - int found = 0; + int found = 0; int j; for (j = 0; afl_environment_variables[j] != NULL; ++j) { char *afl_env = afl_environment_variables[j] + 4; - int distance = string_distance_levenshtein(afl_env, env_name); + int distance = string_distance_levenshtein(afl_env, env_name); if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) { SAYF("Did you mean %s?\n", afl_environment_variables[j]); @@ -575,14 +575,14 @@ void print_suggested_envs(char *mispelled_env) { found = 1; } - + } if (found) goto cleanup; for (j = 0; afl_environment_variables[j] != NULL; ++j) { - char *afl_env = afl_environment_variables[j] + 4; + char * afl_env = afl_environment_variables[j] + 4; size_t afl_env_len = strlen(afl_env); char * reduced = ck_alloc(afl_env_len + 1); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index d77baf25..1ab5f996 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -30,7 +30,6 @@ //#define _DEBUG //#define CMPLOG_INTROSPECTION -#define CMPLOG_COMBINE // CMP attribute enum enum { @@ -523,7 +522,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -#ifdef CMPLOG_SOLVE_TRANSFORM +//#ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -608,7 +607,7 @@ static int is_hex(const char *str) { } - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // tests 4 bytes at location static int is_base64(const char *str) { @@ -721,10 +720,10 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } - #endif - #endif +//#endif + static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -748,9 +747,9 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // o_pattern, pattern, repl, changed_val, idx, taint_len, // h->shape + 1, attr); -#ifdef CMPLOG_SOLVE_TRANSFORM + //#ifdef CMPLOG_SOLVE_TRANSFORM // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 - if (lvl & LVL3) { + if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 * endptr; u8 use_num = 0, use_unum = 0; @@ -771,11 +770,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - #ifdef _DEBUG +#ifdef _DEBUG if (idx == 0) fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n", afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern); - #endif +#endif // num is likely not pattern as atoi("AAA") will be zero... if (use_num && ((u64)num == pattern || !num)) { @@ -1060,7 +1059,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } -#endif + //#endif // we only allow this for ascii2integer (above) so leave if this is the case if (unlikely(pattern == o_pattern)) { return 0; } @@ -1215,8 +1214,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) -#ifdef CMPLOG_SOLVE_ARITHMETIC - if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; } + //#ifdef CMPLOG_SOLVE_ARITHMETIC + if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { + + return 0; + + } if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { @@ -1321,11 +1324,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, double *f = (double *)&repl; float g = (float)*f; repl_new = 0; - #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) memcpy((char *)&repl_new, (char *)&g, 4); - #else +#else memcpy(((char *)&repl_new) + 4, (char *)&g, 4); - #endif +#endif changed_val = repl_new; h->shape = 3; // modify shape @@ -1380,7 +1383,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } -#endif /* CMPLOG_SOLVE_ARITHMETIC */ + //#endif /* CMPLOG_SOLVE_ARITHMETIC return 0; @@ -1539,7 +1542,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { for (k = 0; k < size; ++k) { #else - u32 off = 16 - size; + u32 off = 16 - size; for (k = 16 - size; k < 16; ++k) { #endif @@ -1857,9 +1860,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, #ifndef CMPLOG_COMBINE (void)(cbuf); #endif -#ifndef CMPLOG_SOLVE_TRANSFORM - (void)(changed_val); -#endif + //#ifndef CMPLOG_SOLVE_TRANSFORM + // (void)(changed_val); + //#endif u8 save[40]; u32 saved_idx = idx, pre, from = 0, to = 0, i, j; @@ -1939,16 +1942,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } -#ifdef CMPLOG_SOLVE_TRANSFORM + //#ifdef CMPLOG_SOLVE_TRANSFORM if (*status == 1) return 0; - if (lvl & LVL3) { + if (afl->cmplog_enable_transform && (lvl & LVL3)) { u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0; - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 u32 tob64 = 0, fromb64 = 0; - #endif +#endif u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0; u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0; u8 xor_val[32], arith_val[32], tmp[48]; @@ -2044,7 +2047,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 if (i % 3 == 2 && i < 24) { if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; @@ -2057,7 +2060,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #endif +#endif if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) { @@ -2085,20 +2088,20 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef _DEBUG +#ifdef _DEBUG fprintf(stderr, "RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " "from_0=%u from_slash=%u from_x=%u\n", idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0, to_slash, to_x, from_0, from_slash, from_x); - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 + #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64, fromb64); - #endif #endif +#endif - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // input is base64 and converted to binary? convert repl to base64! if ((i % 4) == 3 && i < 24 && fromb64 > i) { @@ -2121,7 +2124,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #endif +#endif // input is converted to hex? convert repl to binary! if (i < 16 && tohex > i) { @@ -2250,16 +2253,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } - #ifdef CMPLOG_COMBINE +#ifdef CMPLOG_COMBINE if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); } - #endif +#endif if ((i >= 7 && (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i > (fromhex + from_0 + from_x + from_slash + 1) - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 +#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 && i > tob64 + 3 && i > fromb64 + 4 - #endif +#endif )) || repl[i] != changed_val[i] || *status == 1) { @@ -2273,7 +2276,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, } -#endif + //#endif return 0; @@ -2606,9 +2609,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } else if ((lvl & LVL1) -#ifdef CMPLOG_SOLVE_TRANSFORM - || (lvl & LVL3) -#endif + //#ifdef CMPLOG_SOLVE_TRANSFORM + || ((lvl & LVL3) && afl->cmplog_enable_transform) + //#endif ) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { @@ -2689,7 +2692,7 @@ exit_its: #else u32 *v = (u32 *)afl->virgin_bits; u32 *s = (u32 *)virgin_save; - u32 i; + u32 i; for (i = 0; i < (afl->shm.map_size >> 2); i++) { v[i] &= s[i]; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e3e9007d..e2db029d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -103,7 +103,8 @@ static void usage(u8 *argv0, int more_help) { " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-... ms, default %u ms)\n" + " -t msec - timeout for each run (auto-scaled, 50-... ms, default " + "%u ms)\n" " add a '+' to skip over seeds running longer.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" @@ -123,10 +124,10 @@ static void usage(u8 *argv0, int more_help) { " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" " if using QEMU, just use -c 0.\n" - " -l cmplog_level - set the complexity/intensivity of CmpLog.\n" - " Values: 1 (basic), 2 (larger files) and 3 " - "(transform)\n\n" - + " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" + " 1=small files (default), 2=larger files, 3=all " + "files,\n" + " A=arithmetic solving, T=tranformational solving.\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " "random\n" @@ -813,13 +814,36 @@ int main(int argc, char **argv_orig, char **envp) { case 'l': { - if (optarg) { afl->cmplog_lvl = atoi(optarg); } - if (afl->cmplog_lvl < 1 || afl->cmplog_lvl > CMPLOG_LVL_MAX) { + if (!optarg) { FATAL("missing parameter for 'l'"); } + char *c = optarg; + while (*c) { - FATAL( - "Bad complog level value, accepted values are 1 (default), 2 and " - "%u.", - CMPLOG_LVL_MAX); + switch (*c) { + + case '0': + case '1': + afl->cmplog_lvl = 1; + break; + case '2': + afl->cmplog_lvl = 2; + break; + case '3': + afl->cmplog_lvl = 3; + break; + case 'a': + case 'A': + afl->cmplog_enable_arith = 1; + break; + case 't': + case 'T': + afl->cmplog_enable_transform = 1; + break; + default: + FATAL("Unknown option value '%c' in -l %s", *c, optarg); + + } + + ++c; } -- cgit 1.4.1 From c67c4ce7578e45656262bd0eaddca6527ca7b166 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 23:17:40 +0100 Subject: doc update --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aacae1b5..d37826b5 100644 --- a/README.md +++ b/README.md @@ -754,6 +754,8 @@ campaigns as these are much shorter runnings. `-M` enables deterministic fuzzing, old queue handling etc. which is good for a fuzzing campaign but not good for short CI runs. +How this can look like can e.g. be seen at afl++'s setup in Google's [oss-fuzz](https://github.com/google/oss-fuzz/blob/4bb61df7905c6005000f5766e966e6fe30ab4559/infra/base-images/base-builder/compile_afl#L69). + ## Fuzzing binary-only targets When source code is *NOT* available, afl++ offers various support for fast, -- cgit 1.4.1 From ac9cfd89dae0ce99df500793b3f5cbed2fd2e4f7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 23:27:07 +0100 Subject: how to compare afl++ --- README.md | 7 +++++++ src/afl-cc.c | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d37826b5..59b1c143 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website. To cite our work, look at the [Cite](#cite) section. + For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` + with `AFL_LLVM_CMPLOG=1`. ## Major changes in afl++ 3.0 @@ -1170,6 +1172,11 @@ Thank you! If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20: +If you use AFLpluplus to compare to your work, please use either `afl-clang-lto` +or `afl-clang-fast` with `AFL_LLVM_CMPLOG=1` for building targets and +`afl-fuzz` with the command line option `-l 2` for fuzzing. +The most effective setup is the `aflplusplus` default fuzzer on Google's fuzzbench. + + Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020. Bibtex: diff --git a/src/afl-cc.c b/src/afl-cc.c index d41f79a2..a5e54691 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1699,7 +1699,9 @@ int main(int argc, char **argv, char **envp) { "Do not be overwhelmed :) afl-cc uses good defaults if no options are " "selected.\n" "Read the documentation for FEATURES though, all are good but few are " - "defaults.\n\n"); + "defaults.\n"); + "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast with\n" + "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n" exit(1); -- cgit 1.4.1 From 8ad78f5b65d09375dddfa679ccce76bec0862c28 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 Feb 2021 23:42:08 +0100 Subject: fix --- src/afl-cc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index a5e54691..2eb8c575 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1699,9 +1699,9 @@ int main(int argc, char **argv, char **envp) { "Do not be overwhelmed :) afl-cc uses good defaults if no options are " "selected.\n" "Read the documentation for FEATURES though, all are good but few are " - "defaults.\n"); + "defaults.\n" "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast with\n" - "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n" + "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n"); exit(1); -- cgit 1.4.1 From a81b5aa921567ba92c22c9ab1c4493725c43e8aa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 11:08:25 +0100 Subject: dict2file fix --- instrumentation/afl-llvm-dict2file.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 6f34ac5a..ddaa41e1 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -90,7 +90,7 @@ void dict2file(int fd, u8 *mem, u32 len) { j = 1; for (i = 0; i < len; i++) { - if (isprint(mem[i])) { + if (isprint(mem[i]) && mem[i] != '\\') { line[j++] = mem[i]; -- cgit 1.4.1 From 2785c8b197a1e7f109fa4dfb47fdd82eca0ad008 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 12:34:37 +0100 Subject: crash fix --- src/afl-fuzz-init.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 702e732d..e372c803 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1060,13 +1060,22 @@ void perform_dry_run(afl_state_t *afl) { p->perf_score = 0; u32 i = 0; - while (unlikely(afl->queue_buf[i]->disabled)) { + while (unlikely(i < afl->queued_paths && afl->queue_buf[i] && + afl->queue_buf[i]->disabled)) { ++i; } - afl->queue = afl->queue_buf[i]; + if (i < afl->queued_paths && afl->queue_buf[i]) { + + afl->queue = afl->queue_buf[i]; + + } else { + + afl->queue = afl->queue_buf[0]; + + } afl->max_depth = 0; for (i = 0; i < afl->queued_paths; i++) { -- cgit 1.4.1 From 8c133b607cdbde60e6c922236947f7a69c9190f2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 12:43:39 +0100 Subject: stdstring fix attempt --- instrumentation/afl-compiler-rt.o.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index dba4dc65..324d541d 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1653,12 +1653,19 @@ static u8 *get_llvm_stdstring(u8 *string) { void __cmplog_rtn_gcc_stdstring_cstring(u8 *stdstring, u8 *cstring) { + if (unlikely(!__afl_cmp_map)) return; + if (!area_is_mapped(stdstring, 32) || !area_is_mapped(cstring, 32)) return; + __cmplog_rtn_hook(get_gcc_stdstring(stdstring), cstring); } void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { + if (unlikely(!__afl_cmp_map)) return; + if (!area_is_mapped(stdstring1, 32) || !area_is_mapped(stdstring2, 32)) + return; + __cmplog_rtn_hook(get_gcc_stdstring(stdstring1), get_gcc_stdstring(stdstring2)); @@ -1666,12 +1673,17 @@ void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) { + if (unlikely(!__afl_cmp_map)) return; + if (!area_is_mapped(stdstring, 32) || !area_is_mapped(cstring, 32)) return; __cmplog_rtn_hook(get_llvm_stdstring(stdstring), cstring); } void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { + if (unlikely(!__afl_cmp_map)) return; + if (!area_is_mapped(stdstring1, 32) || !area_is_mapped(stdstring2, 32)) + return; __cmplog_rtn_hook(get_llvm_stdstring(stdstring1), get_llvm_stdstring(stdstring2)); -- cgit 1.4.1 From a252943236b12c080248747bee06c9c5084b871e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 12:59:01 +0100 Subject: another fix for disabled entries --- docs/Changelog.md | 1 + src/afl-fuzz.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 477498d0..a006fccb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -32,6 +32,7 @@ sending a mail to . after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map - fix for `-Z` + - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e2db029d..24d77cc9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1770,12 +1770,15 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->old_seed_selection)) { afl->current_entry = 0; - while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) { + while (unlikely(afl->current_entry < afl->queued_paths && + afl->queue_buf[afl->current_entry]->disabled)) { ++afl->current_entry; } + if (afl->current_entry >= afl->queued_paths) { afl->current_entry = 0; } + afl->queue_cur = afl->queue_buf[afl->current_entry]; if (unlikely(seek_to)) { -- cgit 1.4.1 From 70fe872940b9815698b4317bdde33da1dae27923 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 16:39:38 +0100 Subject: ensure a valid seed exists --- instrumentation/afl-compiler-rt.o.c | 2 ++ src/afl-cc.c | 3 ++- src/afl-fuzz.c | 7 ++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 324d541d..e4aeadfa 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1675,6 +1675,7 @@ void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) { if (unlikely(!__afl_cmp_map)) return; if (!area_is_mapped(stdstring, 32) || !area_is_mapped(cstring, 32)) return; + __cmplog_rtn_hook(get_llvm_stdstring(stdstring), cstring); } @@ -1684,6 +1685,7 @@ void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) { if (unlikely(!__afl_cmp_map)) return; if (!area_is_mapped(stdstring1, 32) || !area_is_mapped(stdstring2, 32)) return; + __cmplog_rtn_hook(get_llvm_stdstring(stdstring1), get_llvm_stdstring(stdstring2)); diff --git a/src/afl-cc.c b/src/afl-cc.c index 2eb8c575..5f471355 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1700,7 +1700,8 @@ int main(int argc, char **argv, char **envp) { "selected.\n" "Read the documentation for FEATURES though, all are good but few are " "defaults.\n" - "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast with\n" + "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast " + "with\n" "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n"); exit(1); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 24d77cc9..9137dc23 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1707,7 +1707,12 @@ int main(int argc, char **argv_orig, char **envp) { cull_queue(afl); - if (!afl->pending_not_fuzzed) { + // ensure we have at least one seed that is not disabled. + u32 entry, valid_seeds = 0; + for (entry = 0; entry < afl->queued_paths; ++entry) + if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; } + + if (!afl->pending_not_fuzzed || !valid_seeds) { FATAL("We need at least one valid input seed that does not crash!"); -- cgit 1.4.1 From fb2a6b6941ffb6cf575d2a772c6e0d47b49835ee Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 16:56:35 +0100 Subject: minimum sync time --- docs/Changelog.md | 1 + include/afl-fuzz.h | 1 + include/config.h | 5 +++++ src/afl-fuzz-run.c | 2 ++ src/afl-fuzz.c | 15 ++++++++++++--- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index a006fccb..d8587334 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,6 +35,7 @@ sending a mail to . - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis + - added minimum SYNC_TIME to include/config.h (30 minutes default) - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 10d94fed..e191543a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -570,6 +570,7 @@ typedef struct afl_state { blocks_eff_total, /* Blocks subject to effector maps */ blocks_eff_select, /* Blocks selected as fuzzable */ start_time, /* Unix start time (ms) */ + last_sync_time, /* Time of last sync */ last_path_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ last_hang_time; /* Time for most recent hang (ms) */ diff --git a/include/config.h b/include/config.h index 535ce0d3..083cad23 100644 --- a/include/config.h +++ b/include/config.h @@ -280,6 +280,11 @@ #define SYNC_INTERVAL 8 +/* Sync time (minimum time between syncing in ms, time is halfed for -M main + nodes): */ + +#define SYNC_TIME 18000000LLU /* 18000000 = 30 minutes */ + /* Output directory reuse grace period (minutes): */ #define OUTPUT_GRACE 25 diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 97cb7415..0b84a542 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -707,6 +707,8 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); + afl->last_sync_time = get_cur_time(); + } /* Trim all new test cases to save cycles when doing deterministic checks. The diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9137dc23..f83aac9e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1986,15 +1986,24 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->is_main_node)) { - if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { + if (unlikely(get_cur_time() > + (SYNC_TIME >> 1) + afl->last_sync_time)) { - sync_fuzzers(afl); + if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { + + sync_fuzzers(afl); + + } } } else { - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + if (unlikely(get_cur_time() > SYNC_TIME + afl->last_sync_time)) { + + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + + } } -- cgit 1.4.1 From 7674dac1a16a9963e22eb628fdbd409befe19979 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 18:17:35 +0100 Subject: auto mode for CTX + NGRAM --- src/afl-cc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/afl-cc.c b/src/afl-cc.c index 5f471355..783cf23e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1421,6 +1421,14 @@ int main(int argc, char **argv, char **envp) { } + if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT && + (compiler_mode == LLVM || compiler_mode == UNSET)) { + + instrument_mode = INSTRUMENT_CLASSIC; + compiler_mode = LLVM; + + } + if (!compiler_mode) { // lto is not a default because outside of afl-cc RANLIB and AR have to -- cgit 1.4.1 From 745bc083d144a31981b3686d68bc34777758b359 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 18:22:09 +0100 Subject: fix error msg --- src/afl-cc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index 783cf23e..c3910e6d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1802,8 +1802,8 @@ int main(int argc, char **argv, char **envp) { if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC && instrument_mode != INSTRUMENT_CFG) FATAL( - "CTX and NGRAM instrumentation options can only be used with CFG " - "(recommended) and CLASSIC instrumentation modes!"); + "CTX and NGRAM instrumentation options can only be used with LLVM and " + "CFG or CLASSIC instrumentation modes!"); if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) FATAL( -- cgit 1.4.1 From 4ab90e739ff4410f24c63d71dfffe333063c3b3a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Feb 2021 22:24:59 +0100 Subject: code format --- include/afl-fuzz.h | 2 +- include/config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e191543a..d9dbad5a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -570,7 +570,7 @@ typedef struct afl_state { blocks_eff_total, /* Blocks subject to effector maps */ blocks_eff_select, /* Blocks selected as fuzzable */ start_time, /* Unix start time (ms) */ - last_sync_time, /* Time of last sync */ + last_sync_time, /* Time of last sync */ last_path_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ last_hang_time; /* Time for most recent hang (ms) */ diff --git a/include/config.h b/include/config.h index 083cad23..241b2e69 100644 --- a/include/config.h +++ b/include/config.h @@ -283,7 +283,7 @@ /* Sync time (minimum time between syncing in ms, time is halfed for -M main nodes): */ -#define SYNC_TIME 18000000LLU /* 18000000 = 30 minutes */ +#define SYNC_TIME 18000000LLU /* 18000000 = 30 minutes */ /* Output directory reuse grace period (minutes): */ -- cgit 1.4.1 From 2daeeab844d2c3107f45e62c58138912f7387281 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 Feb 2021 10:06:15 +0100 Subject: encode double quote in dict --- instrumentation/afl-llvm-dict2file.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index ddaa41e1..19ef15f7 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -90,7 +90,7 @@ void dict2file(int fd, u8 *mem, u32 len) { j = 1; for (i = 0; i < len; i++) { - if (isprint(mem[i]) && mem[i] != '\\') { + if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') { line[j++] = mem[i]; -- cgit 1.4.1 From 564f4915665c8a68a97d71b7db812606ddec8c5b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Feb 2021 09:29:19 +0100 Subject: redqueen settings opt --- include/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index 241b2e69..d2e9f889 100644 --- a/include/config.h +++ b/include/config.h @@ -50,14 +50,14 @@ #define CMPLOG_COMBINE /* Minimum % of the corpus to perform cmplog on. Default: 20% */ -#define CMPLOG_CORPUS_PERCENT 20U +#define CMPLOG_CORPUS_PERCENT 10U /* Number of potential positions from which we decide if cmplog becomes useless, default 16384 */ #define CMPLOG_POSITIONS_MAX 16384U /* Maximum allowed fails per CMP value. Default: 32 * 3 */ -#define CMPLOG_FAIL_MAX 96 +#define CMPLOG_FAIL_MAX 128 /* Now non-cmplog configuration options */ -- cgit 1.4.1 From e6ef2ee338d1da1d5fa8e23822247ee7837e1f54 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Feb 2021 12:14:10 +0100 Subject: typo --- include/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index d2e9f889..1c3370ad 100644 --- a/include/config.h +++ b/include/config.h @@ -281,9 +281,9 @@ #define SYNC_INTERVAL 8 /* Sync time (minimum time between syncing in ms, time is halfed for -M main - nodes): */ + nodes) - default is 30 minutes: */ -#define SYNC_TIME 18000000LLU /* 18000000 = 30 minutes */ +#define SYNC_TIME (30 * 60 * 1000) /* Output directory reuse grace period (minutes): */ -- cgit 1.4.1 From cc7c651dc97f5567af33164d396b390d36b46049 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 24 Feb 2021 18:07:08 +0100 Subject: tidied up env suggestions --- docs/Changelog.md | 3 ++- src/afl-common.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index d8587334..1260531e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -36,6 +36,7 @@ sending a mail to . - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - added minimum SYNC_TIME to include/config.h (30 minutes default) + - printing suggestions for mistyped `AFL_` env variables - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a @@ -68,7 +69,7 @@ sending a mail to . - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) + - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b) - @Edznux added a nice documentation on how to use rpc.statsd with afl++ in docs/rpc_statsd.md, thanks! diff --git a/src/afl-common.c b/src/afl-common.c index ce63c262..1628e517 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -529,6 +529,8 @@ static int string_distance_levenshtein(char *s1, char *s2) { s1len = strlen(s1); s2len = strlen(s2); unsigned int column[s1len + 1]; + column[s1len] = 1; + for (y = 1; y <= s1len; y++) column[y] = y; for (x = 1; x <= s2len; x++) { @@ -608,6 +610,8 @@ void print_suggested_envs(char *mispelled_env) { }; + ck_free(reduced); + } if (found) goto cleanup; -- cgit 1.4.1 From 48a1a29baa49b633855f49536d72783d5a489b82 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 24 Feb 2021 20:34:33 +0100 Subject: typos --- src/afl-fuzz.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f83aac9e..d4e3958e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -127,7 +127,7 @@ static void usage(u8 *argv0, int more_help) { " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" " 1=small files (default), 2=larger files, 3=all " "files,\n" - " A=arithmetic solving, T=tranformational solving.\n\n" + " A=arithmetic solving, T=transformational solving.\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " "random\n" @@ -139,8 +139,8 @@ static void usage(u8 *argv0, int more_help) { "Testing settings:\n" " -s seed - use a fixed seed for the RNG\n" - " -V seconds - fuzz for a specific time then terminate\n" - " -E execs - fuzz for a approx. no of total executions then " + " -V seconds - fuzz for a specified time then terminate\n" + " -E execs - fuzz for an approx. no. of total executions then " "terminate\n" " Note: not precise and can have several more " "executions.\n\n" -- cgit 1.4.1 From 5d181950eb48afa6f86bd4455fb9f55b09f5eb19 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Feb 2021 21:17:58 +0100 Subject: fixes --- README.md | 6 +++--- include/config.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 59b1c143..0539752c 100644 --- a/README.md +++ b/README.md @@ -1170,12 +1170,12 @@ Thank you! ## Cite -If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20: - If you use AFLpluplus to compare to your work, please use either `afl-clang-lto` or `afl-clang-fast` with `AFL_LLVM_CMPLOG=1` for building targets and `afl-fuzz` with the command line option `-l 2` for fuzzing. -The most effective setup is the `aflplusplus` default fuzzer on Google's fuzzbench. +The most effective setup is the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). + +If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20: + Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020. diff --git a/include/config.h b/include/config.h index 1c3370ad..6120dcd6 100644 --- a/include/config.h +++ b/include/config.h @@ -49,15 +49,15 @@ /* If a redqueen pass finds more than one solution, try to combine them? */ #define CMPLOG_COMBINE -/* Minimum % of the corpus to perform cmplog on. Default: 20% */ +/* Minimum % of the corpus to perform cmplog on. Default: 10% */ #define CMPLOG_CORPUS_PERCENT 10U /* Number of potential positions from which we decide if cmplog becomes useless, default 16384 */ #define CMPLOG_POSITIONS_MAX 16384U -/* Maximum allowed fails per CMP value. Default: 32 * 3 */ -#define CMPLOG_FAIL_MAX 128 +/* Maximum allowed fails per CMP value. Default: 96 */ +#define CMPLOG_FAIL_MAX 96 /* Now non-cmplog configuration options */ -- cgit 1.4.1 From 047f3436e95b40d541bcc5b688be0052ef5e798e Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 24 Feb 2021 21:29:00 +0100 Subject: edges in plot file --- include/afl-fuzz.h | 4 ++-- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-stats.c | 21 +++++++++++---------- src/afl-fuzz.c | 8 ++++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d9dbad5a..3531d672 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1072,8 +1072,8 @@ void destroy_extras(afl_state_t *); void load_stats_file(afl_state_t *); void write_setup_file(afl_state_t *, u32, char **); -void write_stats_file(afl_state_t *, double, double, double); -void maybe_update_plot_file(afl_state_t *, double, double); +void write_stats_file(afl_state_t *, u32, double, double, double); +void maybe_update_plot_file(afl_state_t *, u32, double, double); void show_stats(afl_state_t *); void show_init_stats(afl_state_t *); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index e372c803..ab743f4b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2026,7 +2026,7 @@ void setup_dirs_fds(afl_state_t *afl) { fprintf(afl->fsrv.plot_file, "# unix_time, cycles_done, cur_path, paths_total, " "pending_total, pending_favs, map_size, unique_crashes, " - "unique_hangs, max_depth, execs_per_sec\n"); + "unique_hangs, max_depth, execs_per_sec, edges_found\n"); fflush(afl->fsrv.plot_file); /* ignore errors */ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 66efeb20..192fdd62 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -185,15 +185,14 @@ void load_stats_file(afl_state_t *afl) { /* Update stats file for unattended monitoring. */ -void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, - double eps) { +void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, + double stability, double eps) { #ifndef __HAIKU__ struct rusage rus; #endif u64 cur_time = get_cur_time(); - u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits); u8 fn[PATH_MAX]; FILE *f; @@ -353,7 +352,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, /* Update the plot file if there is a reason to. */ -void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { +void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, + double eps) { if (unlikely(afl->plot_prev_qp == afl->queued_paths && afl->plot_prev_pf == afl->pending_favored && @@ -384,16 +384,16 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { /* Fields in the file: unix_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed, - favored_not_fuzzed, afl->unique_crashes, afl->unique_hangs, afl->max_depth, - execs_per_sec */ + favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, + execs_per_sec, edges_found */ fprintf( afl->fsrv.plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu\n", + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %u\n", get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps, - afl->plot_prev_ed); /* ignore errors */ + afl->plot_prev_ed, t_bytes); /* ignore errors */ fflush(afl->fsrv.plot_file); @@ -532,7 +532,8 @@ void show_stats(afl_state_t *afl) { if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) { afl->stats_last_stats_ms = cur_ms; - write_stats_file(afl, t_byte_ratio, stab_ratio, afl->stats_avg_exec); + write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, + afl->stats_avg_exec); save_auto(afl); write_bitmap(afl); @@ -555,7 +556,7 @@ void show_stats(afl_state_t *afl) { if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) { afl->stats_last_plot_ms = cur_ms; - maybe_update_plot_file(afl, t_byte_ratio, afl->stats_avg_exec); + maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f83aac9e..f029ef83 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1724,8 +1724,8 @@ int main(int argc, char **argv_orig, char **envp) { afl->start_time = get_cur_time(); if (afl->in_place_resume || afl->afl_env.afl_autoresume) load_stats_file(afl); - write_stats_file(afl, 0, 0, 0); - maybe_update_plot_file(afl, 0, 0); + write_stats_file(afl, 0, 0, 0, 0); + maybe_update_plot_file(afl, 0, 0, 0); save_auto(afl); if (afl->stop_soon) { goto stop_fuzzing; } @@ -2018,12 +2018,12 @@ int main(int argc, char **argv_orig, char **envp) { } write_bitmap(afl); - maybe_update_plot_file(afl, 0, 0); + maybe_update_plot_file(afl, 0, 0, 0); save_auto(afl); stop_fuzzing: - write_stats_file(afl, 0, 0, 0); + write_stats_file(afl, 0, 0, 0, 0); afl->force_ui_update = 1; // ensure the screen is reprinted show_stats(afl); // print the screen one last time -- cgit 1.4.1 From 5c239451cfd1562ce72a78eefc6886fd76f2c132 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 09:15:45 +0100 Subject: cmplog finetuning --- custom_mutators/honggfuzz/honggfuzz.h | 2 +- include/config.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h index eb6a3f11..c80cdd87 100644 --- a/custom_mutators/honggfuzz/honggfuzz.h +++ b/custom_mutators/honggfuzz/honggfuzz.h @@ -39,7 +39,7 @@ #include "libhfcommon/util.h" #define PROG_NAME "honggfuzz" -#define PROG_VERSION "2.3" +#define PROG_VERSION "2.4" /* Name of the template which will be replaced with the proper name of the file */ #define _HF_FILE_PLACEHOLDER "___FILE___" diff --git a/include/config.h b/include/config.h index 6120dcd6..439f4d2f 100644 --- a/include/config.h +++ b/include/config.h @@ -53,11 +53,11 @@ #define CMPLOG_CORPUS_PERCENT 10U /* Number of potential positions from which we decide if cmplog becomes - useless, default 16384 */ -#define CMPLOG_POSITIONS_MAX 16384U + useless, default 8096 */ +#define CMPLOG_POSITIONS_MAX 8096U -/* Maximum allowed fails per CMP value. Default: 96 */ -#define CMPLOG_FAIL_MAX 96 +/* Maximum allowed fails per CMP value. Default: 128 */ +#define CMPLOG_FAIL_MAX 128 /* Now non-cmplog configuration options */ -- cgit 1.4.1 From 2f7e57f6aa4f09d0b6f55b6592fbd70d2c2c1064 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 25 Feb 2021 10:04:41 +0100 Subject: helper_min3 func --- src/afl-common.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index 1628e517..078ffb9d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -518,8 +518,12 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) { } -#define HELPER_MIN3(a, b, c) \ - ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) +static inline unsigned int helper_min3(unsigned int a, unsigned int b, + unsigned int c) { + + return a < b ? (a < c ? a : c) : (b < c ? b : c); + +} // from // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C @@ -539,7 +543,7 @@ static int string_distance_levenshtein(char *s1, char *s2) { for (y = 1, lastdiag = x - 1; y <= s1len; y++) { olddiag = column[y]; - column[y] = HELPER_MIN3(column[y] + 1, column[y - 1] + 1, + column[y] = helper_min3(column[y] + 1, column[y - 1] + 1, lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1)); lastdiag = olddiag; @@ -551,8 +555,6 @@ static int string_distance_levenshtein(char *s1, char *s2) { } -#undef HELPER_MIN3 - #define ENV_SIMILARITY_TRESHOLD 3 void print_suggested_envs(char *mispelled_env) { -- cgit 1.4.1 From 6c9777de13ebd9a8c1cd20c2124aff7e4e31d579 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 25 Feb 2021 10:42:39 +0100 Subject: edges in afl-plot --- afl-plot | 11 +++++++++-- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-stats.c | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/afl-plot b/afl-plot index 0faed0ec..ba100d3e 100755 --- a/afl-plot +++ b/afl-plot @@ -99,7 +99,7 @@ if [ ! -d "$outputdir" ]; then fi -rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" +rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null echo "[*] Generating plots..." @@ -152,6 +152,12 @@ set ytics auto plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\ '$inputdir/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier; +set terminal png truecolor enhanced size 1000,300 butt +set output '$outputdir/edges.png' + +set ytics auto +plot '$inputdir/plot_data' using 1:13 with lines title ' edges' linecolor rgb '#0090ff' linewidth 3 + _EOF_ ) | gnuplot @@ -172,6 +178,7 @@ cat >"$outputdir/index.html" <<_EOF_ Generated on:`date`

+

@@ -183,7 +190,7 @@ _EOF_ # sensitive, this seems like a reasonable trade-off. chmod 755 "$outputdir" -chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/index.html" +chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html" echo "[+] All done - enjoy your charts!" diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ab743f4b..d85a83e0 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2026,7 +2026,7 @@ void setup_dirs_fds(afl_state_t *afl) { fprintf(afl->fsrv.plot_file, "# unix_time, cycles_done, cur_path, paths_total, " "pending_total, pending_favs, map_size, unique_crashes, " - "unique_hangs, max_depth, execs_per_sec, edges_found\n"); + "unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n"); fflush(afl->fsrv.plot_file); /* ignore errors */ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 192fdd62..42c71b05 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -355,7 +355,8 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, double eps) { - if (unlikely(afl->plot_prev_qp == afl->queued_paths && + if (unlikely(afl->stop_soon) || + unlikely(afl->plot_prev_qp == afl->queued_paths && afl->plot_prev_pf == afl->pending_favored && afl->plot_prev_pnf == afl->pending_not_fuzzed && afl->plot_prev_ce == afl->current_entry && -- cgit 1.4.1 From e2b4bc93103c1d311315e324833b7cb71d0677cc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 11:02:59 +0100 Subject: update changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 1260531e..9a61fac3 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -64,6 +64,7 @@ sending a mail to . - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings - afl-cmin and afl-showmap now support the -f option + - afl_plot now also generates a graph on the discovered edges - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars. - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. -- cgit 1.4.1 From ee0ca07f3c9f7c5971440f5dca70a2ee6f37584d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Feb 2021 12:19:46 +0100 Subject: changing the -t ...+ meaning to "auto-calculate buth this is the max" --- README.md | 7 ++++++- docs/Changelog.md | 21 +++++++++++++-------- src/afl-fuzz-init.c | 33 ++++++++++++--------------------- src/afl-fuzz-stats.c | 16 ++++++++-------- src/afl-fuzz.c | 33 +++++++++++++++++++++++++++++---- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 0539752c..119426f6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,12 @@ For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. -## Major changes in afl++ 3.0 +## Major changes in afl++ 3.0 + 3.1 + +With afl++ 3.1 we introduced the following changes from previous behaviours: + * The '+' feature of the '-t' option now means to auto-calculate the timeout + with the value given being the maximum timeout. The original meaning of + "skipping timeouts instead of abort" is now inherent to the -t option. With afl++ 3.0 we introduced changes that break some previous afl and afl++ behaviours and defaults: diff --git a/docs/Changelog.md b/docs/Changelog.md index 9a61fac3..c4347baf 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,26 +16,31 @@ sending a mail to . to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz - - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on start - the target map size + - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on + start the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). This is costly hence new command line option - `-l` that sets the intensity (values 1 to 3). Recommended is 1 or 2. - - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from - `-i` or resumes (as these have most likely already been done) + `-l` that sets the intensity (values 1 to 3). Recommended is 2. + - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial seeds + from `-i` or resumes (these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now reloaded and used, thanks to Vimal Joseph for this patch! - - if deterministic mode is active (`-D`, or `-M` without `-d`) then we sync - after every queue entry as this can take very long time otherwise + - changed the meaning of '+' of the '-t' option, it now means to + auto-calculate the timeout with the value given being the max + timeout. The original meaning of skipping timeouts instead of + abort is now inherent to the -t option. + - if deterministic mode is active (`-D`, or `-M` without `-d`) then + we sync after every queue entry as this can take very long time + otherwise + - added minimum SYNC_TIME to include/config.h (30 minutes default) - better detection if a target needs a large shared map - fix for `-Z` - fixed a few crashes - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - - added minimum SYNC_TIME to include/config.h (30 minutes default) - printing suggestions for mistyped `AFL_` env variables - afl-cc - allow instrumenting LLVMFuzzerTestOneInput diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d85a83e0..3dbc4c65 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -882,32 +882,23 @@ void perform_dry_run(afl_state_t *afl) { if (afl->timeout_given) { - /* The -t nn+ syntax in the command line sets afl->timeout_given to - '2' and instructs afl-fuzz to tolerate but skip queue entries that - time out. */ + /* if we have a timeout but a timeout value was given then always + skip. The '+' meaning has been changed! */ + WARNF("Test case results in a timeout (skipping)"); + ++cal_failures; + q->cal_failed = CAL_CHANCES; + q->disabled = 1; + q->perf_score = 0; - if (afl->timeout_given > 1) { + if (!q->was_fuzzed) { - WARNF("Test case results in a timeout (skipping)"); - q->cal_failed = CAL_CHANCES; - ++cal_failures; - break; + q->was_fuzzed = 1; + --afl->pending_not_fuzzed; + --afl->active_paths; } - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial " - "test cases.\n" - " Usually, the right thing to do is to relax the -t option - " - "or to delete it\n" - " altogether and allow the fuzzer to auto-calibrate. That " - "said, if you know\n" - " what you are doing and want to simply skip the unruly test " - "cases, append\n" - " '+' at the end of the value passed to -t ('-t %u+').\n", - afl->fsrv.exec_tmout, afl->fsrv.exec_tmout); - - FATAL("Test case '%s' results in a timeout", fn); + break; } else { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 42c71b05..bd856088 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -388,13 +388,13 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, favored_not_fuzzed, unique_crashes, unique_hangs, max_depth, execs_per_sec, edges_found */ - fprintf( - afl->fsrv.plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, %u\n", - get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, - afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, - bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps, - afl->plot_prev_ed, t_bytes); /* ignore errors */ + fprintf(afl->fsrv.plot_file, + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, " + "%u\n", + get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, + afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, + bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, + eps, afl->plot_prev_ed, t_bytes); /* ignore errors */ fflush(afl->fsrv.plot_file); @@ -1219,7 +1219,7 @@ void show_init_stats(afl_state_t *afl) { stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), stringify_int(IB(2), avg_us)); - if (!afl->timeout_given) { + if (afl->timeout_given != 1) { /* Figure out the appropriate timeout. The basic idea is: 5x average or 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5810e9a9..a02eadb2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -103,9 +103,10 @@ static void usage(u8 *argv0, int more_help) { " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" - " -t msec - timeout for each run (auto-scaled, 50-... ms, default " - "%u ms)\n" - " add a '+' to skip over seeds running longer.\n" + " -t msec - timeout for each run (auto-scaled, default %u ms). " + "Add a '+'\n" + " to auto-calculate the timeout, the value being the " + "maximum.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" " -Q - use binary-only instrumentation (QEMU mode)\n" @@ -1453,7 +1454,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!afl->timeout_given) { find_timeout(afl); } + if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL && !afl->in_place_resume) { @@ -1718,6 +1719,30 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->timeout_given == 2) { // -t ...+ option + + if (valid_seeds == 1) { + + WARNF( + "Only one valid seed is present, auto-calculating the timeout is " + "disabled!"); + afl->timeout_given = 1; + + } else { + + u64 max_ms = 0; + + for (entry = 0; entry < afl->queued_paths; ++entry) + if (!afl->queue_buf[entry]->disabled) + if (afl->queue_buf[entry]->exec_us > max_ms) + max_ms = afl->queue_buf[entry]->exec_us; + + afl->fsrv.exec_tmout = max_ms; + + } + + } + show_init_stats(afl); if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl); -- cgit 1.4.1