Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Finding Mispriced Opcodes with Fuzzing - 1712

Max Ammann - Trail of Bits Posted 7 Months Ago
  • The author of this post was working on a project for the custom blockchain runtime Fuel VM. They created a fuzzing setup with special invariants to try to catch some bugs. The Fuel network team initially used libFuzzer and cargo-fuzz, but this was slow and didn't make any internal calls.
  • To get better coverage, they used a shim to inject in LibAFL. This allowed for the execution of 1K per second on an eight-core machine versus the original 50 per second.
  • An additional redesign was around the input generation. Originally, the input was a simple byte vector with not much else. Since the Sway language compiler has data interleaved with the actual instructions, the byte vector was ineffective. The input is now a byte vector that has the script assembly, script data, and a magic value separating them. Using this, they used the Sway compiler to obtain a large number of test inputs.
  • They ran into some issues with fuzzing. The program secp256k1 0.27.0 version is not compatible with cargo-fuzz because it fails all the time. So, they had to use a different version for fuzzing. Secondly, they ended up modifying the FuelVM somewhat to add the offset into the execution data to have this within the context of the program.
  • It is assumed this fuzzer was used for a large number of reasons, but a major one they used was gas usage. In most blockchain runtimes, different opcodes cost different amounts of the native currency to run. So, they wanted to see if the gas usage correlates with the execution time. They ran the fuzzer and plotted the information. Within the document, there are several for weird outliers.
  • Through doing this and finding the outliers, they were able to find opcodes that should cost more in gas. In the "lessons learned" section, they state that fuzzers should be run until new coverage stops, pause the campaign when issues are found to let developers fix them, and save the corpus generated from each test. This is because it represents hours of refinement to find the edge cases in the codebase.
  • Overall, a great look into setting up a legitimate fuzzing campaign. It was a unique reason to use fuzzing that turned up good results for them.