Skip to content

Commit

Permalink
separate emulator from executable
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/windows_emulator/main.cpp
  • Loading branch information
momo5502 committed Sep 18, 2024
1 parent acf5673 commit 8f12c13
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ add_subdirectory(common)
add_subdirectory(emulator)
add_subdirectory(unicorn_emulator)
add_subdirectory(windows_emulator)
add_subdirectory(sample)
23 changes: 23 additions & 0 deletions src/sample/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
105 changes: 105 additions & 0 deletions src/sample/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "std_include.hpp"

#include <windows_emulator.hpp>
#include <debugging/x64_gdb_stub_handler.hpp>

#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<RTL_USER_PROCESS_PARAMETERS> 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
20 changes: 20 additions & 0 deletions src/sample/object_watching.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "reflect_type_info.hpp"

template <typename T>
emulator_hook* watch_object(windows_emulator& emu, emulator_object<T> object)
{
const reflect_type_info<T> 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));
});
}
File renamed without changes.
56 changes: 56 additions & 0 deletions src/sample/reflect_type_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include "reflect_extension.hpp"
#include <reflect>

template <typename T>
class reflect_type_info
{
public:
reflect_type_info()
{
this->type_name_ = reflect::type_name<T>();

reflect::for_each<T>([this](auto I)
{
const auto member_name = reflect::member_name<I, T>();
const auto member_offset = reflect::offset_of<I, T>();

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 "<N/A>";
}

const std::string& get_type_name() const
{
return this->type_name_;
}

private:
std::string type_name_{};
std::map<size_t, std::string> members_{};
};
File renamed without changes.
File renamed without changes.
79 changes: 79 additions & 0 deletions src/sample/std_include.hpp
Original file line number Diff line number Diff line change
@@ -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 <map>
#include <set>
#include <list>
#include <array>
#include <deque>
#include <queue>
#include <thread>
#include <ranges>
#include <atomic>
#include <vector>
#include <mutex>
#include <string>
#include <chrono>
#include <memory>
#include <fstream>
#include <functional>
#include <filesystem>
#include <optional>
#include <stdexcept>
#include <string_view>
#include <unordered_set>
#include <condition_variable>

#include <cassert>

#define NTDDI_WIN11_GE 0
#define PHNT_VERSION PHNT_WIN11
#include <phnt_windows.h>
#include <phnt.h>
#include <ntgdi.h>

#ifdef _WIN32
#pragma warning(pop)
#endif

#ifdef max
#undef max
#endif

#ifdef min
#undef min
#endif
#endif

using namespace std::literals;
13 changes: 9 additions & 4 deletions src/windows_emulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@ 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})

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)
17 changes: 17 additions & 0 deletions src/windows_emulator/windows_emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "windows_emulator.hpp"
#include "context_frame.hpp"

#include <unicorn_x64_emulator.hpp>

#define GS_SEGMENT_ADDR 0x6000000ULL
#define GS_SEGMENT_SIZE (20 << 20) // 20 MB

Expand Down Expand Up @@ -465,6 +467,11 @@ namespace
}
}

std::unique_ptr<x64_emulator> create_default_x64_emulator()
{
return unicorn::create_x64_emulator();
}

windows_emulator::windows_emulator(const std::filesystem::path& application, const std::vector<std::wstring>& arguments,
std::unique_ptr<x64_emulator> emu)
: windows_emulator(std::move(emu))
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions src/windows_emulator/windows_emulator.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#pragma once
#include <x64_emulator.hpp>
#include <unicorn_x64_emulator.hpp>

#include "syscalls.hpp"
#include "process_context.hpp"

std::unique_ptr<x64_emulator> create_default_x64_emulator();

class windows_emulator
{
public:
windows_emulator(std::unique_ptr<x64_emulator> emu = unicorn::create_x64_emulator());
windows_emulator(std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(const std::filesystem::path& application, const std::vector<std::wstring>& arguments = {},
std::unique_ptr<x64_emulator> emu = unicorn::create_x64_emulator());
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());

windows_emulator(windows_emulator&&) = delete;
windows_emulator(const windows_emulator&) = delete;
Expand Down

0 comments on commit 8f12c13

Please sign in to comment.