1/ Let's play
Let's play with the fuzzer
afl. I'll write some blogposts about my research with afl. This can be seen as a diary of a fuzzer :-)
2/ At first, choose your target
I think that afl has been pretty much used on usual unix binaries (compressor, file format, and so on), so I did a
$ ls /usr/bin
and choose one of them in order to fuzz. afl is great at fuzzing programs which take a file as argument and don't produce too much output. There is a lot of them which can be fuzzed.
That's easy, just grab the sources of the binary you want to fuzz, recompile it using afl-gcc (or afl-g++), and roll!
Sometimes, it's better to desactivate checksum computations: fuzzing goes faster, fuzzing goes farther (doesn't stop for a bad checksum) and in case of a crash, you can easily recalculate the checksum and see if crash is still here.
After fuzzing a lot of software, I managed to reach two crashes:
That's enough for a good start. Those two crashes will be investigated.
I don't look at hangs: my computer do a lot of things (loadavg > 1 most of the time), and afl has an aggressive value of 50ms for saying that program has stopped. So, there is a lot of false positive. And I'm mostly interested in crashes anyway.
3/ Keep focused
Afl comes with an handy helper call Peruvian were rabbit. Just feed afl-fuzz with some known files causing a crash and it will make some variation around it in order to see if some new crashes appears.
$ cd ..
$ mkdir crashes crashes/findings crashes/testcases
$ cp fuzzy/findings/crashes/id\:000001* crashes/testcases/case1
$ cp fuzzy/findings/crashes/id\:000002* crashes/testcases/case2
$ cd crashes
$ afl-gcc -C -i testcases/ -o findings/ unnamed -t @@
And unsurprisingly, number of crashes grow very fast:
I have now 255 files causing crashes.
What's really interesting in my case is that the unmodified program (the one doing checksum) segfaults too :-) It writes a message "bad checksum", but segfault like a boss:
mitsurugi@mitsu:~/fuzz$ ./unnamed-no-cksum -t case1
Segmentation fault
mitsurugi@mitsu:~/fuzz$ ./unnamed-ori -t case1
failed (checksum error)
Segmentation fault
mitsurugi@mitsu:~/fuzz$
mitsurugi@mitsu:~/fuzz$ ./unnamed-no-cksum -t case1
Segmentation fault
mitsurugi@mitsu:~/fuzz$ dmesg | tail -1
[784784.901989] unnamed-no-cksum[29344]: segfault at 0 ip (null) sp bf89d38c error 14 in unnamed-no-cksum[8048000+57000]
And it seems promising, because it crash on a bad EIP value (and not a losy read or write in forbidden location). My senseï said:
"If you manage to control EIP, you'll soon manage to control the world"
4/ Let's investigate
I have a good lead, the next step is to force EIP to a choosen value (0x41414141 for example) instead of 0x00000000.
The crash appears here:
=> 0x804daf0: call DWORD PTR [eax+0x40]
0x804daf3: cmp eax,0x3
0x804daf6: je 0x804db54
And the memory layout around eax is:
gdb$ x/12dwx $eax + 0x30
0x80618b0: 0x0804a580 0x0804a560 0x00000000 0x0000eaea
0x80618c0: 0x00000000 0x00000000 0x080601e8 0x08060080
0x80618d0: 0x00000000 0x080618dc 0x080618dc 0x00000000
gdb$
unfortunately, I don't have 0xeaea followed by some 0x00 in source file. So I think I'll have to dig really further.
I also have 255 files, I choose 10 of them, all of them crash with EIP=0x00000000. It's time to industrialize the checkings.
That's all for today :-)
Mitsurugi