aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalder Kitagawa <ckitagawa@google.com>2018-04-06 19:31:25 +0000
committerEdward Lesmes <ehmaldonado@google.com>2021-07-23 22:03:49 +0000
commit97b68bff47e939b997bdf9364794591efa77ea8f (patch)
tree429a4a289b20d739cb86f85d9d0d1d674a3d2f2f
parent9e74a61b87dd26ed0f39c41399aedcff279c3f85 (diff)
downloadzucchini-97b68bff47e939b997bdf9364794591efa77ea8f.tar.gz
[Zucchini] Add Win32 PE Disassembler Fuzzer
Fuzzes both the x86 and x64 versions of disassembler_win32.h including reading the reference types: - Reloc - Abs32 - Rel32 The fuzzer runs at ~3000 exec/s which is acceptable based on the fuzzing guide. More details: https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/efficient_fuzzer.md#Seed-Corpus Interesting results should appear here: https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/clusterfuzz.md#Status-Links The seed corpus consists of x64 and x86 libegl which is the smallest binary file in the Windows release of Chrome. Since memory usage and runtime increase significantly with seed size choosing small binaries is key. The sha1 sums are listed and these are uploaded to: https://pantheon.corp.google.com/storage/browser/clusterfuzz-corpus/libfuzzer This achives ~81% line coverage of all associated files within 1 500 000 runs with no single test exceeding 5 seconds. The bulk of the uncovered code is the reference writers which are not part of disassembly. A follow-up improvement would be to validate that the references are within the correct region of the file (or at least within the file) although I'm unclear this is necessary for relocs or calls to dlls. Change-Id: I4682f90c3c037cb7d87d21d7c351817e6158f59f Reviewed-on: https://chromium-review.googlesource.com/996520 Commit-Queue: Calder Kitagawa <ckitagawa@google.com> Reviewed-by: Samuel Huang <huangs@chromium.org> Reviewed-by: Max Moroz <mmoroz@chromium.org> Cr-Commit-Position: refs/heads/master@{#548901} NOKEYCHECK=True GitOrigin-RevId: a3d605e38f9387bbab6c4b30ab35926e6da0ace4
-rw-r--r--BUILD.gn14
-rw-r--r--disassembler_win32_fuzzer.cc64
2 files changed, 78 insertions, 0 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 37a548d..758ba2b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -122,6 +122,20 @@ if (is_win) {
}
}
+# To download the corpus for local fuzzing use:
+# gsutil -m rsync \
+# gs://clusterfuzz-corpus/libfuzzer/zucchini_disassembler_win32_fuzzer \
+# components/zucchini/testdata/disassembler_win32_fuzzer
+fuzzer_test("zucchini_disassembler_win32_fuzzer") {
+ sources = [
+ "disassembler_win32_fuzzer.cc",
+ ]
+ deps = [
+ ":zucchini_lib",
+ "//base",
+ ]
+}
+
fuzzer_test("zucchini_patch_fuzzer") {
sources = [
"patch_fuzzer.cc",
diff --git a/disassembler_win32_fuzzer.cc b/disassembler_win32_fuzzer.cc
new file mode 100644
index 0000000..dbbd0e8
--- /dev/null
+++ b/disassembler_win32_fuzzer.cc
@@ -0,0 +1,64 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/logging.h"
+#include "components/zucchini/buffer_view.h"
+#include "components/zucchini/disassembler.h"
+#include "components/zucchini/disassembler_win32.h"
+
+struct Environment {
+ Environment() {
+ logging::SetMinLogLevel(3); // Disable console spamming.
+ }
+};
+
+Environment* env = new Environment();
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Prep data.
+ zucchini::ConstBufferView image(data, size);
+
+ // One of x86 or x64 should return a non-nullptr if the data is valid.
+
+ // Output will be a pointer to zucchini::DisassemblerWin32X86 if successful
+ // or nullptr otherwise.
+ auto disassembler_win32x86 =
+ zucchini::Disassembler::Make<zucchini::DisassemblerWin32X86>(image);
+ if (disassembler_win32x86 != nullptr) {
+ // Parse the Win32 PE file and ensure nothing bad occurs.
+ // TODO(ckitagawa): Actually validate that the output reference is within
+ // the image.
+ auto relocx86 = disassembler_win32x86->MakeReadRelocs(0, image.size());
+ while (relocx86->GetNext().has_value()) {
+ }
+ auto abs32x86 = disassembler_win32x86->MakeReadAbs32(0, image.size());
+ while (abs32x86->GetNext().has_value()) {
+ }
+ auto rel32x86 = disassembler_win32x86->MakeReadRel32(0, image.size());
+ while (rel32x86->GetNext().has_value()) {
+ }
+ }
+
+ // Output will be a pointer to zucchini::DisassemblerWin32X64 if successful
+ // or nullptr otherwise.
+ auto disassembler_win32x64 =
+ zucchini::Disassembler::Make<zucchini::DisassemblerWin32X64>(image);
+ if (disassembler_win32x64 != nullptr) {
+ // Parse the Win32 PE file and ensure nothing bad occurs.
+ auto relocx64 = disassembler_win32x64->MakeReadRelocs(0, image.size());
+ while (relocx64->GetNext().has_value()) {
+ }
+ auto abs32x64 = disassembler_win32x64->MakeReadAbs32(0, image.size());
+ while (abs32x64->GetNext().has_value()) {
+ }
+ auto rel32x64 = disassembler_win32x64->MakeReadRel32(0, image.size());
+ while (rel32x64->GetNext().has_value()) {
+ }
+ }
+ return 0;
+}