Fuzzilli is a JavaScript engine fuzzer written in Swift that is designed to generate semantically correct javascript. This blog series will be a deep dive into how Fuzzilli works!
Fuzzilli Internals
Fuzzilli works by using an intermediate language called FuzzIL. This language is used to represent javascript operations. Mutations are then defined on fuzzIL that ensure that it can only generate semantically correct code. This approach works better than generating a context free javascript grammar which would generate code that has mismatched types.
Data structures Overview
Opcodes
The most basic building blocks of FuzzIL are Opcodes.
1num Opcode {
2 case nop(Nop)
3 case loadInteger(LoadInteger)
4 <snip..>
5 case probe(Probe)
6 case fixup(Fixup)
7}
These Opcodes represent different fundamental actions in FuzzIL.
Operations
The operations datatype contains opcodes. Operations also contain attributes that have values like:
1struct Attributes: OptionSet {
2 static let isMutable = Attributes(rawValue: 1 << 1)
3 static let isCall = Attributes(rawValue: 1 << 2)
4 static let isBlockStart = Attributes(rawValue: 1 << 3)
5 static let isBlockEnd = Attributes(rawValue: 1 << 4)
6 static let isInternal = Attributes(rawValue: 1 << 5)
7 static let isJump = Attributes(rawValue: 1 << 6)
8 static let isVariadic = Attributes(rawValue: 1 << 7)
9 <snip..>
10}
OptionSets in Swift are a datatype where you can set different attributes as true or false. Attributes keep track of what certain Operations do. Operations also keep track of the number of inputs and outputs an operation has.
Code
The code datatype contains a list of Operations. It also has a check method that tests if the program is semantically correct.
Lift
Fuzzilli lifts FuzzIL into two formats: the first is a human-readable format. It looks like this:
v0 <- LoadInt '0'
v1 <- LoadInt '10'
v2 <- LoadInt '1'
v3 <- Phi v0
BeginFor v0, '<', v1, '+', v2 -> v4
v6 <- BinaryOperation v3, '+', v4
Copy v3, v6
EndFor
The second format is javascript:
1const v0 = 0;
2const v1 = 10;
3const v2 = 1;
4let v3 = v0;
5for (let v4 = v0; v4 < v1; v4 = v4 + v2) {
6 const v6 = v3 + v4;
7 v3 = v6;
8}
Sources
Thanks to Saelo for making an awesome learning resource for JavaScript fuzzing.
Saelo Offensivcon slides 2019
Fuzzilli Source code
HowFuzzilliworks