From 264513d0a39dfed852ed6ffb94311dbb9d75d3b4 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 17 Aug 2024 19:54:08 +0200 Subject: [PATCH] Quick & dirty K_USER_SHARED_DATA mapping --- src/emulator/main.cpp | 143 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 25 deletions(-) diff --git a/src/emulator/main.cpp b/src/emulator/main.cpp index 99ec129e..ef409681 100644 --- a/src/emulator/main.cpp +++ b/src/emulator/main.cpp @@ -11,6 +11,8 @@ #define STACK_ADDRESS 0x7ffffffde000 #define STACK_SIZE 0x40000 +#define KUSD_ADDRESS 0x7ffe0000 + #include "unicorn.hpp" namespace @@ -25,6 +27,81 @@ namespace return align_down(value + (alignment - 1), alignment); } + template + class unicorn_object + { + public: + unicorn_object() = default; + + unicorn_object(const unicorn& uc, uint64_t address) + : uc_(&uc) + , address_(address) + { + } + + uint64_t value() const + { + return this->address_; + } + + T* ptr() const + { + return reinterpret_cast(this->address_); + } + + template + void access(const F& accessor) const + { + T obj{}; + + e(uc_mem_read(*this->uc_, this->address_, &obj, sizeof(obj))); + + accessor(obj); + + e(uc_mem_write(*this->uc_, this->address_, &obj, sizeof(obj))); + } + + private: + const unicorn* uc_{}; + uint64_t address_{}; + }; + + class unicorn_allocator + { + public: + unicorn_allocator(const unicorn& uc, const uint64_t address, const uint64_t size) + : uc_(&uc) + , address_(address) + , size_(size) + , active_address_(address) + { + } + + template + unicorn_object reserve() + { + const auto alignment = alignof(T); + const auto potential_start = align_up(this->active_address_, alignment); + const auto potential_end = potential_start + sizeof(T); + const auto total_end = this->address_ + this->size_; + + if (potential_end > total_end) + { + throw std::runtime_error("Out of memory"); + } + + this->active_address_ = potential_end; + + return unicorn_object(*this->uc_, potential_start); + } + + private: + const unicorn* uc_{}; + const uint64_t address_{}; + const uint64_t size_{}; + uint64_t active_address_{0}; + }; + 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)); @@ -33,7 +110,7 @@ namespace e(uc_reg_write(uc, UC_X86_REG_RSP, &stack_end)); } - void setup_gs_segment(const unicorn& uc, const uint64_t segment_base, const size_t size) + unicorn_allocator setup_gs_segment(const unicorn& uc, const uint64_t segment_base, const uint64_t size) { const std::array value = { IA32_GS_BASE_MSR, @@ -42,40 +119,56 @@ namespace e(uc_reg_write(uc, UC_X86_REG_MSR, value.data())); e(uc_mem_map(uc, segment_base, size, UC_PROT_READ | UC_PROT_WRITE)); + + return {uc, segment_base, size}; + } + + void setup_kusd(const unicorn& uc) + { + /* TODO: Fix + uc_mem_map(uc, KUSD_ADDRESS, sizeof(KUSER_SHARED_DATA), UC_PROT_READ); + + unicorn_object kusd_object{uc, KUSD_ADDRESS}; + */ + + uc_mem_map_ptr(uc, KUSD_ADDRESS, sizeof(KUSER_SHARED_DATA), UC_PROT_READ, + reinterpret_cast(KUSD_ADDRESS)); } void setup_teb_and_peb(const unicorn& uc) { setup_stack(uc, STACK_ADDRESS, STACK_SIZE); - setup_gs_segment(uc, GS_SEGMENT_ADDR, GS_SEGMENT_SIZE); + auto gs = setup_gs_segment(uc, GS_SEGMENT_ADDR, GS_SEGMENT_SIZE); - constexpr auto teb_address = GS_SEGMENT_ADDR; - const auto peb_address = align_up(teb_address + sizeof(TEB), 0x10); - const auto ldr_address = align_up(peb_address + sizeof(PEB_LDR_DATA), 0x10); + const auto teb_object = gs.reserve(); + const auto peb_object = gs.reserve(); + const auto ldr_object = gs.reserve(); - TEB teb{}; - teb.NtTib.StackLimit = reinterpret_cast(STACK_ADDRESS); - teb.NtTib.StackBase = reinterpret_cast((STACK_ADDRESS + STACK_SIZE)); - teb.NtTib.Self = reinterpret_cast(teb_address); - teb.ProcessEnvironmentBlock = reinterpret_cast(peb_address); + teb_object.access([&](TEB& teb) + { + teb.NtTib.StackLimit = reinterpret_cast(STACK_ADDRESS); + teb.NtTib.StackBase = reinterpret_cast((STACK_ADDRESS + STACK_SIZE)); + teb.NtTib.Self = &teb_object.ptr()->NtTib; + teb.ProcessEnvironmentBlock = peb_object.ptr(); + }); - PEB peb{}; - peb.ImageBaseAddress = nullptr; - peb.Ldr = reinterpret_cast(ldr_address); + peb_object.access([&](PEB& peb) + { + peb.ImageBaseAddress = nullptr; + peb.Ldr = ldr_object.ptr(); + }); - PEB_LDR_DATA ldr{}; - ldr.InLoadOrderModuleList.Flink = reinterpret_cast(ldr_address + offsetof(PEB_LDR_DATA, InLoadOrderModuleList)); - ldr.InLoadOrderModuleList.Blink = ldr.InLoadOrderModuleList.Flink; + ldr_object.access([&](PEB_LDR_DATA& ldr) + { + ldr.InLoadOrderModuleList.Flink = &ldr_object.ptr()->InLoadOrderModuleList; + ldr.InLoadOrderModuleList.Blink = ldr.InLoadOrderModuleList.Flink; - ldr.InMemoryOrderModuleList.Flink = reinterpret_cast(ldr_address + offsetof(PEB_LDR_DATA, InMemoryOrderModuleList)); - ldr.InMemoryOrderModuleList.Blink = ldr.InMemoryOrderModuleList.Flink; + ldr.InMemoryOrderModuleList.Flink = &ldr_object.ptr()->InMemoryOrderModuleList; + ldr.InMemoryOrderModuleList.Blink = ldr.InMemoryOrderModuleList.Flink; - ldr.InInitializationOrderModuleList.Flink = reinterpret_cast(ldr_address + offsetof(PEB_LDR_DATA, InInitializationOrderModuleList)); - ldr.InInitializationOrderModuleList.Blink = ldr.InInitializationOrderModuleList.Flink; - - e(uc_mem_write(uc, teb_address, &teb, sizeof(teb))); - e(uc_mem_write(uc, peb_address, &peb, sizeof(peb))); - e(uc_mem_write(uc, ldr_address, &ldr, sizeof(ldr))); + ldr.InInitializationOrderModuleList.Flink = &ldr_object.ptr()->InInitializationOrderModuleList; + ldr.InInitializationOrderModuleList.Blink = ldr.InInitializationOrderModuleList.Flink; + }); } void run() @@ -85,7 +178,7 @@ namespace e(uc_mem_map(uc, ADDRESS, 0x1000, UC_PROT_ALL)); e(uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)); - + setup_kusd(uc); setup_teb_and_peb(uc); e(uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0));