if (strcmp(header.magic_password, "h4ck3d by p1gZ")) goto terminate_now;...or:
...<![<CDATA[C%Ada b="c":]]]>...What the heck?! As most of you probably know, CDATA is a special, differently parsed section within XML, separated from everything else by fairly complex syntax - a nine-character sequence of bytes that can't be realistically discovered by just randomly flipping bits. The finding is actually not magic; there are two possible explanations:
- As a recent "well, it's cheap, so let's see what happens" optimization, AFL automatically sets -O3 -funroll-loops when calling the compiler for instrumented binaries, and some of the shorter fixed-string comparisons will be actually just expanded inline. For example, if the stars align just right, strcmp(buf, "foo") may be unrolled to:
cmpb $0x66,0x200c32(%rip) # 'f' jne 4004b6...which, by the virtue of having a series of explicit and distinct branch points, can be readily instrumented on a per-character basis by afl-fuzz.
cmpb $0x6f,0x200c2a(%rip) # 'o' jne 4004b6 cmpb $0x6f,0x200c22(%rip) # 'o' jne 4004b6 cmpb $0x0,0x200c1a(%rip) # NUL jne 4004b6
- If that fails, it just so happens that some of the string comparisons in libxml2 in parser.c are done using a bunch of macros that will compile to similarly-structured code (as spotted by Ben Hawkes). This is presumably done so that the compiler can optimize this into a tree-style parser - whereas a linear sequence of strcmp() calls would lead to repeated and unnecessary comparisons of the already-examined chars. (Although done by hand in this particular case, the pattern is fairly common for automatically generated parsers of all sorts.)
<![I find this result a bit spooky because it's an example of the fuzzer defiantly and secretly working around one of its intentional and explicit design limitations - and definitely not something I was aiming for =) Of course, treat this first and foremost as a novelty; there are many other circumstances where similar types of highly verbose text-based syntax would not be discoverable to afl-fuzz - or where, even if the syntax could be discovered through some special-cased shims, it would be a waste of CPU time to do it with afl-fuzz, rather than a simple syntax-aware, template-based tool. (Coming up with an API to make template-based generators pluggable into AFL may be a good plan.) By the way, here are some other gems from the randomly generated test cases: