diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ba19fff..cfa8c13e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") ########################################## -project(bird LANGUAGES C CXX) +project(emulator LANGUAGES C CXX) ########################################## diff --git a/src/emulator/CMakeLists.txt b/src/emulator/CMakeLists.txt index 9ad6a25a..8381ec23 100644 --- a/src/emulator/CMakeLists.txt +++ b/src/emulator/CMakeLists.txt @@ -6,16 +6,14 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS list(SORT SRC_FILES) -add_executable(client ${SRC_FILES}) +add_executable(emulator ${SRC_FILES}) momo_assign_source_group(${SRC_FILES}) -target_precompile_headers(client PRIVATE std_include.hpp) +target_precompile_headers(emulator PRIVATE std_include.hpp) -target_link_libraries(client PRIVATE unicorn phnt::phnt) +target_link_libraries(emulator PRIVATE unicorn phnt::phnt) -set_target_properties(client PROPERTIES OUTPUT_NAME "bird") +set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT emulator) -set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT client) - -momo_strip_target(client) +momo_strip_target(emulator) diff --git a/src/emulator/main.cpp b/src/emulator/main.cpp index b1b54096..ef25d7b8 100644 --- a/src/emulator/main.cpp +++ b/src/emulator/main.cpp @@ -1,36 +1,76 @@ #include "std_include.hpp" -#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx +#define X86_CODE32 "\x65\x48\x8B\x04\x25\x60\x00\x00\x00" // INC ecx; DEC edx #define ADDRESS 0x1000000 +#define GS_SEGMENT_ADDR 0x6000000ULL +#define GS_SEGMENT_SIZE (20 << 20) // 20 MB + +#define IA32_GS_BASE_MSR 0xC0000101 + +#define STACK_SIZE 0x40000 + #include "unicorn.hpp" namespace { + uint64_t align_down(const uint64_t value, const uint64_t alignment) + { + return value & ~(alignment - 1); + } + + uint64_t align_up(const uint64_t value, const uint64_t alignment) + { + return align_down(value + (alignment - 1), alignment); + } + + void setup_gs_segment(const unicorn& uc, const uint64_t segment_base, const size_t size) + { + const std::array value = { + IA32_GS_BASE_MSR, + segment_base + }; + + 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)); + } + + void setup_teb_and_peb(const unicorn& uc) + { + 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); + + TEB teb{}; + teb.NtTib.Self = reinterpret_cast(teb_address); + teb.ProcessEnvironmentBlock = reinterpret_cast(peb_address); + + + PEB peb{}; + + e(uc_mem_write(uc, teb_address, &teb, sizeof(teb))); + e(uc_mem_write(uc, peb_address, &peb, sizeof(peb))); + } + void run() { - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register - - printf("Emulate i386 code\n"); - - const unicorn uc{UC_ARCH_X86, UC_MODE_32}; + const unicorn uc{UC_ARCH_X86, UC_MODE_64}; e(uc_mem_map(uc, ADDRESS, 0x1000, UC_PROT_ALL)); e(uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)); - e(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); - e(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); + + setup_teb_and_peb(uc); e(uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0)); printf("Emulation done. Below is the CPU context\n"); - e(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx)); - e(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx)); + uint64_t rax{}; + e(uc_reg_read(uc, UC_X86_REG_RAX, &rax)); - printf(">>> ECX = 0x%x\n", r_ecx); - printf(">>> EDX = 0x%x\n", r_edx); + printf(">>> RAX = 0x%llX\n", rax); } }