AFL for Ruby! You can learn more about AFL itself here.
afl-ruby
is not yet available on Rubygems, so for now you'll have to clone and build it yourself.
git clone git@github.com:richo/afl-ruby.git
You will need to manually build the native extension to the Ruby interpreter in order to allow AFL to instrument your Ruby code. To do this:
cd lib/afl
ruby ../../ext/afl_ext/extconf.rb
make
To instrument your code for AFL, call AFL.init
when you're ready to initialize the AFL forkserver,
then wrap the block of code that you want to fuzz in AFL.with_exceptions_as_crashes { ... }
. For
example:
def byte
$stdin.read(1)
end
def c
r if byte == 'r'
end
def r
s if byte == 's'
end
def s
h if byte == 'h'
end
def h
raise "Crashed"
end
require 'afl'
unless ENV['NO_AFL']
AFL.init
end
AFL.with_exceptions_as_crashes do
c if byte == 'c'
exit!(0)
end
You should then be able to run the sample harness in the example/
directory.
Because we're using a bog stock ruby interpreter, we must set the environment variable AFL_SKIP_BIN_CHECK=1
to prevent AFL from checking to see if our binary is instrumented.
AFL_SKIP_BIN_CHECK=1 /path/to/afl/afl-fuzz -i example/work/input -o example/work/output -- /usr/bin/ruby example/harness.rb
It should only take a few seconds to find a crash. Once a crash is found it should be written to example/work/output/crashes/
for you to inspect.
If AFL complains that Program '/usr/bin/ruby' is not a 64-bit Mach-O binary
then this may be because your system Ruby has the old Mach-O magic header bytes, which AFL does not accept. You should try running afl-fuzz
using a different Ruby interpreter. For example, you can use an rbenv Ruby like so:
# Find out which versions rbenv has available
ls ~/.rbenv/versions
# Pick an available version, then run something like this:
AFL_SKIP_BIN_CHECK=1 /path/to/afl/afl-fuzz -i work/input -o work/output -- ~/.rbenv/versions/2.4.1/bin/ruby harness.rb
Be sure to build the C extension (see "Build the extension" above).
To run the basic test suite, simply run:
rake test
Make sure you have built the extension first, as above.
Substantial portions of afl-ruby are either inspired by, or transposed directly from afl-python by Jakub Wilk jwilk@jwilk.net licensed under MIT.
Stripe allowed both myself and rob to spend substantial amounts of company time developing afl-ruby.