Skip to content

Commit

Permalink
Prepare fuzzing engine
Browse files Browse the repository at this point in the history
  • Loading branch information
momo5502 committed Sep 24, 2024
1 parent f5b5703 commit 10b09b8
Show file tree
Hide file tree
Showing 45 changed files with 587 additions and 90 deletions.
5 changes: 3 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_subdirectory(common)
add_subdirectory(emulator)
add_subdirectory(unicorn_emulator)
add_subdirectory(windows_emulator)
add_subdirectory(unicorn-emulator)
add_subdirectory(windows-emulator)
add_subdirectory(sample)
add_subdirectory(fuzzing-engine)
add_subdirectory(fuzzer)
4 changes: 2 additions & 2 deletions src/emulator/emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ class emulator : public memory_manager

void perform_serialization(utils::buffer_serializer& buffer, const bool is_snapshot) const
{
this->serialize_memory_state(buffer, is_snapshot);
this->serialize_state(buffer, is_snapshot);
this->serialize_memory_state(buffer, is_snapshot);
}

void perform_deserialization(utils::buffer_deserializer& buffer, const bool is_snapshot)
{
this->deserialize_memory_state(buffer, is_snapshot);
this->deserialize_state(buffer, is_snapshot);
this->deserialize_memory_state(buffer, is_snapshot);
}

virtual void serialize_state(utils::buffer_serializer& buffer, bool is_snapshot) const = 0;
Expand Down
11 changes: 11 additions & 0 deletions src/emulator/memory_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ void memory_manager::serialize_memory_state(utils::buffer_serializer& buffer, co

void memory_manager::deserialize_memory_state(utils::buffer_deserializer& buffer, const bool is_snapshot)
{
if (!is_snapshot)
{
for (const auto& reserved_region : this->reserved_regions_)
{
for (const auto& region : reserved_region.second.committed_regions)
{
this->unmap_memory(region.first, region.second.length);
}
}
}

buffer.read_map(this->reserved_regions_);

if (is_snapshot)
Expand Down
3 changes: 2 additions & 1 deletion src/fuzzer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ target_precompile_headers(fuzzer PRIVATE std_include.hpp)

target_link_libraries(fuzzer PRIVATE
common
windows_emulator
fuzzing-engine
windows-emulator
)

momo_strip_target(fuzzer)
137 changes: 100 additions & 37 deletions src/fuzzer/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "std_include.hpp"

#include <windows_emulator.hpp>
#include <debugging/x64_gdb_stub_handler.hpp>
#include <fuzzer.hpp>

#include "utils/finally.hpp"

bool use_gdb = false;

Expand All @@ -11,70 +13,131 @@ namespace
{
try
{
win_emu.logger.disable_output(true);
win_emu.emu().start_from_ip();
}
catch (...)
{
win_emu.logger.disable_output(false);
win_emu.logger.print(color::red, "Emulation failed at: 0x%llX\n", win_emu.emu().read_instruction_pointer());
throw;
}

win_emu.logger.disable_output(false);
win_emu.logger.print(color::red, "Emulation terminated!\n");
}

void run(const std::string_view application)
void forward_emulator(windows_emulator& win_emu)
{
windows_emulator win_emu{
application, {}
};
win_emu.emu().hook_memory_execution(0x140001000, 1, [&](uint64_t, size_t, uint64_t)
{
win_emu.emu().stop();
});

//watch_system_objects(win_emu);
win_emu.buffer_stdout = true;
//win_emu.verbose_calls = true;
run_emulation(win_emu);
}

const auto& exe = *win_emu.process().executable;
std::vector<std::unique_ptr<windows_emulator>> prepare_emulators(const size_t count,
const windows_emulator& base_emulator)
{
std::vector<std::unique_ptr<windows_emulator>> emulators{};

const auto text_start = exe.image_base + 0x1000;
const auto text_end = exe.image_base + 0x52000;
constexpr auto scan_size = 0x100;
utils::buffer_serializer serializer{};
base_emulator.serialize(serializer);

win_emu.emu().hook_memory_read(text_start, scan_size, [&](const uint64_t address, size_t, uint64_t)
for (size_t i = 0; i < count; ++i)
{
const auto rip = win_emu.emu().read_instruction_pointer();
if (rip >= text_start && rip < text_end)
{
win_emu.logger.print(color::green, "Reading from executable .text: 0x%llX at 0x%llX\n", address, rip);
}
});
auto emu = std::make_unique<windows_emulator>();
utils::buffer_deserializer deserializer{serializer.get_buffer()};

emu->deserialize(deserializer);
//emu->save_snapshot();

/*win_emu.add_syscall_hook([&]
emulators.push_back(std::move(emu));
}

return emulators;
}

struct my_fuzzer_handler : fuzzer::fuzzing_handler
{
const std::vector<std::unique_ptr<windows_emulator>>* emulators{};
std::atomic_size_t active_emu{0};
std::atomic_bool stop_fuzzing{false};

fuzzer::execution_result execute(std::span<const uint8_t> data,
const std::function<fuzzer::coverage_functor>& coverage_handler) override
{
const auto syscall_id = win_emu.emu().reg(x64_register::eax);
const auto syscall_name = win_emu.dispatcher().get_syscall_name(syscall_id);
puts("Running...");
const auto emu_index = ++active_emu;
auto& emu = *emulators->at(emu_index % emulators->size());

if (syscall_name != "NtQueryInformationProcess")
utils::buffer_serializer serializer{};
emu.serialize(serializer);

const auto _ = utils::finally([&]
{
return instruction_hook_continuation::run_instruction;
}
utils::buffer_deserializer deserializer{serializer.get_buffer()};
emu.deserialize(deserializer);
});

const auto info_class = win_emu.emu().reg(x64_register::rdx);
if (info_class != ProcessImageFileNameWin32)
//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([&]
{
return instruction_hook_continuation::run_instruction;
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());

emu.emu().reg(x64_register::rcx, memory);
emu.emu().reg<uint64_t>(x64_register::rdx, data.size());

try
{
run_emulation(emu);
return fuzzer::execution_result::success;
}
catch (...)
{
stop_fuzzing = true;
return fuzzer::execution_result::error;
}
}

bool stop() override
{
return stop_fuzzing;
}
};

win_emu.logger.print(color::pink, "Patching NtQueryInformationProcess...\n");
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 data = win_emu.emu().reg(x64_register::r8);
my_fuzzer_handler handler{};
handler.emulators = &emulators;

emulator_allocator data_allocator{win_emu.emu(), data, 0x100};
data_allocator.make_unicode_string(
L"C:\\Users\\mauri\\source\\repos\\lul\\x64\\Release\\lul.exe");
win_emu.emu().reg(x64_register::rax, STATUS_SUCCESS);
return instruction_hook_continuation::skip_instruction;
});*/
fuzzer::run(handler, concurrency);
}

run_emulation(win_emu);
void run(const std::string_view application)
{
windows_emulator win_emu{
application, {}
};

forward_emulator(win_emu);
run_fuzzer(win_emu);
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/fuzzing-engine/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
*.cpp
*.hpp
*.rc
)

list(SORT SRC_FILES)

add_library(fuzzing-engine ${SRC_FILES})

momo_assign_source_group(${SRC_FILES})

target_link_libraries(fuzzing-engine PRIVATE
common
)

target_include_directories(fuzzing-engine INTERFACE
"${CMAKE_CURRENT_LIST_DIR}"
)

momo_strip_target(fuzzing-engine)
114 changes: 114 additions & 0 deletions src/fuzzing-engine/fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "fuzzer.hpp"
#include "input_generator.hpp"

namespace fuzzer
{
namespace
{
class fuzzing_context
{
public:
fuzzing_context(input_generator& generator, fuzzing_handler& handler)
: generator(generator)
, handler(handler)
{
}

void stop()
{
this->stop_ = true;
}

bool should_stop()
{
if (this->stop_)
{
return true;
}

if (!handler.stop())
{
return false;
}

this->stop_ = true;
return true;
}

input_generator& generator;
fuzzing_handler& handler;

private:
std::atomic_bool stop_{false};
};

void perform_fuzzing_iteration(const fuzzing_context& context)
{
context.generator.access_input([&](const std::span<const uint8_t> input)
{
uint64_t score{0};
context.handler.execute(input, [&](uint64_t)
{
++score;
});

return score;
});
}

void worker(fuzzing_context& context)
{
while (!context.should_stop())
{
perform_fuzzing_iteration(context);
}
}

struct worker_pool
{
fuzzing_context* context_{nullptr};
std::vector<std::thread> workers_{};

worker_pool(fuzzing_context& context, const size_t concurrency)
: context_(&context)
{
this->workers_.reserve(concurrency);

for (size_t i = 0; i < concurrency; ++i)
{
this->workers_.emplace_back([&context]
{
worker(context);
});
}
}

~worker_pool()
{
if (this->workers_.empty())
{
return;
}

this->context_->stop();

for (auto& w : this->workers_)
{
w.join();
}
}
};
}

void run(fuzzing_handler& handler, const size_t concurrency)
{
input_generator generator{};
fuzzing_context context{generator, handler};
worker_pool pool{context, concurrency};

while (!context.should_stop())
{
std::this_thread::sleep_for(std::chrono::seconds{1});
}
}
}
Loading

0 comments on commit 10b09b8

Please sign in to comment.