mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-31 16:31:02 +00:00
Setup api set mapping
This commit is contained in:
@@ -1,6 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* offset_pointer(void* data, const size_t offset)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(static_cast<uint8_t*>(data) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T* offset_pointer(const void* data, const size_t offset)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const T*>(static_cast<const uint8_t*>(data) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool is_within_start_and_end(const uint64_t value, const uint64_t start, const uint64_t end)
|
inline bool is_within_start_and_end(const uint64_t value, const uint64_t start, const uint64_t end)
|
||||||
{
|
{
|
||||||
return value >= start && value < end;
|
return value >= start && value < end;
|
||||||
|
|||||||
@@ -45,27 +45,27 @@ public:
|
|||||||
return this->address_ != 0;
|
return this->address_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
T read() const
|
T read(const size_t index = 0) const
|
||||||
{
|
{
|
||||||
T obj{};
|
T obj{};
|
||||||
this->emu_->read_memory(this->address_, &obj, sizeof(obj));
|
this->emu_->read_memory(this->address_ + index * this->size(), &obj, sizeof(obj));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const T& value) const
|
void write(const T& value, const size_t index = 0) const
|
||||||
{
|
{
|
||||||
this->emu_->write_memory(this->address_, &value, sizeof(value));
|
this->emu_->write_memory(this->address_ + index * this->size(), &value, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void access(const F& accessor) const
|
void access(const F& accessor, const size_t index = 0) const
|
||||||
{
|
{
|
||||||
T obj{};
|
T obj{};
|
||||||
this->emu_->read_memory(this->address_, &obj, sizeof(obj));
|
this->emu_->read_memory(this->address_ + index * this->size(), &obj, sizeof(obj));
|
||||||
|
|
||||||
accessor(obj);
|
accessor(obj);
|
||||||
|
|
||||||
this->write(obj);
|
this->write(obj, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -103,9 +103,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
emulator_object<T> reserve()
|
emulator_object<T> reserve(const size_t count = 1)
|
||||||
{
|
{
|
||||||
const auto potential_start = this->reserve(sizeof(T), alignof(T));
|
const auto potential_start = this->reserve(sizeof(T) * count, alignof(T));
|
||||||
return emulator_object<T>(*this->emu_, potential_start);
|
return emulator_object<T>(*this->emu_, potential_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "gdb_stub.hpp"
|
#include "gdb_stub.hpp"
|
||||||
#include "module_mapper.hpp"
|
#include "module_mapper.hpp"
|
||||||
|
#include <address_utils.hpp>
|
||||||
|
|
||||||
#define GS_SEGMENT_ADDR 0x6000000ULL
|
#define GS_SEGMENT_ADDR 0x6000000ULL
|
||||||
#define GS_SEGMENT_SIZE (20 << 20) // 20 MB
|
#define GS_SEGMENT_SIZE (20 << 20) // 20 MB
|
||||||
@@ -77,6 +78,83 @@ namespace
|
|||||||
return kusd_object;
|
return kusd_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t copy_string(x64_emulator& emu, emulator_allocator& allocator, const void* base_ptr, const uint64_t offset,
|
||||||
|
const size_t length)
|
||||||
|
{
|
||||||
|
const auto length_to_allocate = length + 2;
|
||||||
|
const auto str_obj = allocator.reserve(length_to_allocate);
|
||||||
|
emu.write_memory(str_obj, static_cast<const uint8_t*>(base_ptr) + offset, length);
|
||||||
|
|
||||||
|
return str_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG copy_string_as_relative(x64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
|
||||||
|
const void* base_ptr, const uint64_t offset,
|
||||||
|
const size_t length)
|
||||||
|
{
|
||||||
|
return static_cast<ULONG>(copy_string(emu, allocator, base_ptr, offset, length) - result_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
emulator_object<API_SET_NAMESPACE> clone_api_set_map(x64_emulator& emu, emulator_allocator& allocator,const API_SET_NAMESPACE& orig_api_set_map)
|
||||||
|
{
|
||||||
|
const auto api_set_map_obj = allocator.reserve<API_SET_NAMESPACE>();
|
||||||
|
const auto ns_entries_obj = allocator.reserve<API_SET_NAMESPACE_ENTRY>(orig_api_set_map.Count);
|
||||||
|
const auto hash_entries_obj = allocator.reserve<API_SET_HASH_ENTRY>(orig_api_set_map.Count);
|
||||||
|
|
||||||
|
auto api_set_map = orig_api_set_map;
|
||||||
|
api_set_map.EntryOffset = static_cast<ULONG>(ns_entries_obj.value() - api_set_map_obj.value());
|
||||||
|
api_set_map.HashOffset = static_cast<ULONG>(hash_entries_obj.value() - api_set_map_obj.value());
|
||||||
|
|
||||||
|
|
||||||
|
const auto orig_ns_entries = offset_pointer<API_SET_NAMESPACE_ENTRY>(
|
||||||
|
&orig_api_set_map, orig_api_set_map.EntryOffset);
|
||||||
|
const auto orig_hash_entries = offset_pointer<API_SET_HASH_ENTRY>(
|
||||||
|
&orig_api_set_map, orig_api_set_map.HashOffset);
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < orig_api_set_map.Count; ++i)
|
||||||
|
{
|
||||||
|
auto ns_entry = orig_ns_entries[i];
|
||||||
|
const auto hash_entry = orig_hash_entries[i];
|
||||||
|
|
||||||
|
ns_entry.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map,
|
||||||
|
ns_entry.NameOffset, ns_entry.NameLength);
|
||||||
|
|
||||||
|
const auto values_obj = allocator.reserve<API_SET_VALUE_ENTRY>(ns_entry.ValueCount);
|
||||||
|
const auto orig_values = offset_pointer<API_SET_VALUE_ENTRY>(
|
||||||
|
&orig_api_set_map, ns_entry.ValueOffset);
|
||||||
|
|
||||||
|
for (ULONG j = 0; j < ns_entry.ValueCount; ++j)
|
||||||
|
{
|
||||||
|
auto value = orig_values[j];
|
||||||
|
|
||||||
|
value.ValueOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map,
|
||||||
|
value.ValueOffset, value.ValueLength);
|
||||||
|
|
||||||
|
if (value.NameLength)
|
||||||
|
{
|
||||||
|
value.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(),
|
||||||
|
&orig_api_set_map,
|
||||||
|
value.NameOffset, value.NameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
values_obj.write(value, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_entries_obj.write(ns_entry, i);
|
||||||
|
hash_entries_obj.write(hash_entry, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
api_set_map_obj.write(api_set_map);
|
||||||
|
|
||||||
|
return api_set_map_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
emulator_object<API_SET_NAMESPACE> build_api_set_map(x64_emulator& emu, emulator_allocator& allocator)
|
||||||
|
{
|
||||||
|
const auto& orig_api_set_map = *NtCurrentTeb()->ProcessEnvironmentBlock->ApiSetMap;
|
||||||
|
return clone_api_set_map(emu, allocator, orig_api_set_map);
|
||||||
|
}
|
||||||
|
|
||||||
process_context setup_context(x64_emulator& emu)
|
process_context setup_context(x64_emulator& emu)
|
||||||
{
|
{
|
||||||
setup_stack(emu, STACK_ADDRESS, STACK_SIZE);
|
setup_stack(emu, STACK_ADDRESS, STACK_SIZE);
|
||||||
@@ -102,22 +180,22 @@ namespace
|
|||||||
teb.ProcessEnvironmentBlock = context.peb.ptr();
|
teb.ProcessEnvironmentBlock = context.peb.ptr();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params)
|
||||||
|
{
|
||||||
|
proc_params.Length = sizeof(proc_params);
|
||||||
|
proc_params.Flags = 0x6001;
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
|
||||||
context.peb.access([&](PEB& peb)
|
context.peb.access([&](PEB& peb)
|
||||||
{
|
{
|
||||||
peb.ImageBaseAddress = nullptr;
|
peb.ImageBaseAddress = nullptr;
|
||||||
peb.ProcessHeap = nullptr;
|
peb.ProcessHeap = nullptr;
|
||||||
peb.ProcessHeaps = nullptr;
|
peb.ProcessHeaps = nullptr;
|
||||||
peb.ProcessParameters = context.process_params.ptr();
|
peb.ProcessParameters = context.process_params.ptr();
|
||||||
peb.ApiSetMap = gs.reserve<API_SET_NAMESPACE>().ptr();
|
peb.ApiSetMap = build_api_set_map(emu, gs).ptr();
|
||||||
});
|
|
||||||
|
|
||||||
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params)
|
|
||||||
{
|
|
||||||
proc_params.Length = sizeof(proc_params);
|
|
||||||
proc_params.Flags = 0x6001;
|
|
||||||
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");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
@@ -549,9 +627,9 @@ int main(int /*argc*/, char** /*argv*/)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (std::exception& uce)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
puts(uce.what());
|
puts(e.what());
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
//MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||||
|
|||||||
@@ -2,34 +2,6 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <emulator.hpp>
|
#include <emulator.hpp>
|
||||||
|
|
||||||
/*
|
|
||||||
inline memory_permission get_memory_protection(emulator& emu, const uint64_t address)
|
|
||||||
{
|
|
||||||
for (const auto& region : emu.get_memory_regions())
|
|
||||||
{
|
|
||||||
if (is_within_start_and_length(address, region.start, region.length))
|
|
||||||
{
|
|
||||||
return region.pemissions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return memory_permission::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_memory_allocated(emulator& emu, const uint64_t address)
|
|
||||||
{
|
|
||||||
for (const auto& region : emu.get_memory_regions())
|
|
||||||
{
|
|
||||||
if (is_within_start_and_length(address, region.start, region.length))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
inline memory_permission map_nt_to_emulator_protection(const uint32_t nt_protection)
|
inline memory_permission map_nt_to_emulator_protection(const uint32_t nt_protection)
|
||||||
{
|
{
|
||||||
switch (nt_protection)
|
switch (nt_protection)
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
#include "std_include.hpp"
|
#include "std_include.hpp"
|
||||||
#include "module_mapper.hpp"
|
#include "module_mapper.hpp"
|
||||||
|
#include <address_utils.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template <typename T>
|
|
||||||
T offset_pointer(const void* data, const size_t offset)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<T>(static_cast<const uint8_t*>(data) + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void collect_exports(mapped_binary& binary, const unsigned char* ptr, const IMAGE_OPTIONAL_HEADER& optional_header)
|
void collect_exports(mapped_binary& binary, const unsigned char* ptr, const IMAGE_OPTIONAL_HEADER& optional_header)
|
||||||
{
|
{
|
||||||
auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||||
|
|||||||
Reference in New Issue
Block a user