diff --git a/src/fuzzer/main.cpp b/src/fuzzer/main.cpp index bceb7ec..8fa3ee2 100644 --- a/src/fuzzer/main.cpp +++ b/src/fuzzer/main.cpp @@ -24,7 +24,6 @@ namespace } win_emu.logger.disable_output(false); - win_emu.logger.print(color::red, "Emulation terminated!\n"); } void forward_emulator(windows_emulator& win_emu) @@ -37,40 +36,33 @@ namespace run_emulation(win_emu); } - std::vector> prepare_emulators(const size_t count, - const windows_emulator& base_emulator) + struct fuzzer_executer : fuzzer::executer { - std::vector> emulators{}; + windows_emulator emu{}; + const std::function* handler{nullptr}; - utils::buffer_serializer serializer{}; - base_emulator.serialize(serializer); - for (size_t i = 0; i < count; ++i) + fuzzer_executer(std::span data) { - auto emu = std::make_unique(); - utils::buffer_deserializer deserializer{serializer.get_buffer()}; + utils::buffer_deserializer deserializer{data}; + emu.deserialize(deserializer); + //emu.save_snapshot(); - emu->deserialize(deserializer); - //emu->save_snapshot(); - - emulators.push_back(std::move(emu)); + emu.emu().hook_edge_generation([&](const basic_block& current_block, + const basic_block&) + { + if (this->handler) + { + (*this->handler)(current_block.address); + } + }); } - return emulators; - } - - struct my_fuzzer_handler : fuzzer::fuzzing_handler - { - const std::vector>* emulators{}; - std::atomic_size_t active_emu{0}; - std::atomic_bool stop_fuzzing{false}; - fuzzer::execution_result execute(std::span data, const std::function& coverage_handler) override { - puts("Running..."); - const auto emu_index = ++active_emu; - auto& emu = *emulators->at(emu_index % emulators->size()); + printf("Input size: %zd\n", data.size()); + this->handler = &coverage_handler; utils::buffer_serializer serializer{}; emu.serialize(serializer); @@ -83,17 +75,6 @@ namespace //emu.restore_snapshot(); - auto* h = emu.emu().hook_edge_generation([&](const basic_block& current_block, - const basic_block&) - { - coverage_handler(current_block.address); - }); - - const auto __ = utils::finally([&] - { - emu.emu().delete_hook(h); - }); - const auto memory = emu.emu().allocate_memory(page_align_up(std::max(data.size(), 1ULL)), memory_permission::read_write); emu.emu().write_memory(memory, data.data(), data.size()); @@ -108,10 +89,25 @@ namespace } catch (...) { - stop_fuzzing = true; return fuzzer::execution_result::error; } } + }; + + struct my_fuzzer_handler : fuzzer::handler + { + std::vector emulator_state{}; + std::atomic_bool stop_fuzzing{false}; + + my_fuzzer_handler(std::vector emulator_state) + : emulator_state(std::move(emulator_state)) + { + } + + std::unique_ptr make_executer() override + { + return std::make_unique(emulator_state); + } bool stop() override { @@ -121,11 +117,12 @@ namespace void run_fuzzer(const windows_emulator& base_emulator) { - const auto concurrency = 1ULL; //std::thread::hardware_concurrency(); - const auto emulators = prepare_emulators(concurrency, base_emulator); + const auto concurrency = std::thread::hardware_concurrency(); + + utils::buffer_serializer serializer{}; + base_emulator.serialize(serializer); - my_fuzzer_handler handler{}; - handler.emulators = &emulators; + my_fuzzer_handler handler{serializer.move_buffer()}; fuzzer::run(handler, concurrency); } diff --git a/src/fuzzing-engine/fuzzer.cpp b/src/fuzzing-engine/fuzzer.cpp index 4e7ea77..190f0e8 100644 --- a/src/fuzzing-engine/fuzzer.cpp +++ b/src/fuzzing-engine/fuzzer.cpp @@ -8,7 +8,7 @@ namespace fuzzer class fuzzing_context { public: - fuzzing_context(input_generator& generator, fuzzing_handler& handler) + fuzzing_context(input_generator& generator, handler& handler) : generator(generator) , handler(handler) { @@ -36,31 +36,38 @@ namespace fuzzer } input_generator& generator; - fuzzing_handler& handler; + handler& handler; private: std::atomic_bool stop_{false}; }; - void perform_fuzzing_iteration(const fuzzing_context& context) + void perform_fuzzing_iteration(const fuzzing_context& context, executer& executer) { context.generator.access_input([&](const std::span input) { uint64_t score{0}; - context.handler.execute(input, [&](uint64_t) + const auto result = executer.execute(input, [&](uint64_t) { ++score; }); + if(result == execution_result::error) + { + printf("Found error!"); + } + return score; }); } void worker(fuzzing_context& context) { + const auto executer = context.handler.make_executer(); + while (!context.should_stop()) { - perform_fuzzing_iteration(context); + perform_fuzzing_iteration(context, *executer); } } @@ -100,7 +107,7 @@ namespace fuzzer }; } - void run(fuzzing_handler& handler, const size_t concurrency) + void run(handler& handler, const size_t concurrency) { input_generator generator{}; fuzzing_context context{generator, handler}; diff --git a/src/fuzzing-engine/fuzzer.hpp b/src/fuzzing-engine/fuzzer.hpp index 1c15bf0..bebfb4f 100644 --- a/src/fuzzing-engine/fuzzer.hpp +++ b/src/fuzzing-engine/fuzzer.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -14,12 +15,19 @@ namespace fuzzer error, }; - struct fuzzing_handler + struct executer { - virtual ~fuzzing_handler() = default; + virtual ~executer() = default; virtual execution_result execute(std::span data, - const std::function& coverage_handler) = 0; + const std::function& coverage_handler) = 0; + }; + + struct handler + { + virtual ~handler() = default; + + virtual std::unique_ptr make_executer() = 0; virtual bool stop() { @@ -27,5 +35,5 @@ namespace fuzzer } }; - void run(fuzzing_handler& handler, size_t concurrency = std::thread::hardware_concurrency()); + void run(handler& handler, size_t concurrency = std::thread::hardware_concurrency()); } diff --git a/src/fuzzing-engine/input_generator.cpp b/src/fuzzing-engine/input_generator.cpp index 4d63460..28cc0e6 100644 --- a/src/fuzzing-engine/input_generator.cpp +++ b/src/fuzzing-engine/input_generator.cpp @@ -8,7 +8,7 @@ namespace fuzzer void mutate_input(random_generator& rng, std::vector& input) { - if (input.empty() || rng.get(10) == 0) + if (input.empty() || rng.get(3) == 0) { const auto new_bytes = rng.get_geometric() + 1; input.resize(input.size() + new_bytes); diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index 6043716..728cfa2 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -1,6 +1,7 @@ #include "../std_include.hpp" #include "module_manager.hpp" #include "module_mapping.hpp" +#include "windows-emulator/logger.hpp" static void serialize(utils::buffer_serializer& buffer, const exported_symbol& sym) { @@ -49,7 +50,7 @@ module_manager::module_manager(emulator& emu) { } -mapped_module* module_manager::map_module(const std::filesystem::path& file) +mapped_module* module_manager::map_module(const std::filesystem::path& file, logger& logger) { for (auto& mod : this->modules_) { @@ -62,11 +63,11 @@ mapped_module* module_manager::map_module(const std::filesystem::path& file) auto mod = map_module_from_file(*this->emu_, file); if (!mod) { - printf("Failed to map %s\n", file.generic_string().c_str()); + logger.error("Failed to map %s\n", file.generic_string().c_str()); return nullptr; } - printf("Mapped %s at 0x%llX\n", mod->path.generic_string().c_str(), mod->image_base); + logger.log("Mapped %s at 0x%llX\n", mod->path.generic_string().c_str(), mod->image_base); const auto image_base = mod->image_base; const auto entry = this->modules_.try_emplace(image_base, std::move(*mod)); diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index ea1854a..361890e 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -2,12 +2,14 @@ #include "mapped_module.hpp" #include +class logger; + class module_manager { public: module_manager(emulator& emu); - mapped_module* map_module(const std::filesystem::path& file); + mapped_module* map_module(const std::filesystem::path& file, logger& logger); mapped_module* find_by_address(const uint64_t address) { diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index d0fdb09..16e4a2f 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -434,7 +434,7 @@ namespace const auto attributes = object_attributes.read(); auto filename = read_unicode_string(c.emu, attributes.ObjectName); - printf("Opening section: %S\n", filename.c_str()); + c.win_emu.logger.print(color::gray, "Opening section: %S\n", filename.c_str()); if (filename == L"\\Windows\\SharedSection") { @@ -536,7 +536,7 @@ namespace return STATUS_INVALID_HANDLE; } - const auto binary = c.proc.module_manager.map_module(section_entry->name); + const auto binary = c.proc.module_manager.map_module(section_entry->name, c.win_emu.logger); if (!binary) { return STATUS_FILE_INVALID; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 3a12ac9..2f8773e 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -493,15 +493,15 @@ void windows_emulator::setup_process(const std::filesystem::path& application, setup_context(context, emu, application, arguments); - context.executable = context.module_manager.map_module(application); + context.executable = context.module_manager.map_module(application, this->logger); context.peb.access([&](PEB& peb) { peb.ImageBaseAddress = reinterpret_cast(context.executable->image_base); }); - context.ntdll = context.module_manager.map_module(R"(C:\Windows\System32\ntdll.dll)"); - context.win32u = context.module_manager.map_module(R"(C:\Windows\System32\win32u.dll)"); + context.ntdll = context.module_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->logger); + context.win32u = context.module_manager.map_module(R"(C:\Windows\System32\win32u.dll)", this->logger); this->dispatcher_.setup(context.ntdll->exports, context.win32u->exports);