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
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ jobs:
with:
name: build-artifacts
path: artifacts
aflpp:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- run: src/ci/aflpp.sh
- uses: actions/upload-artifact@v2.1.4
with:
name: build-artifacts
path: artifacts
radamsa-linux:
runs-on: ubuntu-18.04
steps:
Expand Down
2 changes: 1 addition & 1 deletion docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ include:
* supervisor_env: User specified environment variables for the supervisor
* supervisor_options: User specified command line options for the supervisor
* supervisor_input_marker: Marker to specify the path to the filename for
supervisors (Example: for AFL, this should be '@@')
supervisors (Example: for AFL and AFL++, this should be '@@')
bmc-msft marked this conversation as resolved.
Show resolved Hide resolved
* stats_file: Path to the fuzzer's stats file
* stats_format: Format of the fuzzer's stats file
* input_queue_from_container: Container name to monitor for new changes.
Expand Down
3 changes: 2 additions & 1 deletion docs/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ Users should take care over the following items:
* radamsa-linux
* radamsa-windows
* afl-linux
* aflpp-linux
1. Any jobs deployed during the upgrade process may temporarily fail to be
submitted.
The CLI will automatic retry to submit jobs that fail due error codes known
to happen during the service upgrade procedure. If this behavior is
undesired, please pause submission of jobs during the upgrade process.
undesired, please pause submission of jobs during the upgrade process.
15 changes: 15 additions & 0 deletions src/ci/aflpp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

mkdir -p artifacts/third-party/aflpp-linux

git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make
(test -e llvm_mode && cd llvm_mode && make)
(test -e gcc_plugin && cd gcc_plugin && make)
(cd examples/libdislocator && make)
bmc-msft marked this conversation as resolved.
Show resolved Hide resolved

cp -rf afl-* *.so *.a dictionaries examples/libdislocator/libdislocator.so LICENSE ../artifacts/third-party/aflpp-linux
169 changes: 169 additions & 0 deletions src/cli/onefuzz/templates/aflpp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/usr/bin/env python
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from typing import Dict, List, Optional

from onefuzztypes.enums import OS, ContainerType, StatsFormat, TaskType
from onefuzztypes.models import NotificationConfig
from onefuzztypes.primitives import Container, Directory, File

from onefuzz.api import Command

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.

""" Pre-defined AFL job """

def basic(
self,
project: str,
name: str,
build: str,
*,
pool_name: str,
target_exe: File = File("fuzz.exe"),
setup_dir: Optional[Directory] = None,
vm_count: int = 2,
inputs: Optional[Directory] = None,
reboot_after_setup: bool = False,
duration: int = 24,
target_options: Optional[List[str]] = None,
supervisor_exe: str = "{tools_dir}/afl-fuzz",
supervisor_options: List[str] = [
"-d",
"-i",
"{input_corpus}",
"-o",
"{runtime_dir}",
"--",
"{target_exe}",
"{target_options}",
],
supervisor_env: Optional[Dict[str, str]] = None,
supervisor_input_marker: str = "@@",
tags: Optional[Dict[str, str]] = None,
wait_for_running: bool = False,
wait_for_files: Optional[List[ContainerType]] = None,
fuzzer_setup_container: Optional[Container] = None,
existing_inputs: Optional[Container] = None,
dryrun: bool = False,
notification_config: Optional[NotificationConfig] = None,
) -> None:
""" Basic AFL job """

if existing_inputs:
self.onefuzz.containers.get(existing_inputs)

if dryrun:
return

self.logger.info("creating afl++ from template")

target_options = target_options or ["{input}"]

helper = JobHelper(
self.onefuzz,
self.logger,
project,
name,
build,
duration,
pool_name=pool_name,
target_exe=target_exe,
)
helper.add_tags(tags)
helper.define_containers(
ContainerType.setup,
ContainerType.crashes,
ContainerType.reports,
ContainerType.unique_reports,
)
if existing_inputs:
self.onefuzz.containers.get(existing_inputs)
helper.containers[ContainerType.inputs] = existing_inputs
else:
helper.define_containers(ContainerType.inputs)

helper.create_containers()
helper.setup_notifications(notification_config)
helper.upload_setup(setup_dir, target_exe)
if inputs:
helper.upload_inputs(inputs)
helper.wait_on(wait_for_files, wait_for_running)

if (
len(
self.onefuzz.containers.files.list(
helper.containers[ContainerType.inputs]
).files
)
== 0
):
raise Exception("AFL++ requires at least one input")

target_exe_blob_name = helper.target_exe_blob_name(target_exe, setup_dir)

if fuzzer_setup_container is None:
fuzzer_setup_container = Container(
"aflpp-linux" if helper.platform == OS.linux else "aflpp-windows"
)

containers = [
(ContainerType.tools, fuzzer_setup_container),
(ContainerType.setup, helper.containers[ContainerType.setup]),
(ContainerType.crashes, helper.containers[ContainerType.crashes]),
(ContainerType.inputs, helper.containers[ContainerType.inputs]),
]

self.logger.info("creating afl++ fuzz task")
fuzzer_task = self.onefuzz.tasks.create(
helper.job.job_id,
TaskType.generic_supervisor,
target_exe_blob_name,
containers,
pool_name=pool_name,
duration=duration,
vm_count=vm_count,
reboot_after_setup=reboot_after_setup,
target_options=target_options,
supervisor_exe=supervisor_exe,
supervisor_options=supervisor_options,
supervisor_env=supervisor_env,
supervisor_input_marker=supervisor_input_marker,
stats_file="{runtime_dir}/fuzzer_stats",
stats_format=StatsFormat.AFL,
task_wait_for_files=ContainerType.inputs,
tags=helper.tags,
)

report_containers = [
(ContainerType.setup, helper.containers[ContainerType.setup]),
(ContainerType.crashes, helper.containers[ContainerType.crashes]),
(ContainerType.reports, helper.containers[ContainerType.reports]),
(
ContainerType.unique_reports,
helper.containers[ContainerType.unique_reports],
),
]

self.logger.info("creating generic_crash_report task")
self.onefuzz.tasks.create(
helper.job.job_id,
TaskType.generic_crash_report,
target_exe_blob_name,
report_containers,
pool_name=pool_name,
duration=duration,
vm_count=1,
reboot_after_setup=reboot_after_setup,
target_options=target_options,
check_debugger=True,
tags=tags,
prereq_tasks=[fuzzer_task.task_id],
)

self.logger.info("done creating tasks")
helper.wait()