From 4cdf7a1e3e351f10537683d49a08181b6c1576cc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 23 Oct 2023 18:03:59 +0200 Subject: add scale encode mode for cmplog --- src/afl-fuzz-redqueen.c | 263 +++++++++++++++++++++++++++++++++++++++++++----- src/afl-fuzz.c | 4 + 2 files changed, 243 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index db4991db..b6c54df2 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -40,7 +40,7 @@ enum { IS_FP = 8, // is a floating point, not an integer /* --- below are internal settings, not from target cmplog */ IS_FP_MOD = 16, // arithemtic changed floating point - IS_INT_MOD = 32, // arithmetic changed interger + IS_INT_MOD = 32, // arithmetic changed integer IS_TRANSFORM = 64 // transformed integer }; @@ -775,6 +775,13 @@ static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) { } +#ifdef WORD_SIZE_64 +static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, + u128 pattern, u128 repl, u128 o_pattern, + u128 changed_val, u8 attr, u32 idx, + u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, + u32 len, u8 do_reverse, u8 lvl, u8 *status); +#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, @@ -807,6 +814,29 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, hshape, attr); */ + u8 bytes; + + switch (hshape) { + + case 0: + case 1: + bytes = 1; + break; + case 2: + bytes = 2; + break; + case 3: + case 4: + bytes = 4; + break; + default: + bytes = 8; + + } + + // necessary for preventing heap access overflow + bytes = MIN(bytes, len - idx); + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { @@ -895,29 +925,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) { u64 b_val, o_b_val, mask; - u8 bytes; - - switch (hshape) { - - case 0: - case 1: - bytes = 1; - break; - case 2: - bytes = 2; - break; - case 3: - case 4: - bytes = 4; - break; - default: - bytes = 8; - - } - - // necessary for preventing heap access overflow - bytes = MIN(bytes, len - idx); - switch (bytes) { case 0: // cannot happen @@ -1285,6 +1292,125 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + // If 'S' is set for cmplog mode then we try a scale encoding of the value. + // Currently we can only handle bytes up to 1 << 55 + + if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u8 do_call = 1; + u64 new_val = repl << 2; + u32 saved_hshape = hshape; + + if (changed_val <= 255) { + + // nothing + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + + } else { + +#ifndef WORD_SIZE_64 + if (repl <= 0x00ffffffffffffff { + + new_val = repl << 8; + u8 scale_len = 0; + u64 tmp_val = repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = 8; + + } else { + + do_call = 0; + + } + +#else + { + + u128 new_val = ((u128)repl) << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + do_call = 0; + + } + +#endif + + } + + if (do_call) { + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_val, o_pattern, changed_val, 32, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + // here we add and subract 1 from the value, but only if it is not an // == or != comparison // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float @@ -1551,6 +1677,95 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + if (attr < IS_FP && attr < 32 && + (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u128 new_val = repl << 2; + u128 max_scale = (u128)1 << 120; + u32 saved_hshape = hshape; + + if (new_val <= 255) { + + hshape = 1; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (repl < max_scale) { + + u128 new_val = (u128)repl << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + } return 0; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2538f4a4..9fdd2193 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1152,6 +1152,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'A': afl->cmplog_enable_arith = 1; break; + case 's': + case 'S': + afl->cmplog_enable_scale = 1; + break; case 't': case 'T': afl->cmplog_enable_transform = 1; -- cgit 1.4.1 From 7210a1c35972244325ceb0d4e357a78de2afb757 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 25 Oct 2023 10:58:05 +0200 Subject: fix scale --- src/afl-fuzz-redqueen.c | 126 +++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index b6c54df2..43b5c8bd 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1293,27 +1293,30 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } // If 'S' is set for cmplog mode then we try a scale encoding of the value. - // Currently we can only handle bytes up to 1 << 55 + // Currently we can only handle bytes up to 1 << 55 on 32 bit and 1 << 119 + // on 64 bit systems. + // Caveat: This implementation here works only on little endian systems. - if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { + if (attr < IS_FP && (afl->cmplog_enable_scale || lvl >= LVL3) && + repl == changed_val) { u8 do_call = 1; u64 new_val = repl << 2; - u32 saved_hshape = hshape; + u32 ilen = 0; if (changed_val <= 255) { - // nothing + ilen = 1; } else if (new_val <= 65535) { new_val += 1; // two byte mode - hshape = 2; + ilen = 2; } else if (new_val <= 4294967295) { new_val += 2; // four byte mode - hshape = 4; + ilen = 4; } else { @@ -1341,7 +1344,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, }; new_val += (scale_len << 2) + 3; - hshape = 8; + ilen = scale_len + 5; } else { @@ -1352,7 +1355,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, #else { - u128 new_val = ((u128)repl) << 8; + u128 new_vall = ((u128)repl) << 8; u8 scale_len = 0; u128 tmp_val = (u128)repl; @@ -1373,18 +1376,22 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, }; - new_val += (scale_len << 2) + 3; - hshape = scale_len + 5; + new_vall += (scale_len << 2) + 3; + ilen = scale_len + 5; - if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, - (u128)o_pattern, (u128)changed_val, - 32, idx, taint_len, orig_buf, buf, - cbuf, len, 1, lvl, status))) { + if (ilen <= its_len) { - hshape = saved_hshape; - return 1; + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_vall, ilen); - } + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_vall, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; do_call = 0; @@ -1396,18 +1403,21 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (do_call) { - if (unlikely(cmp_extend_encoding( - afl, h, pattern, new_val, o_pattern, changed_val, 32, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + if (ilen <= its_len) { - hshape = saved_hshape; - return 1; + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); - } + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } +#ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } +#endif + memcpy(buf + idx, tmpbuf, ilen); - } + }; - hshape = saved_hshape; + } } @@ -1677,57 +1687,33 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + // Scale encoding only works on little endian systems + if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { u128 new_val = repl << 2; u128 max_scale = (u128)1 << 120; - u32 saved_hshape = hshape; + u32 ilen = 0; + u8 do_call = 1; if (new_val <= 255) { - hshape = 1; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 1; } else if (new_val <= 65535) { new_val += 1; // two byte mode - hshape = 2; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 2; } else if (new_val <= 4294967295) { new_val += 2; // four byte mode - hshape = 4; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 4; } else if (repl < max_scale) { - u128 new_val = (u128)repl << 8; + new_val = (u128)repl << 8; u8 scale_len = 0; u128 tmp_val = (u128)repl; while (tmp_val) { @@ -1748,21 +1734,27 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, }; new_val += (scale_len << 2) + 3; - hshape = scale_len + 5; - - if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, - (u128)o_pattern, (u128)changed_val, - 32, idx, taint_len, orig_buf, buf, - cbuf, len, 1, lvl, status))) { + ilen = scale_len + 5; - hshape = saved_hshape; - return 1; + } else { - } + do_call = 0; } - hshape = saved_hshape; + if (do_call && ilen <= its_len) { + + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; } -- cgit 1.4.1