<-- back
               88@@                     
               88888X;                  
              S88888@8S8                
             .88@88@888@8.              
             @888888888X8S;             
           888888888S8t888@             
         88X888@%8%8%8@88%8S88          
         88888t8888t8t8;8888888         
        t88@88888%88 88 88@8;88S        
         8tX8S @@88.8 8 8tS88 8S8       
      88888 S8@@ @88X8;8 X@@  .888;     
     8888.  888;  8888%  @88S ;8%88S    
     8S888S      t8@888  8:8  .88%8X    
    :X8888SS    S8.88888     %888@XX    
  .88S8;8888:8S888SS8;88%@@8@8@8S8X88t  
 X8t8t88@8888 8@88@8X8S888 88888%88888X 
88t8.8;8;888t8:           8888:8;88888S8
8888t88%8X88888888%::8X888S8888X8%8X@@X:
 SX@8%88X8%88X8888888@888XX8888X88S8@88 
    888SS 8S    S8 %8.S8@8X888X% 88     
_____ _ | ___| _ _______(_)_ __ __ _ | |_ | | | |_ /_ / | '_ \ / _` | | _|| |_| |/ / / /| | | | | (_| | |_| \__,_/___/___|_|_| |_|\__, | |___/ ____ / ___|__ _ ___ __ _ | | / _` |/ __/ _` | | |__| (_| | (_| (_| | \____\__,_|\___\__,_| Fuzzing Caca and more Scott Griffy September 14th, 2016 (Note: This information is to be used for educational/research purposes only.) ------------------------------------------------------------------------------- -- Contents -- Introduction Materials Method Fuzzing Caca Fuzzing objdump Conclusion -- Introduction -- Fuzzing is a method which is now prevalent in the security researcher field. It's the process of sending random input to software to test if it will break. Pretty simple in concept, but fuzzers can become very complex. But for this blog post I'll be using a very simple fuzzer: zzuf. -- Materials -- Zzuf simply which simply changes a percentage of a file to random bytes. And is meant to be used on files that a program would normally work on without error. And I'll be fuzzing libcaca (where the title of this blog gets it's name). Libcaca is an ASCII utility library, specifically I'll be fuzzing the utility img2txt, which takes images and converts them into ASCII formats. -- Method -- I'm pretty much just following a guide I found online here: https://fuzzing-project.org/tutorial1.html Nothing all that fancy, but a good place to start. I've worked a lot with Image Magick, so I created the 3x3 image with that: $ convert -size 3x3 xc:white example.gif To get the different file formats, you use more convert commands like it says in the tutorial: $ convert example.png example.gif $ convert example.png example.xwd $ convert example.png example.tga Now, you use the fuzzer to get your giant array of corrupted images: $ for i in {1000..3000}; do for f in example.*; \ do zzuf -r 0.01 -s $i < "$f" > "$i-$f"; \ done; done I love bash, so this is how I do loops (also this is how the tutorial did it), but you might be able to do this another scripting language. This script is iterating from 1000 to 3000 and giving that as a seed to change a fraction (0.01) of the input file randomly. It's also iterating through all the different file formats I made with Image Magick. You can then use these images to test any program that would normally take images as an input. Because the format looks familiar it will get far into the code before an error is found, which usually has less secure code than the code that initially rejects files. Note that this is a lot faster if you make a ramfs or even better, use zzuf to fuzz and hand the files directy to the executable you're testing. -- Fuzzing Caca -- I marched my army of corrupted files to libcaca's door step, trying out the img2txt utility. The img2txt utility takes an image file and spits out an ASCII representation of it. $ bash -c ' \ echo `date`; \ for f in *-example*; do echo "doing $f"; \ img2txt $f 1>/dev/null ; \ done' &> i2tRes I'm iterating through all 2000 of the corrumpted image files and dumping the ASCII straight to /dev/null. The file 'i2tRes' is going to have the stderr of all the iterations and is hopefully going to have some segfaults to make this blog worthwhile ... And it did! ... at first. I found this in the output file: doing 2027-example.gif bash: line 1: 14537 Segmentation fault img2txt $f > /dev/null Wow! I found a bug! Well, hold on there. I was testing with the version of libcaca found in the debian repository: 0.99.beta19, but when I downloaded 0.99.beta20, I found that this bug had already been fixed, which makes sense because zzuf was written by the same guy who made libcaca. This illustrates a good takeaway for anyone doing security research: always use the latest version. It may save sometime to simply download the binaries from your repo, but this code is much less likely to have bugs in it. -- Fuzzing objdump -- Unphased by the defeat at the battle of img2txt, I struggled on to Firefox, where I couldn't find a good place to even create a test suite. Then to WordPress, whose json and emoji parsing engines could not be breached. Finally I decided to finish the tutorial I started because I thought it might have some more information I could use. And doing the very next step found me a legitimate bug: zzuf -s 0:1000000 -c -C 0 -q -T 3 objdump -x win9x.exe "win9x.exe" is from the tutorial's archive. The rest of the options get rid of stdin, create a timeout, "-c" isn't necessary and "-C 0" makes sure that the program finds as many bugs as it can. On seed 16915 it found a segfault! But surely this was because I was using an old stable release! ... Not so! I downloaded the source from GNU binutils' website, built it, and ran the test again: zzuf -s 16915 -c -C 0 -q -T 3 objdump -x win9x.exe And to my surprise it segfaulted. I then tried to run valgrind, but I didn't know exactly how to interpret it, so I ran gdb on it, which I use consistently to debug: $ gdb ~/checkout/binutils-gdb/binutils/objdump GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 ... Reading symbols from /home/grifball/checkout/binutils-gdb/binutils/objdump...done. (gdb) set args -x crash.exe (gdb) r Starting program: /home/grifball/checkout/binutils-gdb/binutils/objdump -x crash.exe Program received signal SIGSEGV, Segmentation fault. bfd_getl32 (p=0x85a000) at libbfd.c:552 552 return v; (gdb) where #0 bfd_getl32 (p=0x85a000) at libbfd.c:552 #1 0x00000000004acaea in _bfd_pei_swap_debugdir_in (abfd=abfd@entry=0x83a1c0, ext1=0x85a000, in1=in1@entry=0x7fffffffcfa0) at peigen.c:1116 #2 0x00000000004a89dc in pe_bfd_read_buildid (abfd=0x83a1c0) at peicode.h:1342 #3 pe_bfd_object_p (abfd=0x83a1c0) at peicode.h:1486 #4 0x000000000044913d in bfd_check_format_matches (abfd=abfd@entry=0x83a1c0, format=format@entry=bfd_object, matching=matching@entry=0x7fffffffded0) at format.c:308 #5 0x0000000000408888 in display_object_bfd (abfd=0x83a1c0) at ./objdump.c:3461 #6 display_any_bfd (file=file@entry=0x83a1c0, level=level@entry=0) at ./objdump.c:3552 #7 0x000000000040a9a3 in display_file (filename=0x7fffffffe2f0 "crash.exe", target=) at ./objdump.c:3573 #8 0x0000000000404cca in main (argc=3, argv=0x7fffffffe078) at ./objdump.c:3856 (gdb) Great! Now I have enough information to write up a bug report and file it. https://sourceware.org/bugzilla/show_bug.cgi?id=20605 -- Conclusion -- Hopefully this is just the beginning of my foray into fuzzing applications. I've learned a lot, such as not writing fuzzed iterations to disk, making sure to use the latest version of applications, and reading the tutorial fully. I think the next place I'm going from here is to use American Fuzzy Lop along with the address sanitizer. I ran the full 1000000 iterations on objdump, finding nothing. That bug find was literally one in a million.