Skip to content

Problem while fuzzing with qiling #2

Open

Description

@SamNzo

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

Activity

  1. wtdcode commented on Apr 27, 2023

    @wtdcode
    Owner

    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.

  2. SamNzo commented on Apr 28, 2023

    @SamNzo
    Author

    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

  3. wtdcode commented on Apr 28, 2023

    @wtdcode
    Owner

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

  4. SamNzo commented on May 3, 2023

    @SamNzo
    Author

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions