mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Fix and improve AFL linux example
This commit is contained in:
@@ -17,35 +17,44 @@ Steps:
|
||||
$ 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
|
||||
|
||||
sys.path.append("../../..")
|
||||
QLHOME = os.path.realpath(r'../../..')
|
||||
|
||||
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
|
||||
@@ -54,23 +63,24 @@ def main(input_file: str):
|
||||
"""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])
|
||||
|
||||
# get image base address
|
||||
ba = ql.loader.images[0].base
|
||||
# set afl instrumentation [re]starting point
|
||||
ql.hook_address(start_afl, main_begins)
|
||||
|
||||
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'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user