From 7ccad76fefc1acfed3a33f5ceb53c22e43e5a996 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 18 Sep 2024 18:11:33 +0200 Subject: [PATCH] separate emulator from executable # Conflicts: # src/windows_emulator/main.cpp --- src/CMakeLists.txt | 1 + src/sample/CMakeLists.txt | 23 +++ src/sample/main.cpp | 105 +++++++++++ src/sample/object_watching.hpp | 20 ++ .../reflect_extension.hpp | 0 src/sample/reflect_type_info.hpp | 56 ++++++ src/{windows_emulator => sample}/resource.rc | 0 .../resources/icon.ico | Bin src/sample/std_include.hpp | 79 ++++++++ src/windows_emulator/CMakeLists.txt | 13 +- src/windows_emulator/main.cpp | 177 ------------------ src/windows_emulator/windows_emulator.cpp | 17 ++ src/windows_emulator/windows_emulator.hpp | 7 +- 13 files changed, 314 insertions(+), 184 deletions(-) create mode 100644 src/sample/CMakeLists.txt create mode 100644 src/sample/main.cpp create mode 100644 src/sample/object_watching.hpp rename src/{windows_emulator => sample}/reflect_extension.hpp (100%) create mode 100644 src/sample/reflect_type_info.hpp rename src/{windows_emulator => sample}/resource.rc (100%) rename src/{windows_emulator => sample}/resources/icon.ico (100%) create mode 100644 src/sample/std_include.hpp delete mode 100644 src/windows_emulator/main.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c57578e0..1fb2c0a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(common) add_subdirectory(emulator) add_subdirectory(unicorn_emulator) add_subdirectory(windows_emulator) +add_subdirectory(sample) diff --git a/src/sample/CMakeLists.txt b/src/sample/CMakeLists.txt new file mode 100644 index 00000000..72f9734d --- /dev/null +++ b/src/sample/CMakeLists.txt @@ -0,0 +1,23 @@ +file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS + *.cpp + *.hpp + *.rc +) + +list(SORT SRC_FILES) + +add_executable(sample ${SRC_FILES}) + +momo_assign_source_group(${SRC_FILES}) + +target_precompile_headers(sample PRIVATE std_include.hpp) + +target_link_libraries(sample PRIVATE + common + reflect + windows_emulator +) + +set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT sample) + +momo_strip_target(sample) diff --git a/src/sample/main.cpp b/src/sample/main.cpp new file mode 100644 index 00000000..d4d52a25 --- /dev/null +++ b/src/sample/main.cpp @@ -0,0 +1,105 @@ +#include "std_include.hpp" + +#include +#include + +#include "object_watching.hpp" + +bool use_gdb = false; + +namespace +{ + void watch_system_objects(windows_emulator& win_emu) + { + watch_object(win_emu, win_emu.process().teb); + watch_object(win_emu, win_emu.process().peb); + watch_object(win_emu, win_emu.process().kusd); + auto* params_hook = watch_object(win_emu, win_emu.process().process_params); + + win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB, ProcessParameters), 0x8, + [&](const uint64_t address, size_t, const uint64_t value) + { + const auto target_address = win_emu.process().peb.value() + offsetof( + PEB, ProcessParameters); + + if (address == target_address) + { + const emulator_object obj{ + win_emu.emu(), value + }; + + win_emu.emu().delete_hook(params_hook); + params_hook = watch_object(win_emu, obj); + } + }); + } + + + void run() + { + windows_emulator win_emu { + R"(C:\Users\mauri\source\repos\ConsoleApplication6\x64\Release\ConsoleApplication6.exe)", + { + L"Hello", + L"World", + } + }; + + watch_system_objects(win_emu); + + try + { + if (use_gdb) + { + puts("Launching gdb stub..."); + + x64_gdb_stub_handler handler{win_emu.emu()}; + run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), "0.0.0.0:28960"); + } + else + { + win_emu.emu().start_from_ip(); + } + } + catch (...) + { + printf("Emulation failed at: %llX\n", win_emu.emu().read_instruction_pointer()); + throw; + } + + printf("Emulation done.\n"); + } +} + +int main(int /*argc*/, char** /*argv*/) +{ + //setvbuf(stdout, nullptr, _IOFBF, 0x10000); + + try + { + do + { + run(); + } + while (use_gdb); + + return 0; + } + catch (std::exception& e) + { + puts(e.what()); + +#if defined(_WIN32) && 0 + MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); +#endif + } + + return 1; +} + +#ifdef _WIN32 +int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) +{ + return main(__argc, __argv); +} +#endif diff --git a/src/sample/object_watching.hpp b/src/sample/object_watching.hpp new file mode 100644 index 00000000..db2bfac1 --- /dev/null +++ b/src/sample/object_watching.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "reflect_type_info.hpp" + +template +emulator_hook* watch_object(windows_emulator& emu, emulator_object object) +{ + const reflect_type_info info{}; + + return emu.emu().hook_memory_read(object.value(), object.size(), + [i = std::move(info), object, &emu](const uint64_t address, size_t, uint64_t) + { + const auto rip = emu.emu().read_instruction_pointer(); + + const auto offset = address - object.value(); + printf("%s: %llX (%s) at %llX (%s)\n", i.get_type_name().c_str(), offset, + i.get_member_name(offset).c_str(), rip, + emu.process().module_manager.find_name(rip)); + }); +} diff --git a/src/windows_emulator/reflect_extension.hpp b/src/sample/reflect_extension.hpp similarity index 100% rename from src/windows_emulator/reflect_extension.hpp rename to src/sample/reflect_extension.hpp diff --git a/src/sample/reflect_type_info.hpp b/src/sample/reflect_type_info.hpp new file mode 100644 index 00000000..fa943337 --- /dev/null +++ b/src/sample/reflect_type_info.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "reflect_extension.hpp" +#include + +template +class reflect_type_info +{ +public: + reflect_type_info() + { + this->type_name_ = reflect::type_name(); + + reflect::for_each([this](auto I) + { + const auto member_name = reflect::member_name(); + const auto member_offset = reflect::offset_of(); + + this->members_[member_offset] = member_name; + }); + } + + std::string get_member_name(const size_t offset) const + { + size_t last_offset{}; + std::string_view last_member{}; + + for (const auto& member : this->members_) + { + if (offset == member.first) + { + return member.second; + } + + if (offset < member.first) + { + const auto diff = offset - last_offset; + return std::string(last_member) + "+" + std::to_string(diff); + } + + last_offset = member.first; + last_member = member.second; + } + + return ""; + } + + const std::string& get_type_name() const + { + return this->type_name_; + } + +private: + std::string type_name_{}; + std::map members_{}; +}; diff --git a/src/windows_emulator/resource.rc b/src/sample/resource.rc similarity index 100% rename from src/windows_emulator/resource.rc rename to src/sample/resource.rc diff --git a/src/windows_emulator/resources/icon.ico b/src/sample/resources/icon.ico similarity index 100% rename from src/windows_emulator/resources/icon.ico rename to src/sample/resources/icon.ico diff --git a/src/sample/std_include.hpp b/src/sample/std_include.hpp new file mode 100644 index 00000000..05e56c34 --- /dev/null +++ b/src/sample/std_include.hpp @@ -0,0 +1,79 @@ +#pragma once + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 4005) +#pragma warning(disable: 4127) +#pragma warning(disable: 4201) +#pragma warning(disable: 4244) +#pragma warning(disable: 4245) +#pragma warning(disable: 4324) +#pragma warning(disable: 4458) +#pragma warning(disable: 4471) +#pragma warning(disable: 4505) +#pragma warning(disable: 4702) +#pragma warning(disable: 4996) +#pragma warning(disable: 5054) +#pragma warning(disable: 6011) +#pragma warning(disable: 6297) +#pragma warning(disable: 6385) +#pragma warning(disable: 6386) +#pragma warning(disable: 6387) +#pragma warning(disable: 26110) +#pragma warning(disable: 26451) +#pragma warning(disable: 26444) +#pragma warning(disable: 26451) +#pragma warning(disable: 26489) +#pragma warning(disable: 26495) +#pragma warning(disable: 26498) +#pragma warning(disable: 26812) +#pragma warning(disable: 28020) + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NTDDI_WIN11_GE 0 +#define PHNT_VERSION PHNT_WIN11 +#include +#include +#include + +#ifdef _WIN32 +#pragma warning(pop) +#endif + +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif +#endif + +using namespace std::literals; diff --git a/src/windows_emulator/CMakeLists.txt b/src/windows_emulator/CMakeLists.txt index 3974af95..bed2e16e 100644 --- a/src/windows_emulator/CMakeLists.txt +++ b/src/windows_emulator/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS list(SORT SRC_FILES) -add_executable(windows_emulator ${SRC_FILES}) +add_library(windows_emulator ${SRC_FILES}) momo_assign_source_group(${SRC_FILES}) @@ -14,12 +14,17 @@ target_precompile_headers(windows_emulator PRIVATE std_include.hpp) target_link_libraries(windows_emulator PRIVATE common - phnt::phnt - reflect unicorn_emulator mini-gdbstub ) -set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT windows_emulator) +target_link_libraries(windows_emulator PUBLIC + emulator + phnt::phnt +) + +target_include_directories(windows_emulator INTERFACE + "${CMAKE_CURRENT_LIST_DIR}" +) momo_strip_target(windows_emulator) diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp deleted file mode 100644 index b17b56cc..00000000 --- a/src/windows_emulator/main.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include - -#include "std_include.hpp" - -#include "emulator_utils.hpp" -#include "process_context.hpp" -#include "syscalls.hpp" - -#include "reflect_extension.hpp" -#include - -#include "windows_emulator.hpp" - -#include "debugging/x64_gdb_stub_handler.hpp" - - -bool use_gdb = false; - -namespace -{ - template - class type_info - { - public: - type_info() - { - this->type_name_ = reflect::type_name(); - - reflect::for_each([this](auto I) - { - const auto member_name = reflect::member_name(); - const auto member_offset = reflect::offset_of(); - - this->members_[member_offset] = member_name; - }); - } - - std::string get_member_name(const size_t offset) const - { - size_t last_offset{}; - std::string_view last_member{}; - - for (const auto& member : this->members_) - { - if (offset == member.first) - { - return member.second; - } - - if (offset < member.first) - { - const auto diff = offset - last_offset; - return std::string(last_member) + "+" + std::to_string(diff); - } - - last_offset = member.first; - last_member = member.second; - } - - return ""; - } - - const std::string& get_type_name() const - { - return this->type_name_; - } - - private: - std::string type_name_{}; - std::map members_{}; - }; - - template - emulator_hook* watch_object(windows_emulator& emu, emulator_object object) - { - const type_info info{}; - - return emu.emu().hook_memory_read(object.value(), object.size(), - [i = std::move(info), object, &emu](const uint64_t address, size_t, uint64_t) - { - const auto rip = emu.emu().read_instruction_pointer(); - - const auto offset = address - object.value(); - printf("%s: %llX (%s) at %llX (%s)\n", i.get_type_name().c_str(), offset, - i.get_member_name(offset).c_str(), rip, - emu.process().module_manager.find_name(rip)); - }); - } - - void run() - { - const std::filesystem::path application = - //R"(C:\Users\mauri\source\repos\ConsoleApplication6\x64\Release\ConsoleApplication6.exe)"; - R"(C:\Program Files (x86)\Steam\steamapps\common\Hogwarts Legacy\Phoenix\Binaries\Win64\HogwartsLegacy.exe)"; - - windows_emulator win_emu{application, {L"Hello", L"World"}}; - - watch_object(win_emu, win_emu.process().teb); - watch_object(win_emu, win_emu.process().peb); - watch_object(win_emu, win_emu.process().kusd); - auto* params_hook = watch_object(win_emu, win_emu.process().process_params); - - win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB, ProcessParameters), 0x8, - [&](const uint64_t address, size_t, const uint64_t value) - { - const auto target_address = win_emu.process().peb.value() + offsetof( - PEB, ProcessParameters); - - if (address == target_address) - { - const emulator_object obj{ - win_emu.emu(), value - }; - - win_emu.emu().delete_hook(params_hook); - params_hook = watch_object(win_emu, obj); - } - }); - - win_emu.set_verbose(false); - - try - { - if (use_gdb) - { - puts("Launching gdb stub..."); - - x64_gdb_stub_handler handler{win_emu.emu()}; - run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), "0.0.0.0:28960"); - } - else - { - win_emu.emu().start_from_ip(); - } - } - catch (...) - { - printf("Emulation failed at: %llX\n", win_emu.emu().read_instruction_pointer()); - throw; - } - - printf("Emulation done.\n"); - } -} - -int main(int /*argc*/, char** /*argv*/) -{ - //setvbuf(stdout, nullptr, _IOFBF, 0x10000); - - try - { - do - { - run(); - } - while (use_gdb); - - return 0; - } - catch (std::exception& e) - { - puts(e.what()); - -#if defined(_WIN32) && 0 - MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); -#endif - } - - return 1; -} - -#ifdef _WIN32 -int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) -{ - return main(__argc, __argv); -} -#endif diff --git a/src/windows_emulator/windows_emulator.cpp b/src/windows_emulator/windows_emulator.cpp index 35b1f877..e0d88d0e 100644 --- a/src/windows_emulator/windows_emulator.cpp +++ b/src/windows_emulator/windows_emulator.cpp @@ -2,6 +2,8 @@ #include "windows_emulator.hpp" #include "context_frame.hpp" +#include + #define GS_SEGMENT_ADDR 0x6000000ULL #define GS_SEGMENT_SIZE (20 << 20) // 20 MB @@ -465,6 +467,11 @@ namespace } } +std::unique_ptr create_default_x64_emulator() +{ + return unicorn::create_x64_emulator(); +} + windows_emulator::windows_emulator(const std::filesystem::path& application, const std::vector& arguments, std::unique_ptr emu) : windows_emulator(std::move(emu)) @@ -569,6 +576,16 @@ void windows_emulator::setup_hooks() { ++this->process().executed_instructions; + if (address == 0x180038B65) + { + puts("!!! DLL init failed"); + } + if (address == 0x180038A20) + { + const auto* name = this->process().module_manager.find_name( + this->emu().reg(x64_register::rcx)); + printf("!!! DLL init: %s\n", name); + } const auto* binary = this->process().module_manager.find_by_address(address); if (binary) diff --git a/src/windows_emulator/windows_emulator.hpp b/src/windows_emulator/windows_emulator.hpp index ffcb68e9..0b79ba60 100644 --- a/src/windows_emulator/windows_emulator.hpp +++ b/src/windows_emulator/windows_emulator.hpp @@ -1,16 +1,17 @@ #pragma once #include -#include #include "syscalls.hpp" #include "process_context.hpp" +std::unique_ptr create_default_x64_emulator(); + class windows_emulator { public: - windows_emulator(std::unique_ptr emu = unicorn::create_x64_emulator()); + windows_emulator(std::unique_ptr emu = create_default_x64_emulator()); windows_emulator(const std::filesystem::path& application, const std::vector& arguments = {}, - std::unique_ptr emu = unicorn::create_x64_emulator()); + std::unique_ptr emu = create_default_x64_emulator()); windows_emulator(windows_emulator&&) = delete; windows_emulator(const windows_emulator&) = delete;