Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

afl++ addition #7

Merged
merged 10 commits into from
Oct 15, 2020
Merged

afl++ addition #7

merged 10 commits into from
Oct 15, 2020

Conversation

vanhauser-thc
Copy link
Contributor

Summary of the Pull Request

Adding afl++ as a default fuzzer, see #3

Info on Pull Request

adding afl++, basically just copying afl.* files to aflpp.* and making a few changes plus updating documentation

Validation Steps Performed

I am unsure if this is all that is needed. if so, sweet :)

@bmc-msft
Copy link
Contributor

Thanks for the contribution! With a few adjustments, this would be a beneficial contribution:

  1. The additional build script you added, src/ci/aflpp.sh, needs to be added to .github/workflows/ci.yml to execute.
  2. We pin all redistributed third-party tools needs to specific revisions. As AFL++ does regular releases, can you update to use a specific release, such as https://github.com/AFLplusplus/AFLplusplus/archive/2.68c.tar.gz?

Rather than adding another CLI subcommand to launch afl++, it would be useful to expose another command line argument to the existing 'afl' subcommand that allows the user to specify which AFL binary to execute. The auto-generation of CLI using python typing will need an update to support this easily. I'm happy to do that part for you.

@bmc-msft
Copy link
Contributor

Looking into the AFL template, we already allow the user to specify alternate implementations using 'fuzzer_setup_container', though it would be useful to enable providing a list of existing containers as possible options.

onefuzz template afl basic myproj target build-1 linux --fuzzer_setup_container aflpp-linux

@vanhauser-thc
Copy link
Contributor Author

  1. is done.
  2. we have a stable branch which is always the newest afl++ with current additions, to which we push every 2-4 weeks. currently it is 2.68c. This would prevent needing to push a new version every 1-2 months. (the checkout in this PR is to the stable branch). Would that be fine?
  3. this is a difficult question. afl and then sub commands for specific spin-offs or the specific spin-offs at the root command. IMHO It depends how compatible they are. e.g. afl++ has command line options that vanilla afl does not understand, also some environment variables. what do you think?

@bmc-msft
Copy link
Contributor

  1. I saw the update. Thanks! The llvm_mode does not compile. Based on the output, I think the github build VMs does not include the llvm-config prerequisite. In the short term, I think adding apt-get install llvm-config or apt-get install llvm will address this issue.

  2. Keeping third-party versions up-to-date is a requirement of the Onefuzz team. We are required to keep track of the version and license of every component that gets integrated.

  3. The need for researchers to specify custom arguments & environment variables is entirely reasonable and supported. I don't think we will want to try to keep up with fuzzing researcher's novel arguments & environment variables. Rather, our goal is to make it easy to specify anything custom, while providing basic sensible defaults as needed.

    In the afl commandline plugin, we provide a basic set of arguments to pass to afl-fuzz via --supervisor_options. By default for AFL, these are -d -i {input_corpus} -o {runtime_dir} -- {target_exe} {target_options}, where the onefuzz-agent replaces the '{str}' at runtime. Users can similarly specify environment variables via --supervisor_env KEY=VALUE KEY2=VALUE2.

from . import JobHelper


class AFL(Command):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class isn't used or exposed anywhere yet. FYI, to actually expose it as a subcommand of template, it would need to instantiated and bound to self in .template.Template.__init__().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we'd probably want to name this something like AFLPlusPlus to prevent ambiguity in the existing use site linked above.

@ranweiler
Copy link
Member

To note another option here: we could add a plusplus (sub-)subcommand to the existing AFL template. This would just mean adding a plusplus method to the existing .afl.AFL class.

Exposing AFL++ as a method is compatible with arbitrary API differences between AFL and AFL++. It does not require any actual tool similarity. Sharing the afl part really just provides namespacing, and if desired, a convenient way to share setup code between templates (via the AFL class).

With that approach, invoking would look like:

onefuzz template afl plusplus <...>

@vanhauser-thc
Copy link
Contributor Author

I renamed the class, pinned the checkout to v2.68c and installed the llvm components.

If there is any python stuff to do ... I can't do that. I can do C, C++, Assembly, even Perl ... but I stayed away from Python and anything beyond simple script changes is not something I feel comfortable to do :)

@bmc-msft
Copy link
Contributor

I renamed the class, pinned the checkout to v2.68c and installed the llvm components.

Can you prefix the 'apt' calls with sudo?

If there is any python stuff to do ... I can't do that. I can do C, C++, Assembly, even Perl ... but I stayed away from Python and anything beyond simple script changes is not something I feel comfortable to do :)

That's fine. Can you delete the python code? I'll take on exposing afl++ via CLI in a meaningful fashion.

@vanhauser-thc
Copy link
Contributor Author

sure! done.

src/ci/aflpp.sh Outdated Show resolved Hide resolved
src/ci/aflpp.sh Outdated Show resolved Hide resolved
@bmc-msft bmc-msft merged commit 5f7105f into microsoft:main Oct 15, 2020
ghost pushed a commit that referenced this pull request Mar 18, 2021
For a given entry in a call stack, this parses out the following: line, function name, function offset, source file name, source file line, module path, and module offset.

Additionally, this provides a code-generated libclusterfuzz port of the regular expressions used for stack minimization.

For an example of the minimization, instead of:
```json
[
"#0 0x56512a9c1418 in __sanitizer_print_stack_trace /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_stack.cpp:86:3",
"#1 0x56512aaaa42d in fuzzer::PrintStackTrace() third_party/libFuzzer/src/FuzzerUtil.cpp:205:5",
"#2 0x56512aa6a85e in fuzzer::Fuzzer::CrashCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:232:3",
"#3 0x56512aa6a7df in fuzzer::Fuzzer::StaticCrashSignalCallback() third_party/libFuzzer/src/FuzzerLoop.cpp:203:6",
"#4 0x56512aaab948 in fuzzer::CrashHandler(int, siginfo_t*, void*) third_party/libFuzzer/src/FuzzerUtilPosix.cpp:46:3",
"#5 0x7f1ee3f0188f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1288f)",
"#6 0x56512a9e5aa1 in Json::OurReader::parse(char const*, char const*, Json::Value&, bool) third_party/jsoncpp/source/src/lib_json/json_reader.cpp:1062:10",
"#7 0x56512a9eedb4 in Json::OurCharReader::parse(char const*, char const*, Json::Value*, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char> >*) third_party/jsoncpp/source/src/lib_json/json_reader.cpp:1899:23",
"#8 0x56512a9e03a3 in LLVMFuzzerTestOneInput third_party/jsoncpp/fuzzers/json_fuzzer.cc:39:24",
"#9 0x56512aa6d0cf in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) third_party/libFuzzer/src/FuzzerLoop.cpp:556:15",
"#10 0x56512aa3b7da in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) third_party/libFuzzer/src/FuzzerDriver.cpp:292:6",
"#11 0x56512aa4108a in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) third_party/libFuzzer/src/FuzzerDriver.cpp:774:9","#12 0x56512aa821ac in main third_party/libFuzzer/src/FuzzerMain.cpp:19:10",
"#13 0x7f1ee3361b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310",
]
```

The minimized call stack is:
```json
[
"Json::OurReader::parse(char const*, char const*, Json::Value&, bool)", 
"Json::OurCharReader::parse(char const*, char const*, Json::Value*, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char> >*)",
"json_fuzzer.cc"
]
```

This also provides a naïve function name list, which comes close to Clusterfuzz's function identification.

This would result in:
```json
[
    "Json::OurReader::parse",
    "Json::OurCharReader::parse",
    "json_fuzzer.cc"
]
```

Lastly, for our `stack hash` functionality used by the crash reporting task, those now provide the ability to specify the number of frames to include when building the hash.
ghost pushed a commit that referenced this pull request Mar 22, 2021
Adds `test-input` and `test-input-libfuzzer`, which print the CrashTestResult in json form.

While many of the existing tasks make sense running in a managed loop, crash report generation is something that having a single one-off is useful.

Example:
```
$ onefuzz-agent local test-input /tmp/fuzz.exe /tmp/crash.txt
{
  "crash_report": {
    "input_sha256": "a35b3ce1038750e9175a6dcd3f64c8d4e85720affb12cc11f5d0b6889274d06e",
    "executable": "/tmp/fuzz.exe",
    "crash_type": "SIGABRT",
    "crash_site": "0x7f0d9d4ad18b in gsignal+0xcb (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x4618b)",
    "call_stack": [
      "#0 0x7f0d9d4ad18b in gsignal+0xcb (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x4618b)",
      "#1 0x7f0d9d48c859 in abort+0x12b (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x25859)",
      "#2 0x7f0d9d4f73ee in <unknown> (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x903ee)",
      "#3 0x7f0d9d599b4a in __fortify_fail+0x2a (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x132b4a)",
      "#4 0x7f0d9d5983e6 in __chk_fail+0x16 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x1313e6)",
      "#5 0x7f0d9d597e09 in __strncpy_chk+0x19 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x130e09)",
      "#6 0x400a54 in from_file+0xa4 (/tmp/fuzz.exe+0xa54)",
      "#7 0x7f0d9d48e0b3 in __libc_start_main+0xf3 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x270b3)",
      "#8 0x40077a in _start+0x2a (/tmp/fuzz.exe+0x77a)"
    ],
    "call_stack_sha256": "6906234fb235690cc2843a1a55f49ff68b424e54bec55f9b8258415d97b3e638",
    "task_id": "00000000-0000-0000-0000-000000000000",
    "job_id": "00000000-0000-0000-0000-000000000000"
  }
}
$
```
ghost pushed a commit that referenced this pull request Mar 23, 2021
This builds upon #591 to expand the stack minimization to crash reporting mechanisms.

Example (see #703 for an example without the new functionality):

```
$ onefuzz-agent local test-input /tmp/fuzz.exe /etc/passwd
{
  "crash_report": {
    "input_sha256": "a35b3ce1038750e9175a6dcd3f64c8d4e85720affb12cc11f5d0b6889274d06e",
    "executable": "/tmp/fuzz.exe",
    "crash_type": "SIGABRT",
    "crash_site": "0x7ffff7e0d18b in gsignal+0xcb (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x4618b)",
    "call_stack": [
      "#0 0x7ffff7e0d18b in gsignal+0xcb (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x4618b)",
      "#1 0x7ffff7dec859 in abort+0x12b (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x25859)",
      "#2 0x7ffff7e573ee in <unknown> (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x903ee)",
      "#3 0x7ffff7ef9b4a in __fortify_fail+0x2a (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x132b4a)",
      "#4 0x7ffff7ef83e6 in __chk_fail+0x16 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x1313e6)",
      "#5 0x7ffff7ef7e09 in __strncpy_chk+0x19 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x130e09)",
      "#6 0x400a54 in from_file+0xa4 (/tmp/fuzz.exe+0xa54)",
      "#7 0x7ffff7dee0b3 in __libc_start_main+0xf3 (/usr/lib/x86_64-linux-gnu/libc-2.31.so+0x270b3)",
      "#8 0x40077a in _start+0x2a (/tmp/fuzz.exe+0x77a)"
    ],
    "call_stack_sha256": "99625a7c103136e02910b65c7b60f1bbd1a7612242d6838da52d968369039409",
    "minimized_stack": [
      "__fortify_fail",
      "__chk_fail",
      "from_file"
    ],
    "minimized_stack_sha256": "237f13bfa384c6c2bc06369099373efbb36995a9ad00fd5469d354b5fc672ba1",
    "minimized_stack_function_names": [
      "__fortify_fail",
      "__chk_fail",
      "from_file"
    ],
    "minimized_stack_function_names_sha256": "237f13bfa384c6c2bc06369099373efbb36995a9ad00fd5469d354b5fc672ba1",
    "asan_log": "",
    "task_id": "00000000-0000-0000-0000-000000000000",
    "job_id": "00000000-0000-0000-0000-000000000000"
  }
}
$
```
@ghost ghost locked as resolved and limited conversation to collaborators Apr 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants