Skip to content

Commit

Permalink
Fix and improve AFL linux example
Browse files Browse the repository at this point in the history
  • Loading branch information
elicn committed Mar 25, 2024
1 parent 08a780b commit 287cc9f
Showing 1 changed file with 31 additions and 21 deletions.
52 changes: 31 additions & 21 deletions examples/fuzzing/linux_x8664/fuzz_x8664_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,44 @@
$ rm -fr afl_outputs/default/
"""

# No more need for importing unicornafl, try afl.ql_afl_fuzz instead!

import os
import sys

from typing import Optional
from typing import Sequence

QLHOME = os.path.realpath(r'../../..')

sys.path.append("../../..")
sys.path.append(QLHOME)
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions import pipe
from qiling.extensions import afl

def main(input_file: str):
ql = Qiling(["./x8664_fuzz"], "../../rootfs/x8664_linux",
verbose=QL_VERBOSE.OFF, # keep qiling logging off
console=False) # thwart program output

def main(argv: Sequence[str], rootfs: str, infilename: str):
# initialize a qiling instance.
# note we keep verbosity off and thwart the program's output to gain some speed-up
ql = Qiling(argv, rootfs, verbose=QL_VERBOSE.OFF, console=False)

# get the image base address
img = ql.loader.get_image_by_name('x8664_fuzz')
assert img is not None

# fuzzing scope: the main function
main_begins = img.base + 0x1275
main_ends = img.base + 0x1293

# redirect stdin to our mock to feed it with incoming fuzzed keystrokes
ql.os.stdin = pipe.SimpleInStream(sys.stdin.fileno())

def place_input_callback(ql: Qiling, input: bytes, persistent_round: int) -> Optional[bool]:
def place_input_callback(ql: Qiling, feed: bytes, round: int) -> bool:
"""Feed generated stimuli to the fuzzed target.
This method is called with every fuzzing iteration.
"""

# feed fuzzed input to our mock stdin
ql.os.stdin.write(input)
ql.os.stdin.write(feed)

# signal afl to proceed with this input
return True
Expand All @@ -54,23 +63,24 @@ def start_afl(ql: Qiling):
"""Have Unicorn fork and start instrumentation.
"""

afl.ql_afl_fuzz(ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
afl.ql_afl_fuzz(ql, infilename, place_input_callback, [main_ends])

# set afl instrumentation [re]starting point
ql.hook_address(start_afl, main_begins)

# get image base address
ba = ql.loader.images[0].base
def __crash(ql: Qiling) -> None:
os.abort()

# make the process crash whenever __stack_chk_fail@plt is about to be called.
# this way afl will count stack protection violations as crashes
ql.hook_address(callback=lambda x: os.abort(), address=ba + 0x126e)

# set afl instrumentation [re]starting point. we set it to 'main'
ql.hook_address(callback=start_afl, address=ba + 0x1275)
ql.hook_address(__crash, img.base + 0x126e)

# okay, ready to roll
ql.run()

if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")

main(sys.argv[1])
main(
rf'{QLHOME}/examples/fuzzing/linux_x8664/x8664_fuzz'.split(),
rf'{QLHOME}/examples/rootfs/x8664_linux',
rf'{QLHOME}/examples/fuzzing/linux_x8664/afl_inputs/a'
)

0 comments on commit 287cc9f

Please sign in to comment.