mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-21 04:33:56 +00:00
Quick & dirty K_USER_SHARED_DATA mapping
This commit is contained in:
@@ -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 <typename T>
|
||||
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<T*>(this->address_);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
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 <typename T>
|
||||
unicorn_object<T> 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<T>(*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<uint64_t, 2> 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<KUSER_SHARED_DATA> kusd_object{uc, KUSD_ADDRESS};
|
||||
*/
|
||||
|
||||
uc_mem_map_ptr(uc, KUSD_ADDRESS, sizeof(KUSER_SHARED_DATA), UC_PROT_READ,
|
||||
reinterpret_cast<void*>(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<TEB>();
|
||||
const auto peb_object = gs.reserve<PEB>();
|
||||
const auto ldr_object = gs.reserve<PEB_LDR_DATA>();
|
||||
|
||||
TEB teb{};
|
||||
teb.NtTib.StackLimit = reinterpret_cast<void*>(STACK_ADDRESS);
|
||||
teb.NtTib.StackBase = reinterpret_cast<void*>((STACK_ADDRESS + STACK_SIZE));
|
||||
teb.NtTib.Self = reinterpret_cast<NT_TIB*>(teb_address);
|
||||
teb.ProcessEnvironmentBlock = reinterpret_cast<PEB*>(peb_address);
|
||||
teb_object.access([&](TEB& teb)
|
||||
{
|
||||
teb.NtTib.StackLimit = reinterpret_cast<void*>(STACK_ADDRESS);
|
||||
teb.NtTib.StackBase = reinterpret_cast<void*>((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<PEB_LDR_DATA*>(ldr_address);
|
||||
peb_object.access([&](PEB& peb)
|
||||
{
|
||||
peb.ImageBaseAddress = nullptr;
|
||||
peb.Ldr = ldr_object.ptr();
|
||||
});
|
||||
|
||||
PEB_LDR_DATA ldr{};
|
||||
ldr.InLoadOrderModuleList.Flink = reinterpret_cast<LIST_ENTRY*>(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<LIST_ENTRY*>(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<LIST_ENTRY*>(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));
|
||||
|
||||
Reference in New Issue
Block a user