American fuzzy lop – a security-oriented fuzzer
lcamtuf.coredump.cx
lcamtuf.coredump.cx
def run_test_case(input):
# return a set() of instructions that the target executes when ran on `input`
# or throw a CrashException if the target crashes
def mutate(input):
# mess with the input- flip some bits, delete chunks, set things to 0xffffffff... randomly
# return the mutated input
def fuzz(initial_test_cases):
test_cases = initial_test_cases
coverage_seen = set()
# collect coverage from the initial inputs
for case in test_cases:
coverage_seen += run_test_case(case)
while True:
fuzzed = mutate(random.choice(test_cases))
try:
new_coverage = run_test_case(fuzzed) - coverage_seen
if new_coverage:
# ooh, this input did something we've never seen before!
# save it, so it can be used as a starting point
# for even more mutation
test_cases.add(fuzzed)
coverage_seen += new_coverage
except CrashException:
# we successfully crashed the target!
# save fuzzed off to disk or something and log a happy message
There's more to it in practice, of course- for example, run_test_case doesn't return a set of instructions, it's a bitmap / psuedo-Bloom filter of basic blocks hit. (A basic block, to a first approximation, is "a sequence of instructions that doesn't have any unusual control flow" - so if you run the first instruction in a basic block, you'll run all the rest.) And there's a fair bit of complexity involved for performance reasons.But the core algorithm is simple enough that you can actually implement it in pure Python, for Python programs, in < 100LOC - and that implementation will find real bugs in a lot of Python libraries.
Makes a pretty good case for "worse is better", if you like.
The funniest part is that this ugly hack kept working across platforms for many years; whereas when somebody else implemented a "proper" integration with the clang / llvm API, their solution proved to be extremely fragile. The API wasn't stable between compiler versions, and because it wasn't really used much, it had all kinds of bugs, including being outright unusable at times.
Also, most distros packaged clang in a way that made it impossible to compile the plugin, because of missing or mismatched headers, missing companions tools, etc. So you had to download and rebuild the whole compiler, which took hours (and that's if you didn't get stuck in a dependency hell).
So yeah, this was very much a lesson in "worse is better".
I suck at assembly but this proved to be a nice spot to hack away at it (with copious googling) to even further improve my understanding of not only the instrumentation but the effects that mutations had on program execution.
So for me worse was definitely better.
Although the instrumentation via asm patching works well in most cases, it can break down in strange ways. See (shameless plug) : https://blog.adacore.com/running-american-fuzzy-lop-on-your-...
Amazing tool, quite extensible (adapted it to work only in memory+tmpfs without touching disk - specific corner-case... Very easily) and readable. It's also funny to scale to multiple cores and multiple machines.
(I kinda made a Java version https://github.com/cretz/javan-warty-pig that attempts to mimic this logic)
https://github.com/vanhauser-thc/AFLplusplus
AFL itself hasn't seen updates in years.
While AFL++ is cool, it sort of ditches that philosophy, giving you a lot of options to tweak, but not necessarily a whole lot of hope that you're going to tweak them the right way. So, that's one gotcha to keep in mind.
Both the tool and the documentation made it easy for me jump in, identify bugs, write new test cases, implement a fix, and verify the fix passed without issue. I've mentioned it on HN before, but AFL taught me how incredibly difficult it is, even for experts (think most senior engineers at a FAANG) in the field, to write C++ without security vulnerabilities. I was even able to find and fix bugs which were previously reported but no one was able to reproduce reliably.
If there was an AFL t-shirt, I'd wear it ;-)
Right now at work I'm modifying an old C++ codebase, and knowing that AFL can't crash it is just one of the main things letting me sleep at night. (When I first set it up, it almost immediately found two minor bugs that were obvious in retrospect).
https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
I think there have been many more even than these, but can't think of how else to search for them.
Chrome browser will rendering non-HTTPS sites as "not secure". And the download links are local.