Fuzzilii is a JavaScript engine fuzzing library, it’s a coverage-guided fuzzer for dynamic language interpreters based on a custom intermediate language (“FuzzIL”) which can be mutated and translated to JavaScript.
When fuzzing for core interpreter bugs, e.g. in JIT compilers, semantic correctness of generated programs becomes a concern. This is in contrast to most other scenarios, e.g. fuzzing of runtime APIs, in which case semantic correctness can easily be worked around by wrapping the generated code in try-catch constructs. There are different possibilities to achieve an acceptable rate of semantically correct samples, one of them being a mutational approach in which all samples in the corpus are also semantically valid. In that case, each mutation only has a small chance of turning a valid sample into an invalid one.
Using Fuzzilli JavaScript Engine Fuzzing Library
The basic steps to use this fuzzer are:
- Download the source code for one of the supported JavaScript engines. See the Targets/ directory for the list of supported JavaScript engines.
- Apply the corresponding patches from the target’s directory. Also see the README.md in that directory.
- Compile the engine with coverage instrumentation (requires clang >= 4.0) as described in the README.
- Compile the fuzzer:
swift build [-c release]
. - Run the fuzzer:
swift run [-c release] FuzzilliCli --profile=
. See also swift run[other cli options] /path/to/jsshell FuzzilliCli --help
.
How FuzzIl works
FuzzIL has a number of properties:
- A FuzzIL program is simply a list of instructions.
- A FuzzIL instruction is an operation together with input and output variables and potentially one or more parameters (enclosed in single quotes in the notation above).
- Inputs to instructions are always variables, there are no immediate values.
- Every output of an instruction is a new variable, and existing variables can only be reassigned through dedicated operations such as the Reassign instruction.
- Every variable is defined before it is used.
A number of mutations can then be performed on these programs:
- InputMutator: replaces input variables of instructions with different ones to mutate the dataflow of the program.
- CodeGenMutator: generates code and inserts it somewhere in the mutated program. Code is generated either by running a code generator or by copying some instructions from another program in the corpus (splicing).
- CombineMutator: inserts a program from the corpus into a random position in the mutated program.
- OperationMutator: mutates the parameters of operations, for example replacing an integer constant with a different one.
- and more…
You can download Fuzzilli here:
Or read more here.