mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Small fixes and adjustments
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000;
|
||||
constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffff;
|
||||
constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL;
|
||||
constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL;
|
||||
|
||||
void split_regions(memory_manager::committed_region_map& regions, const std::vector<uint64_t>& split_points)
|
||||
{
|
||||
@@ -287,7 +287,7 @@ bool memory_manager::release_memory(const uint64_t address, size_t size)
|
||||
|
||||
uint64_t memory_manager::find_free_allocation_base(const size_t size) const
|
||||
{
|
||||
uint64_t start_address = MIN_ALLOCATION_ADDRESS;
|
||||
uint64_t start_address = std::max(MIN_ALLOCATION_ADDRESS, 0x1000000000ULL);
|
||||
|
||||
for (const auto& region : this->reserved_regions_)
|
||||
{
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace
|
||||
emu.reg<uint16_t>(x64_register::ss, 0x2B);
|
||||
}
|
||||
|
||||
process_context setup_context(x64_emulator& emu)
|
||||
process_context setup_context(x64_emulator& emu, const std::filesystem::path& file)
|
||||
{
|
||||
process_context context{};
|
||||
|
||||
@@ -325,9 +325,9 @@ namespace
|
||||
proc_params.StandardInput = STDIN_HANDLE.h;
|
||||
proc_params.StandardError = proc_params.StandardOutput;
|
||||
|
||||
gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, L"C:\\Users\\mauri\\Desktop");
|
||||
gs.make_unicode_string(proc_params.ImagePathName, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe");
|
||||
gs.make_unicode_string(proc_params.CommandLine, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe");
|
||||
gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, file.parent_path().wstring());
|
||||
gs.make_unicode_string(proc_params.ImagePathName, file.wstring());
|
||||
gs.make_unicode_string(proc_params.CommandLine, file.wstring());
|
||||
});
|
||||
|
||||
context.peb.access([&](PEB& peb)
|
||||
@@ -518,10 +518,13 @@ namespace
|
||||
{
|
||||
const auto emu = unicorn::create_x64_emulator();
|
||||
|
||||
auto context = setup_context(*emu);
|
||||
const std::filesystem::path application =
|
||||
R"(C:\Program Files (x86)\Steam\steamapps\common\Hogwarts Legacy\Phoenix\Binaries\Win64\HogwartsLegacy.exe)";
|
||||
|
||||
auto context = setup_context(*emu, application);
|
||||
context.module_manager = module_manager(*emu);
|
||||
|
||||
context.executable = context.module_manager.map_module(R"(C:\Users\mauri\Desktop\ConsoleApplication6.exe)");
|
||||
context.executable = context.module_manager.map_module(application);
|
||||
|
||||
context.peb.access([&](PEB& peb)
|
||||
{
|
||||
@@ -574,18 +577,19 @@ namespace
|
||||
return memory_violation_continuation::resume;
|
||||
});
|
||||
|
||||
/*
|
||||
watch_object(*emu, context.teb);
|
||||
watch_object(*emu, context.peb);
|
||||
watch_object(*emu, context.process_params);
|
||||
watch_object(*emu, context.kusd);
|
||||
|
||||
*/
|
||||
context.verbose = false;
|
||||
|
||||
emu->hook_memory_execution(0, std::numeric_limits<size_t>::max(), [&](const uint64_t address, const size_t)
|
||||
{
|
||||
++context.executed_instructions;
|
||||
|
||||
const auto* binary = context.module_manager.find_by_address(address);
|
||||
/*const auto* binary = context.module_manager.find_by_address(address);
|
||||
|
||||
if (binary)
|
||||
{
|
||||
@@ -595,7 +599,7 @@ namespace
|
||||
printf("Executing function: %s - %s (%llX)\n", binary->name.c_str(), export_entry->second.c_str(),
|
||||
address);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!context.verbose)
|
||||
{
|
||||
|
||||
@@ -7,14 +7,17 @@ module_manager::module_manager(emulator& emu)
|
||||
{
|
||||
}
|
||||
|
||||
mapped_module* module_manager::map_module(std::filesystem::path file)
|
||||
mapped_module* module_manager::map_module(const std::filesystem::path& file)
|
||||
{
|
||||
auto mod = map_module_from_file(*this->emu_, std::move(file));
|
||||
auto mod = map_module_from_file(*this->emu_, file);
|
||||
if (!mod)
|
||||
{
|
||||
printf("Failed to map %s\n", file.generic_string().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
printf("Mapped %s at %llX\n", mod->path.generic_string().c_str(), mod->image_base);
|
||||
|
||||
const auto image_base = mod->image_base;
|
||||
const auto entry = this->modules_.try_emplace(image_base, std::move(*mod));
|
||||
return &entry.first->second;
|
||||
|
||||
@@ -8,7 +8,7 @@ public:
|
||||
module_manager() = default; // TODO: Get rid of that
|
||||
module_manager(emulator& emu);
|
||||
|
||||
mapped_module* map_module(std::filesystem::path file);
|
||||
mapped_module* map_module(const std::filesystem::path& file);
|
||||
|
||||
mapped_module* find_by_address(const uint64_t address)
|
||||
{
|
||||
|
||||
@@ -178,58 +178,68 @@ namespace
|
||||
std::ifstream stream(file, std::ios::in | std::ios::binary);
|
||||
return {(std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<mapped_module> map_module(emulator& emu, const std::span<const uint8_t> data,
|
||||
std::filesystem::path file)
|
||||
{
|
||||
mapped_module binary{};
|
||||
binary.path = std::move(file);
|
||||
binary.name = binary.path.filename().string();
|
||||
|
||||
utils::safe_buffer_accessor buffer{data};
|
||||
|
||||
const auto dos_header = buffer.as<IMAGE_DOS_HEADER>(0).get();
|
||||
const auto nt_headers_offset = dos_header.e_lfanew;
|
||||
|
||||
const auto nt_headers = buffer.as<IMAGE_NT_HEADERS>(nt_headers_offset).get();
|
||||
auto& optional_header = nt_headers.OptionalHeader;
|
||||
|
||||
binary.image_base = optional_header.ImageBase;
|
||||
binary.size_of_image = optional_header.SizeOfImage; // TODO: Sanitize
|
||||
|
||||
if (!emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read))
|
||||
{
|
||||
binary.image_base = emu.find_free_allocation_base(binary.size_of_image);
|
||||
if ((optional_header.DllCharacteristics &
|
||||
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 || //
|
||||
!emu.allocate_memory(
|
||||
binary.image_base, binary.size_of_image, memory_permission::read))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint;
|
||||
|
||||
const auto* header_buffer = buffer.get_pointer_for_range(0, optional_header.SizeOfHeaders);
|
||||
emu.write_memory(binary.image_base, header_buffer,
|
||||
optional_header.SizeOfHeaders);
|
||||
|
||||
map_sections(emu, binary, buffer, nt_headers, nt_headers_offset);
|
||||
|
||||
auto mapped_memory = read_mapped_memory(emu, binary);
|
||||
utils::safe_buffer_accessor<uint8_t> mapped_buffer{mapped_memory};
|
||||
|
||||
apply_relocations(binary, mapped_buffer, optional_header);
|
||||
collect_exports(binary, mapped_buffer, optional_header);
|
||||
|
||||
emu.write_memory(binary.image_base, mapped_memory.data(), mapped_memory.size());
|
||||
|
||||
return binary;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<mapped_module> map_module_from_data(emulator& emu, const std::span<const uint8_t> data,
|
||||
std::filesystem::path file)
|
||||
{
|
||||
mapped_module binary{};
|
||||
binary.path = std::move(file);
|
||||
binary.name = binary.path.filename().string();
|
||||
|
||||
utils::safe_buffer_accessor buffer{data};
|
||||
|
||||
const auto dos_header = buffer.as<IMAGE_DOS_HEADER>(0).get();
|
||||
const auto nt_headers_offset = dos_header.e_lfanew;
|
||||
|
||||
const auto nt_headers = buffer.as<IMAGE_NT_HEADERS>(nt_headers_offset).get();
|
||||
auto& optional_header = nt_headers.OptionalHeader;
|
||||
|
||||
binary.image_base = optional_header.ImageBase;
|
||||
binary.size_of_image = optional_header.SizeOfImage; // TODO: Sanitize
|
||||
|
||||
if (!emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read))
|
||||
try
|
||||
{
|
||||
binary.image_base = emu.find_free_allocation_base(binary.size_of_image);
|
||||
if ((optional_header.DllCharacteristics &
|
||||
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 || //
|
||||
!emu.allocate_memory(
|
||||
binary.image_base, binary.size_of_image, memory_permission::read))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return map_module(emu, data, std::move(file));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint;
|
||||
|
||||
printf("Mapping %s at %llX\n", binary.path.generic_string().c_str(), binary.image_base);
|
||||
|
||||
const auto* header_buffer = buffer.get_pointer_for_range(0, optional_header.SizeOfHeaders);
|
||||
emu.write_memory(binary.image_base, header_buffer,
|
||||
optional_header.SizeOfHeaders);
|
||||
|
||||
map_sections(emu, binary, buffer, nt_headers, nt_headers_offset);
|
||||
|
||||
auto mapped_memory = read_mapped_memory(emu, binary);
|
||||
utils::safe_buffer_accessor<uint8_t> mapped_buffer{mapped_memory};
|
||||
|
||||
apply_relocations(binary, mapped_buffer, optional_header);
|
||||
collect_exports(binary, mapped_buffer, optional_header);
|
||||
|
||||
emu.write_memory(binary.image_base, mapped_memory.data(), mapped_memory.size());
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
std::optional<mapped_module> map_module_from_file(emulator& emu, std::filesystem::path file)
|
||||
|
||||
@@ -719,28 +719,46 @@ namespace
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (info_class != ProcessCookie)
|
||||
if (info_class == ProcessCookie)
|
||||
{
|
||||
printf("Unsupported process info class: %X\n", info_class);
|
||||
c.emu.stop();
|
||||
if (return_length)
|
||||
{
|
||||
return_length.write(sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
if (process_information_length != sizeof(uint32_t))
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
const emulator_object<uint32_t> info{c.emu, process_information};
|
||||
info.write(0x01234567);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (return_length)
|
||||
if (info_class == ProcessDebugPort)
|
||||
{
|
||||
return_length.write(sizeof(uint32_t));
|
||||
if (return_length)
|
||||
{
|
||||
return_length.write(sizeof(DWORD_PTR));
|
||||
}
|
||||
|
||||
if (process_information_length != sizeof(DWORD_PTR))
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
const emulator_object<DWORD_PTR> info{c.emu, process_information};
|
||||
info.write(0);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (process_information_length != sizeof(uint32_t))
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
printf("Unsupported process info class: %X\n", info_class);
|
||||
c.emu.stop();
|
||||
|
||||
const emulator_object<uint32_t> info{c.emu, process_information};
|
||||
info.write(0x01234567);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, const uint64_t process_handle,
|
||||
@@ -1097,6 +1115,23 @@ namespace
|
||||
|
||||
throw std::runtime_error("Unsupported file");
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status,
|
||||
const ULONG /*number_of_parameters*/,
|
||||
const emulator_object<UNICODE_STRING> /*unicode_string_parameter_mask*/,
|
||||
const emulator_object<DWORD> /*parameters*/,
|
||||
const HARDERROR_RESPONSE_OPTION /*valid_response_option*/,
|
||||
const emulator_object<HARDERROR_RESPONSE> response)
|
||||
{
|
||||
if (response)
|
||||
{
|
||||
response.write(ResponseAbort);
|
||||
}
|
||||
|
||||
printf("Hard error: %X\n", error_status);
|
||||
c.emu.stop();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports)
|
||||
@@ -1154,6 +1189,7 @@ syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports)
|
||||
add_handler(NtContinue);
|
||||
add_handler(NtTerminateProcess);
|
||||
add_handler(NtWriteFile);
|
||||
add_handler(NtRaiseHardError);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user