From 6a2b423e5bae106cea8c155481439f2ce4ba5c32 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 18 Aug 2024 11:15:01 +0200 Subject: [PATCH] Some progress --- src/emulator/main.cpp | 112 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 10 deletions(-) diff --git a/src/emulator/main.cpp b/src/emulator/main.cpp index b673f81c..c27ca250 100644 --- a/src/emulator/main.cpp +++ b/src/emulator/main.cpp @@ -24,6 +24,11 @@ namespace return align_down(value + (alignment - 1), alignment); } + uint64_t page_align_up(const uint64_t value) + { + return align_up(value, 0x1000); + } + template class unicorn_object { @@ -99,6 +104,70 @@ namespace uint64_t active_address_{0}; }; + class unicorn_hook + { + public: + using function = std::function; + + unicorn_hook(const unicorn& uc, const int type, const uint64_t begin, const uint64_t end, function callback) + : uc_(&uc) + , function_(std::make_unique(std::move(callback))) + { + auto* handler = +[](uc_engine*, const uint64_t address, const uint32_t size, + void* user_data) + { + (*static_cast(user_data))(address, size); + }; + + e(uc_hook_add(*this->uc_, &this->hook_, type, handler, this->function_.get(), begin, end)); + } + + unicorn_hook(const unicorn_hook&) = delete; + unicorn_hook& operator=(const unicorn_hook&) = delete; + + unicorn_hook(unicorn_hook&& obj) noexcept + { + this->operator=(std::move(obj)); + } + + unicorn_hook& operator=(unicorn_hook&& obj) noexcept + { + if (this != &obj) + { + this->remove(); + + this->uc_ = obj.uc_; + this->hook_ = obj.hook_; + this->function_ = std::move(obj.function_); + + obj.hook_ = {}; + } + + return *this; + } + + ~unicorn_hook() + { + this->remove(); + } + + void remove() + { + if (this->hook_) + { + uc_hook_del(*this->uc_, this->hook_); + this->hook_ = {}; + } + + this->function_ = {}; + } + + private: + const unicorn* uc_{}; + uc_hook hook_{}; + std::unique_ptr function_{}; + }; + void setup_stack(const unicorn& uc, uint64_t stack_base, size_t stack_size) { e(uc_mem_map(uc, stack_base, stack_size, UC_PROT_READ | UC_PROT_WRITE)); @@ -122,17 +191,26 @@ namespace void setup_kusd(const unicorn& uc) { - /* TODO: Fix - uc_mem_map(uc, KUSD_ADDRESS, sizeof(KUSER_SHARED_DATA), UC_PROT_READ); + e(uc_mem_map(uc, KUSD_ADDRESS, page_align_up(sizeof(KUSER_SHARED_DATA)), UC_PROT_READ)); - unicorn_object kusd_object{uc, KUSD_ADDRESS}; - */ + const unicorn_object kusd_object{uc, KUSD_ADDRESS}; + kusd_object.access([](KUSER_SHARED_DATA& kusd) + { + const auto& real_kusd = *reinterpret_cast(KUSD_ADDRESS); - uc_mem_map_ptr(uc, KUSD_ADDRESS, sizeof(KUSER_SHARED_DATA), UC_PROT_READ, - reinterpret_cast(KUSD_ADDRESS)); + memcpy(&kusd, &real_kusd, sizeof(kusd)); + + kusd.ImageNumberLow = IMAGE_FILE_MACHINE_I386; + kusd.ImageNumberHigh = IMAGE_FILE_MACHINE_AMD64; + + memset(&kusd.ProcessorFeatures, 0, sizeof(kusd.ProcessorFeatures)); + + // ... + }); } - std::unordered_map map_module(const unicorn& uc, const std::vector& module_data) + std::unordered_map map_module(const unicorn& uc, const std::vector& module_data, + const std::string& name) { // TODO: Range checks auto* ptr = module_data.data(); @@ -159,6 +237,8 @@ namespace } } + printf("Mapping %s at %llX\n", name.c_str(), prefered_base); + e(uc_mem_write(uc, prefered_base, ptr, optional_header.SizeOfHeaders)); const std::span sections(IMAGE_FIRST_SECTION(nt_headers), nt_headers->FileHeader.NumberOfSections); @@ -191,7 +271,7 @@ namespace permissions |= UC_PROT_WRITE; } - const auto size_of_section = align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize), 0x1000); + const auto size_of_section = page_align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize)); e(uc_mem_protect(uc, target_ptr, size_of_section, permissions)); } @@ -271,7 +351,7 @@ namespace std::unordered_map map_file(const unicorn& uc, const std::filesystem::path& file) { const auto data = load_file(file); - return map_module(uc, data); + return map_module(uc, data, file.generic_string()); } void run() @@ -291,7 +371,19 @@ namespace (void)entry1; (void)entry2; - //e(uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0)); + unicorn_hook hook(uc, UC_HOOK_INTR, 0, 0, [](const uint64_t address, const uint32_t /*size*/) + { + printf("Syscall: %llX\n", address); + }); + + const auto err = uc_emu_start(uc, entry1, 0, 0, 0); + if (err != UC_ERR_OK) + { + uint64_t rip{}; + uc_reg_read(uc, UC_X86_REG_RIP, &rip); + printf("Emulation failed at: %llX\n", rip); + e(err); + } printf("Emulation done. Below is the CPU context\n");