-
-
Notifications
You must be signed in to change notification settings - Fork 293
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
Qemu arm launcher #708
Merged
Merged
Qemu arm launcher #708
Changes from 4 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
0c4a5be
Adding qemu_arm_launcher crate
TeumessianFox 20f9045
Trying to fix qemu arm usermode
TeumessianFox 25aaa32
Cargo fmt
TeumessianFox a7890ff
Adding CROSS_CC env
TeumessianFox f529cf2
Remove hardcoded arm-linux-gnueabi-gcc and replace by CROSS_CC
TeumessianFox 373ff7b
Adding arm-linux-gnueabi-gcc to github workflows for ubuntu
TeumessianFox e74c908
Fixing typo in apt install package
TeumessianFox 20f51cd
Resetting LR after each fuzzing emulation
TeumessianFox 2b69255
Merge branch 'main' into qemu_arm_launcher
TeumessianFox e4b10e5
Cargo fmt after merge conflict
TeumessianFox b7d7a80
Using GuestAddr
TeumessianFox 1b0f64f
Compiling, running and running with artificial crash detection
TeumessianFox f91237d
Merge branch 'main' into qemu_arm_launcher
TeumessianFox cd0ba61
Adding dependencies for github workflow to cross compile for arm
TeumessianFox 48f48fd
Merge branch 'qemu_arm_launcher' of github.com:TeumessianFox/LibAFL i…
TeumessianFox 36ff165
Fixing github workflow for ubuntu fuzzer
TeumessianFox 61d2a76
arm-linux-binutils for mac in github workflows
TeumessianFox da4ee5a
Qemu does not work for mac, no need to compile qemu_arm_launcher harn…
TeumessianFox abc4cd6
Merge branch 'main' into qemu_arm_launcher
TeumessianFox File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ vendor | |
.env | ||
|
||
*.tmp | ||
*.swp | ||
*.o | ||
*.a | ||
*.so | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
libpng-* | ||
libpng_harness | ||
zlib-* | ||
crashes | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "qemu_arm_launcher" | ||
version = "0.8.0" | ||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"] | ||
edition = "2018" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [] | ||
|
||
[profile.release] | ||
#lto = true | ||
#codegen-units = 1 | ||
#opt-level = 3 | ||
debug = true | ||
|
||
[dependencies] | ||
libafl = { path = "../../libafl/" } | ||
libafl_qemu = { path = "../../libafl_qemu/", features = ["arm"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Variables | ||
[env] | ||
FUZZER_NAME='libpng_harness' | ||
PROJECT_DIR = { script = ["pwd"] } | ||
CROSS_CC = "arm-linux-gnueabi-gcc" | ||
|
||
[tasks.unsupported] | ||
script_runner="@shell" | ||
script=''' | ||
echo "Qemu fuzzer not supported on windows" | ||
''' | ||
|
||
#zlib | ||
[tasks.zlib] | ||
linux_alias = "zlib_unix" | ||
mac_alias = "zlib_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.zlib_unix_wget] | ||
condition = { files_not_exist = [ "./zlib-1.2.12" ] } | ||
script_runner="@shell" | ||
script=''' | ||
wget http://www.zlib.net/zlib-1.2.12.tar.gz | ||
tar -xvf zlib-1.2.12.tar.gz | ||
''' | ||
|
||
[tasks.zlib_unix] | ||
condition = { files_not_exist = [ "./zlib-1.2.12/zlib/lib/libz.a" ] } | ||
script_runner="@shell" | ||
script=''' | ||
cd zlib-1.2.12 && CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar ./configure --prefix=./zlib | ||
make install | ||
''' | ||
dependencies = [ "zlib_unix_wget" ] | ||
|
||
# libpng | ||
[tasks.libpng] | ||
linux_alias = "libpng_unix" | ||
mac_alias = "libpng_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.libpng_unix_wget] | ||
condition = { files_not_exist = [ "./libpng-1.6.37" ] } | ||
script_runner="@shell" | ||
script=''' | ||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz | ||
tar -xvf libpng-1.6.37.tar.xz | ||
''' | ||
|
||
[tasks.libpng_unix] | ||
condition = { files_not_exist = [ "./libpng-1.6.37/.libs/libpng16.a" ] } | ||
script_runner="@shell" | ||
script=''' | ||
cd libpng-1.6.37 && CC=arm-linux-gnueabi-gcc CFLAGS=-I../zlib-1.2.12/zlib/lib LDFLAGS=-L../zlib-1.2.12/zlib/lib ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes --host=arm | ||
make | ||
''' | ||
dependencies = [ "zlib", "libpng_unix_wget" ] | ||
|
||
# fuzzer | ||
[tasks.fuzzer] | ||
linux_alias = "fuzzer_unix" | ||
mac_alias = "fuzzer_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.fuzzer_unix] | ||
command = "cargo" | ||
args = ["build", "--release"] | ||
|
||
# Harness | ||
[tasks.harness] | ||
linux_alias = "harness_unix" | ||
mac_alias = "harness_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.harness_unix] | ||
script_runner="@shell" | ||
script=''' | ||
# Build the libpng harness | ||
arm-linux-gnueabi-g++ \ | ||
./harness.cc \ | ||
./libpng-1.6.37/.libs/libpng16.a \ | ||
./zlib-1.2.12/zlib/lib/libz.a \ | ||
-I./libpng-1.6.37/ \ | ||
-I../zlib-1.2.12/zlib/lib \ | ||
-L../zlib-1.2.12/zlib/lib \ | ||
-o ${FUZZER_NAME} \ | ||
-lm \ | ||
-static | ||
''' | ||
dependencies = [ "libpng" ] | ||
|
||
# Run the fuzzer | ||
[tasks.run] | ||
linux_alias = "run_unix" | ||
mac_alias = "run_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.run_unix] | ||
command = "cargo" | ||
args = ["run", "--release", "./${FUZZER_NAME}"] | ||
dependencies = [ "harness", "fuzzer" ] | ||
|
||
# Run the fuzzer | ||
[tasks.test] | ||
linux_alias = "test_unix" | ||
mac_alias = "test_unix" | ||
windows_alias = "unsupported" | ||
|
||
# Short test | ||
[tasks.test_unix] | ||
script_runner = "@shell" | ||
script=''' | ||
rm -rf libafl_unix_shmem_server || true | ||
timeout 11s cargo run --release ./${FUZZER_NAME} 2>/dev/null & | ||
''' | ||
dependencies = [ "harness", "fuzzer" ] | ||
|
||
# Clean up | ||
[tasks.clean] | ||
linux_alias = "clean_unix" | ||
mac_alias = "clean_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.clean_unix] | ||
# Disable default `clean` definition | ||
clear = true | ||
script_runner="@shell" | ||
script=''' | ||
rm -f ./${FUZZER_NAME} | ||
rm -rf zlib-* | ||
rm -rf libpng-* | ||
cargo clean | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# LibAFL with launcher for libpng with qemu arm in usermode | ||
|
||
This folder contains an example fuzzer for libpng using the qemu emulator in arm usermode. | ||
To show off crash detection, we added a `ud2` instruction to the harness, edit harness.cc if you want a non-crashing example. | ||
It has been tested on Linux. | ||
|
||
In contrast to the normal libfuzzer libpng example, this uses the `launcher` feature, that automatically spawns `n` child processes, and binds them to a free core. | ||
|
||
## Prerequisites | ||
```bash | ||
sudo apt install arm-linux-gnueabi-gcc g++-arm-linux-gnueabi | ||
``` | ||
|
||
## Run | ||
|
||
```bash | ||
cargo make run | ||
``` |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
// libpng_read_fuzzer.cc | ||
// Copyright 2017-2018 Glenn Randers-Pehrson | ||
// Copyright 2015 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that may | ||
// be found in the LICENSE file https://cs.chromium.org/chromium/src/LICENSE | ||
|
||
// Last changed in libpng 1.6.35 [July 15, 2018] | ||
|
||
// The modifications in 2017 by Glenn Randers-Pehrson include | ||
// 1. addition of a PNG_CLEANUP macro, | ||
// 2. setting the option to ignore ADLER32 checksums, | ||
// 3. adding "#include <string.h>" which is needed on some platforms | ||
// to provide memcpy(). | ||
// 4. adding read_end_info() and creating an end_info structure. | ||
// 5. adding calls to png_set_*() transforms commonly used by browsers. | ||
|
||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
#include <vector> | ||
|
||
#define PNG_INTERNAL | ||
#include "png.h" | ||
|
||
#define PNG_CLEANUP \ | ||
if (png_handler.png_ptr) { \ | ||
if (png_handler.row_ptr) \ | ||
png_free(png_handler.png_ptr, png_handler.row_ptr); \ | ||
if (png_handler.end_info_ptr) \ | ||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \ | ||
&png_handler.end_info_ptr); \ | ||
else if (png_handler.info_ptr) \ | ||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \ | ||
nullptr); \ | ||
else \ | ||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \ | ||
png_handler.png_ptr = nullptr; \ | ||
png_handler.row_ptr = nullptr; \ | ||
png_handler.info_ptr = nullptr; \ | ||
png_handler.end_info_ptr = nullptr; \ | ||
} | ||
|
||
struct BufState { | ||
const uint8_t *data; | ||
size_t bytes_left; | ||
}; | ||
|
||
struct PngObjectHandler { | ||
png_infop info_ptr = nullptr; | ||
png_structp png_ptr = nullptr; | ||
png_infop end_info_ptr = nullptr; | ||
png_voidp row_ptr = nullptr; | ||
BufState *buf_state = nullptr; | ||
|
||
~PngObjectHandler() { | ||
if (row_ptr) { png_free(png_ptr, row_ptr); } | ||
if (end_info_ptr) | ||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr); | ||
else if (info_ptr) | ||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); | ||
else | ||
png_destroy_read_struct(&png_ptr, nullptr, nullptr); | ||
delete buf_state; | ||
} | ||
}; | ||
|
||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) { | ||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr)); | ||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); } | ||
memcpy(data, buf_state->data, length); | ||
buf_state->bytes_left -= length; | ||
buf_state->data += length; | ||
} | ||
|
||
static const int kPngHeaderSize = 8; | ||
|
||
// Entry point for LibFuzzer. | ||
// Roughly follows the libpng book example: | ||
// http://www.libpng.org/pub/png/book/chapter13.html | ||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | ||
if (size < kPngHeaderSize) { return 0; } | ||
|
||
std::vector<unsigned char> v(data, data + size); | ||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { | ||
// not a PNG. | ||
return 0; | ||
} | ||
|
||
PngObjectHandler png_handler; | ||
png_handler.png_ptr = nullptr; | ||
png_handler.row_ptr = nullptr; | ||
png_handler.info_ptr = nullptr; | ||
png_handler.end_info_ptr = nullptr; | ||
|
||
png_handler.png_ptr = | ||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); | ||
if (!png_handler.png_ptr) { return 0; } | ||
|
||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr); | ||
if (!png_handler.info_ptr) { | ||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr); | ||
if (!png_handler.end_info_ptr) { | ||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); | ||
#ifdef PNG_IGNORE_ADLER32 | ||
png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON); | ||
#endif | ||
|
||
// Setting up reading from buffer. | ||
png_handler.buf_state = new BufState(); | ||
png_handler.buf_state->data = data + kPngHeaderSize; | ||
png_handler.buf_state->bytes_left = size - kPngHeaderSize; | ||
png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data); | ||
png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize); | ||
|
||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) { | ||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
// Reading. | ||
png_read_info(png_handler.png_ptr, png_handler.info_ptr); | ||
|
||
// reset error handler to put png_deleter into scope. | ||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) { | ||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
png_uint_32 width, height; | ||
int bit_depth, color_type, interlace_type, compression_type; | ||
int filter_type; | ||
|
||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height, | ||
&bit_depth, &color_type, &interlace_type, &compression_type, | ||
&filter_type)) { | ||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
// This is going to be too slow. | ||
if (width && height > 100000000 / width) { | ||
PNG_CLEANUP | ||
#ifdef HAS_DUMMY_CRASH | ||
#ifdef __aarch64__ | ||
asm volatile(".word 0xf7f0a000\n"); | ||
#else | ||
asm("ud2"); | ||
#endif | ||
#endif | ||
return 0; | ||
} | ||
|
||
// Set several transforms that browsers typically use: | ||
png_set_gray_to_rgb(png_handler.png_ptr); | ||
png_set_expand(png_handler.png_ptr); | ||
png_set_packing(png_handler.png_ptr); | ||
png_set_scale_16(png_handler.png_ptr); | ||
png_set_tRNS_to_alpha(png_handler.png_ptr); | ||
|
||
int passes = png_set_interlace_handling(png_handler.png_ptr); | ||
|
||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr); | ||
|
||
png_handler.row_ptr = | ||
png_malloc(png_handler.png_ptr, | ||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr)); | ||
|
||
for (int pass = 0; pass < passes; ++pass) { | ||
for (png_uint_32 y = 0; y < height; ++y) { | ||
png_read_row(png_handler.png_ptr, | ||
static_cast<png_bytep>(png_handler.row_ptr), nullptr); | ||
} | ||
} | ||
|
||
png_read_end(png_handler.png_ptr, png_handler.end_info_ptr); | ||
|
||
PNG_CLEANUP | ||
return 0; | ||
} | ||
|
||
int main() { | ||
uint8_t buf[10] = {0}; | ||
LLVMFuzzerTestOneInput(buf, 10); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could probably try to patch build.rs of libafl_qemu to figure this binary out by itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that hardcoding the CROSS_CC is not a good idea. The problem is that this fuzzer needs a CROSS_CC to function. Figuring out which cross_cc is installed is hard and also systems might have multiple cross_cc installed.
Especially for the github workflows it needs to be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the scope of this PR it's more than fine, I was thinking in general
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, that would be great. I also thought about it, but there are just so many cross_cc. Already for arm on ubuntu using apt you might have arm-none-eabi-gcc, arm-linux-gnueabi-gcc and arm-linux-gnueabihf-gcc installed. Not even speaking about other targets then arm32 or manually installed cross_cc. I think it is impossible to pick the correct one for the user or do you have any idea on how to?