Problem while fuzzing with qiling
I am trying to use fuzzercorn with qiling with this example: https://github.com/qilingframework/qiling/blob/master/examples/fuzzing/linux_x8664/libfuzzer_x8664_linux.py
I first installed fuzzercorn with pip but when executing libfuzzer_x8664_linux.py I got the following
WARNING: Failed to find function "__sanitizer_acquire_crash_state".
WARNING: Failed to find function "__sanitizer_print_stack_trace".
WARNING: Failed to find function "__sanitizer_set_death_callback".
It expected an input as if I executed the binary without fuzzing and then returned a seg fault
To fix it I tried to clone the fuzzercorn repo, build libfuzzercorn.so and create a sym link between it and the one I installed with pip
This time when executing libfuzzer_x8664_linux.py I still had this waiting for an input
WARNING: Failed to find function "__sanitizer_acquire_crash_state".
WARNING: Failed to find function "__sanitizer_print_stack_trace".
WARNING: Failed to find function "__sanitizer_set_death_callback".
But when I entered one it looked like libfuzzer was working
A
A�Y���
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1757911264
INFO: 4096 Extra Counters
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED ft: 2 corp: 1/1b exec/s: 0 rss: 84Mb
#2048 pulse ft: 2 corp: 1/1b lim: 21 exec/s: 682 rss: 86Mb
#4096 pulse ft: 2 corp: 1/1b lim: 43 exec/s: 682 rss: 87Mb
#8192 pulse ft: 2 corp: 1/1b lim: 80 exec/s: 630 rss: 89Mb
#16384 pulse ft: 2 corp: 1/1b lim: 163 exec/s: 630 rss: 93Mb
However it keeps doing this until it eventually runs out of memory without finding any crash
I'm confused, do you know what am I doing wrong ?
thx
Hey, thanks for your interest! The symbol seems from sanitizers and shouldn't be used with fuzzercorn actually. i.e. you could safely ignore them.
Thank you, this answers my first question !
But I still have two more:
- Is it normal that when executing
libfuzzer_x8664_linux.pyI then have to manually enter an input ? shouldn't it be done automatically while fuzzing ? - The output from libFuzzer shows that it never gets any new coverage and cant find any crash
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1269338389
INFO: 4096 Extra Counters
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED ft: 186 corp: 1/1b exec/s: 0 rss: 86Mb
#2048 pulse ft: 186 corp: 1/1b lim: 21 exec/s: 682 rss: 87Mb
#4096 pulse ft: 186 corp: 1/1b lim: 43 exec/s: 682 rss: 88Mb
#8192 pulse ft: 186 corp: 1/1b lim: 80 exec/s: 682 rss: 90Mb
#16384 pulse ft: 186 corp: 1/1b lim: 163 exec/s: 655 rss: 95Mb
#32768 pulse ft: 186 corp: 1/1b lim: 325 exec/s: 642 rss: 103Mb
#65536 pulse ft: 186 corp: 1/1b lim: 652 exec/s: 624 rss: 120Mb
#131072 pulse ft: 186 corp: 1/1b lim: 1300 exec/s: 648 rss: 155Mb
It tried to modify the addresses in libfuzzer_x8664_linux.py for fun, ___stack_chk_fail and main with the ones I had in IDA but it doesnt change anything
This doesn't seem correct indeed. Could you share the full reproduction case, including the script and binary?
The script is the following:
#!/usr/bin/python3
from fuzzercorn import *
from unicorn import *
from qiling import Qiling
from qiling.extensions import pipe
import sys, os, ctypes
class SimpleFuzzer:
def run(self):
ql = Qiling(["./x8664_fuzz"], "../../rootfs/x8664_linux", console=False)
ba = ql.loader.images[0].base
try:
# Only instrument the function `fun`, so we don't need to instrument libc and ld
FuzzerCornFuzz(ql.uc, sys.argv, [ql.os.exit_point], self.place_input, self.init, UserData=ql, Ranges=[(ba+0x11c9, ba+0x1274)], CountersCount=4096)
except Exception as ex:
os.abort() # Quick exit
def place_input(self, uc: Uc, data: ctypes.Array, ql: Qiling):
# Restore from snapshot
ql.restore(self.snapshot)
ql.os.stdin = pipe.SimpleInStream(1)
ql.os.stdin.write(bytes(data))
return 1
def init(self, uc: Uc, argv: list, ql: Qiling):
ba = ql.loader.images[0].base
# Call os.abort when ___stack_chk_fail is called (stack overflow)
ql.hook_address(callback=lambda x: os.abort(), address=ba+0x126e) # ___stack_chk_fail
# Execute binary until given address
ql.run(end=ba+0x1293) # Run to main.
# Save a snapshot.
self.snapshot = ql.save()
return 0
if __name__ == "__main__":
# chmod +x ./libfuzzer_x8664_linux.py
# ./libfuzzer_x8664_linux.py -jobs=6 -workers=6
SimpleFuzzer().run()
The binary is: https://github.com/qilingframework/qiling/blob/master/examples/fuzzing/linux_x8664/x8664_fuzz