Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem while fuzzing with qiling #2

Open
SamNzo opened this issue Apr 27, 2023 · 4 comments
Open

Problem while fuzzing with qiling #2

SamNzo opened this issue Apr 27, 2023 · 4 comments

Comments

@SamNzo
Copy link

SamNzo commented Apr 27, 2023

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

@wtdcode
Copy link
Owner

wtdcode commented Apr 27, 2023

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.

@SamNzo
Copy link
Author

SamNzo commented Apr 28, 2023

Thank you, this answers my first question !

But I still have two more:

  • Is it normal that when executing libfuzzer_x8664_linux.py I 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

@wtdcode
Copy link
Owner

wtdcode commented Apr 28, 2023

This doesn't seem correct indeed. Could you share the full reproduction case, including the script and binary?

@SamNzo
Copy link
Author

SamNzo commented May 3, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants