migrate to platform structures

This commit is contained in:
robert-yates
2024-11-23 18:59:54 +01:00
parent 12c80f159e
commit 8e049a2650
16 changed files with 326 additions and 295 deletions

View File

@@ -16,15 +16,15 @@ namespace
//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,
win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8,
[&](const uint64_t address, size_t, const uint64_t value)
{
const auto target_address = win_emu.process().peb.value() + offsetof(
PEB, ProcessParameters);
PEB64, ProcessParameters);
if (address == target_address)
{
const emulator_object<RTL_USER_PROCESS_PARAMETERS> obj{
const emulator_object<RTL_USER_PROCESS_PARAMETERS64> obj{
win_emu.emu(), value
};

View File

@@ -1,5 +1,7 @@
#pragma once
#ifdef OS_WINDOWS
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
@@ -83,3 +85,5 @@ namespace utils::nt
HANDLE handle_{InvalidHandleFunction()};
};
}
#endif

View File

@@ -3,9 +3,9 @@
namespace context_frame
{
void restore(x64_emulator& emu, const CONTEXT& context)
void restore(x64_emulator& emu, const CONTEXT64& context)
{
if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS)
if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64)
{
emu.reg(x64_register::dr0, context.Dr0);
emu.reg(x64_register::dr1, context.Dr1);
@@ -15,7 +15,7 @@ namespace context_frame
emu.reg(x64_register::dr7, context.Dr7);
}
if (context.ContextFlags & CONTEXT_CONTROL)
if (context.ContextFlags & CONTEXT_CONTROL_64)
{
emu.reg<uint16_t>(x64_register::ss, context.SegSs);
emu.reg<uint16_t>(x64_register::cs, context.SegCs);
@@ -26,7 +26,7 @@ namespace context_frame
emu.reg<uint32_t>(x64_register::eflags, context.EFlags);
}
if (context.ContextFlags & CONTEXT_INTEGER)
if (context.ContextFlags & CONTEXT_INTEGER_64)
{
emu.reg(x64_register::rax, context.Rax);
emu.reg(x64_register::rbx, context.Rbx);
@@ -53,7 +53,7 @@ namespace context_frame
emu.reg<uint16_t>(x64_register::gs, context.SegGs);
}*/
if (context.ContextFlags & CONTEXT_FLOATING_POINT)
if (context.ContextFlags & CONTEXT_FLOATING_POINT_64)
{
emu.reg<uint16_t>(x64_register::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x64_register::fpsw, context.FltSave.StatusWord);
@@ -66,7 +66,7 @@ namespace context_frame
}
}
if (context.ContextFlags & CONTEXT_XSTATE)
if (context.ContextFlags & CONTEXT_XSTATE_64)
{
emu.reg<uint32_t>(x64_register::mxcsr, context.MxCsr);
@@ -78,9 +78,9 @@ namespace context_frame
}
}
void save(x64_emulator& emu, CONTEXT& context)
void save(x64_emulator& emu, CONTEXT64& context)
{
if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS)
if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64)
{
context.Dr0 = emu.reg(x64_register::dr0);
context.Dr1 = emu.reg(x64_register::dr1);
@@ -90,7 +90,7 @@ namespace context_frame
context.Dr7 = emu.reg(x64_register::dr7);
}
if (context.ContextFlags & CONTEXT_CONTROL)
if (context.ContextFlags & CONTEXT_CONTROL_64)
{
context.SegSs = emu.reg<uint16_t>(x64_register::ss);
context.SegCs = emu.reg<uint16_t>(x64_register::cs);
@@ -99,7 +99,7 @@ namespace context_frame
context.EFlags = emu.reg<uint32_t>(x64_register::eflags);
}
if (context.ContextFlags & CONTEXT_INTEGER)
if (context.ContextFlags & CONTEXT_INTEGER_64)
{
context.Rax = emu.reg(x64_register::rax);
context.Rbx = emu.reg(x64_register::rbx);
@@ -118,7 +118,7 @@ namespace context_frame
context.R15 = emu.reg(x64_register::r15);
}
if (context.ContextFlags & CONTEXT_SEGMENTS)
if (context.ContextFlags & CONTEXT_SEGMENTS_64)
{
context.SegDs = emu.reg<uint16_t>(x64_register::ds);
context.SegEs = emu.reg<uint16_t>(x64_register::es);
@@ -126,7 +126,7 @@ namespace context_frame
context.SegGs = emu.reg<uint16_t>(x64_register::gs);
}
if (context.ContextFlags & CONTEXT_FLOATING_POINT)
if (context.ContextFlags & CONTEXT_FLOATING_POINT_64)
{
context.FltSave.ControlWord = emu.reg<uint16_t>(x64_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x64_register::fpsw);
@@ -138,7 +138,7 @@ namespace context_frame
}
}
if (context.ContextFlags & CONTEXT_XSTATE)
if (context.ContextFlags & CONTEXT_XSTATE_64)
{
context.MxCsr = emu.reg<uint32_t>(x64_register::mxcsr);
for (int i = 0; i < 16; i++)

View File

@@ -3,6 +3,6 @@
namespace context_frame
{
void save(x64_emulator& emu, CONTEXT& context);
void restore(x64_emulator& emu, const CONTEXT& context);
void save(x64_emulator& emu, CONTEXT64& context);
void restore(x64_emulator& emu, const CONTEXT64& context);
}

View File

@@ -32,23 +32,23 @@ namespace
return win_emu.emu().read_memory<afd_creation_data>(data.buffer);
}
std::pair<AFD_POLL_INFO, std::vector<AFD_POLL_HANDLE_INFO>> get_poll_info(
std::pair<AFD_POLL_INFO64, std::vector<AFD_POLL_HANDLE_INFO64>> get_poll_info(
windows_emulator& win_emu, const io_device_context& c)
{
constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles);
constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles);
if (!c.input_buffer || c.input_buffer_length < info_size)
{
throw std::runtime_error("Bad AFD poll data");
}
AFD_POLL_INFO poll_info{};
AFD_POLL_INFO64 poll_info{};
win_emu.emu().read_memory(c.input_buffer, &poll_info, info_size);
std::vector<AFD_POLL_HANDLE_INFO> handle_info{};
std::vector<AFD_POLL_HANDLE_INFO64> handle_info{};
const emulator_object<AFD_POLL_HANDLE_INFO> handle_info_obj{win_emu.emu(), c.input_buffer + info_size};
const emulator_object<AFD_POLL_HANDLE_INFO64> handle_info_obj{win_emu.emu(), c.input_buffer + info_size};
if (c.input_buffer_length < (info_size + sizeof(AFD_POLL_HANDLE_INFO) * poll_info.NumberOfHandles))
if (c.input_buffer_length < (info_size + sizeof(AFD_POLL_HANDLE_INFO64) * poll_info.NumberOfHandles))
{
throw std::runtime_error("Bad AFD poll handle data");
}
@@ -126,7 +126,7 @@ namespace
NTSTATUS perform_poll(windows_emulator& win_emu, const io_device_context& c,
const std::span<const SOCKET> endpoints,
const std::span<const AFD_POLL_HANDLE_INFO> handles)
const std::span<const AFD_POLL_HANDLE_INFO64> handles)
{
std::vector<pollfd> poll_data{};
poll_data.resize(endpoints.size());
@@ -147,8 +147,8 @@ namespace
return STATUS_PENDING;
}
constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles);
const emulator_object<AFD_POLL_HANDLE_INFO> handle_info_obj{win_emu.emu(), c.input_buffer + info_size};
constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles);
const emulator_object<AFD_POLL_HANDLE_INFO64> handle_info_obj{win_emu.emu(), c.input_buffer + info_size};
size_t current_index = 0;
@@ -170,7 +170,7 @@ namespace
assert(current_index == static_cast<size_t>(count));
emulator_object<AFD_POLL_INFO>{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO& info)
emulator_object<AFD_POLL_INFO64>{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO64& info)
{
info.NumberOfHandles = static_cast<ULONG>(current_index);
});
@@ -367,7 +367,7 @@ namespace
}
static std::vector<SOCKET> resolve_endpoints(windows_emulator& win_emu,
const std::span<const AFD_POLL_HANDLE_INFO> handles)
const std::span<const AFD_POLL_HANDLE_INFO64> handles)
{
auto& proc = win_emu.process();
@@ -376,7 +376,7 @@ namespace
for (const auto& handle : handles)
{
auto* device = proc.devices.get(reinterpret_cast<uint64_t>(handle.Handle));
auto* device = proc.devices.get(handle.Handle);
if (!device)
{
throw std::runtime_error("Bad device!");
@@ -428,17 +428,17 @@ namespace
{
auto& emu = win_emu.emu();
if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO))
if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO<EmulatorTraits<Emu64>>))
{
return STATUS_BUFFER_TOO_SMALL;
}
const auto receive_info = emu.read_memory<AFD_RECV_DATAGRAM_INFO>(c.input_buffer);
const auto buffer = emu.read_memory<WSABUF>(receive_info.BufferArray);
const auto receive_info = emu.read_memory<AFD_RECV_DATAGRAM_INFO<EmulatorTraits<Emu64>>>(c.input_buffer);
const auto buffer = emu.read_memory<EMU_WSABUF<EmulatorTraits<Emu64>>>(receive_info.BufferArray);
std::vector<std::byte> address{};
ULONG address_length = 0x1000;
unsigned long address_length = 0x1000;
if (receive_info.AddressLength)
{
address_length = emu.read_memory<ULONG>(receive_info.AddressLength);
@@ -456,8 +456,13 @@ namespace
std::vector<char> data{};
data.resize(buffer.len);
#ifdef OS_WINDOWS
const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast<int>(data.size()), 0,
reinterpret_cast<sockaddr*>(address.data()), &fromlength);
#else
const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast<int>(data.size()), 0,
reinterpret_cast<sockaddr*>(address.data()), (socklen_t*)&fromlength);
#endif
if (recevied_data < 0)
{
@@ -482,7 +487,7 @@ namespace
if (c.io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = static_cast<uint32_t>(recevied_data);
c.io_status_block.write(block);
}
@@ -494,13 +499,13 @@ namespace
{
const auto& emu = win_emu.emu();
if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO))
if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO<EmulatorTraits<Emu64>>))
{
return STATUS_BUFFER_TOO_SMALL;
}
const auto send_info = emu.read_memory<AFD_SEND_DATAGRAM_INFO>(c.input_buffer);
const auto buffer = emu.read_memory<WSABUF>(send_info.BufferArray);
const auto send_info = emu.read_memory<AFD_SEND_DATAGRAM_INFO<EmulatorTraits<Emu64>>>(c.input_buffer);
const auto buffer = emu.read_memory<EMU_WSABUF<EmulatorTraits<Emu64>>>(send_info.BufferArray);
const auto address = emu.read_memory(send_info.TdiConnInfo.RemoteAddress,
send_info.TdiConnInfo.RemoteAddressLength);
@@ -528,7 +533,7 @@ namespace
if (c.io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = static_cast<uint32_t>(sent_data);
c.io_status_block.write(block);
}

View File

@@ -3,87 +3,93 @@
#include "../std_include.hpp"
typedef LONG TDI_STATUS;
typedef PVOID CONNECTION_CONTEXT;
typedef struct _TDI_CONNECTION_INFORMATION
template <typename Traits>
struct TDI_CONNECTION_INFORMATION
{
LONG UserDataLength;
PVOID UserData;
typename Traits::PVOID UserData;
LONG OptionsLength;
PVOID Options;
typename Traits::PVOID Options;
LONG RemoteAddressLength;
PVOID RemoteAddress;
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;
typename Traits::PVOID RemoteAddress;
};
typedef struct _TDI_REQUEST
template <typename Traits>
struct TDI_REQUEST
{
union
{
HANDLE AddressHandle;
CONNECTION_CONTEXT ConnectionContext;
HANDLE ControlChannel;
typename Traits::HANDLE AddressHandle;
EMULATOR_CAST(typename Traits::PVOID, CONNECTION_CONTEXT) ConnectionContext;
typename Traits::HANDLE ControlChannel;
} Handle;
PVOID RequestNotifyObject;
PVOID RequestContext;
typename Traits::PVOID RequestNotifyObject;
typename Traits::PVOID RequestContext;
TDI_STATUS TdiStatus;
} TDI_REQUEST, *PTDI_REQUEST;
};
typedef struct _TDI_REQUEST_SEND_DATAGRAM
template <typename Traits>
struct TDI_REQUEST_SEND_DATAGRAM
{
TDI_REQUEST Request;
PTDI_CONNECTION_INFORMATION SendDatagramInformation;
} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM;
TDI_REQUEST<Traits> Request;
EMULATOR_CAST(typename Traits::PVOID, PTDI_CONNECTION_INFORMATION) SendDatagramInformation;
};
typedef struct _AFD_SEND_INFO
template <typename Traits>
struct AFD_SEND_INFO
{
LPWSABUF BufferArray;
EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray;
ULONG BufferCount;
ULONG AfdFlags;
ULONG TdiFlags;
} AFD_SEND_INFO, *PAFD_SEND_INFO;
};
typedef struct _AFD_SEND_DATAGRAM_INFO
template <typename Traits>
struct AFD_SEND_DATAGRAM_INFO
{
LPWSABUF BufferArray;
EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray;
ULONG BufferCount;
ULONG AfdFlags;
TDI_REQUEST_SEND_DATAGRAM TdiRequest;
TDI_CONNECTION_INFORMATION TdiConnInfo;
} AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO;
TDI_REQUEST_SEND_DATAGRAM<Traits> TdiRequest;
TDI_CONNECTION_INFORMATION<Traits> TdiConnInfo;
};
typedef struct _AFD_RECV_INFO
template <typename Traits>
struct AFD_RECV_INFO
{
LPWSABUF BufferArray;
EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray;
ULONG BufferCount;
ULONG AfdFlags;
ULONG TdiFlags;
} AFD_RECV_INFO, *PAFD_RECV_INFO;
};
typedef struct _AFD_RECV_DATAGRAM_INFO
template <typename Traits>
struct AFD_RECV_DATAGRAM_INFO
{
LPWSABUF BufferArray;
EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray;
ULONG BufferCount;
ULONG AfdFlags;
ULONG TdiFlags;
PVOID Address;
PULONG AddressLength;
} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO;
typename Traits::PVOID Address;
EMULATOR_CAST(typename Traits::PVOID, PULONG) AddressLength;
};
typedef struct _AFD_POLL_HANDLE_INFO
struct AFD_POLL_HANDLE_INFO64
{
HANDLE Handle;
EmulatorTraits<Emu64>::HANDLE Handle;
ULONG PollEvents;
NTSTATUS Status;
} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
};
typedef struct _AFD_POLL_INFO
struct AFD_POLL_INFO64
{
LARGE_INTEGER Timeout;
ULONG NumberOfHandles;
BOOLEAN Unique;
AFD_POLL_HANDLE_INFO Handles[1];
} AFD_POLL_INFO, *PAFD_POLL_INFO;
AFD_POLL_HANDLE_INFO64 Handles[1];
};
#define AFD_POLL_RECEIVE_BIT 0
#define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT)

View File

@@ -31,11 +31,12 @@ struct handle_value
static_assert(sizeof(handle_value) == 8);
// TODO: this is a concrete 64bit handle
union handle
{
handle_value value;
uint64_t bits;
HANDLE h;
std::uint64_t h;
};
inline void serialize(utils::buffer_serializer& buffer, const handle& h)

View File

@@ -12,7 +12,7 @@ namespace
};
}
std::unique_ptr<io_device<EmulatorTraits<Emu64>>> create_device64(const std::u16string_view device)
std::unique_ptr<io_device> create_device(const std::u16string_view device)
{
if (device == u"CNG"
|| device == u"KsecDD"
@@ -27,5 +27,5 @@ std::unique_ptr<io_device<EmulatorTraits<Emu64>>> create_device64(const std::u16
return create_afd_endpoint();
}
throw std::runtime_error("Unsupported device: " + std::string(device.begin(), device.end()));
throw std::runtime_error("Unsupported device: " + u16_to_u8(device));
}

View File

@@ -15,7 +15,7 @@ struct io_device_context
handle event{};
emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine{};
emulator_pointer apc_context{};
emulator_object<IO_STATUS_BLOCK> io_status_block;
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block;
ULONG io_control_code{};
emulator_pointer input_buffer{};
ULONG input_buffer_length{};
@@ -65,11 +65,11 @@ struct io_device_creation_data
uint32_t length;
};
inline void write_io_status(const emulator_object<IO_STATUS_BLOCK> io_status_block, const NTSTATUS status)
inline void write_io_status(const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const NTSTATUS status)
{
if (io_status_block)
{
io_status_block.access([&](IO_STATUS_BLOCK& status_block)
io_status_block.access([&](IO_STATUS_BLOCK<EmulatorTraits<Emu64>>& status_block)
{
status_block.Status = status;
});
@@ -131,14 +131,14 @@ struct stateless_device : io_device
}
};
std::unique_ptr<io_device> create_device(std::wstring_view device);
std::unique_ptr<io_device> create_device(std::u16string_view device);
class io_device_container : public io_device
{
public:
io_device_container() = default;
io_device_container(std::wstring device, windows_emulator& win_emu, const io_device_creation_data& data)
io_device_container(std::u16string device, windows_emulator& win_emu, const io_device_creation_data& data)
: device_name_(std::move(device))
{
this->setup();
@@ -182,7 +182,7 @@ public:
}
private:
std::wstring device_name_{};
std::u16string device_name_{};
std::unique_ptr<io_device> device_{};
void setup()

View File

@@ -5,12 +5,12 @@
#include <address_utils.hpp>
constexpr auto KUSD_ADDRESS = 0x7ffe0000ULL;
constexpr auto KUSD_SIZE = sizeof(KUSER_SHARED_DATA);
constexpr auto KUSD_SIZE = sizeof(KUSER_SHARED_DATA64);
constexpr auto KUSD_BUFFER_SIZE = page_align_up(KUSD_SIZE);
namespace
{
void setup_kusd(KUSER_SHARED_DATA& kusd, const bool use_relative_time)
void setup_kusd(KUSER_SHARED_DATA64& kusd, const bool use_relative_time)
{
memset(&kusd, 0, sizeof(kusd));
@@ -88,13 +88,13 @@ namespace
}
}
inline void serialize(utils::buffer_serializer& buffer, const KUSER_SHARED_DATA& kusd)
inline void serialize(utils::buffer_serializer& buffer, const KUSER_SHARED_DATA64& kusd)
{
static_assert(KUSD_SIZE == sizeof(kusd));
buffer.write(&kusd, KUSD_SIZE);
}
inline void deserialize(utils::buffer_deserializer& buffer, KUSER_SHARED_DATA& kusd)
inline void deserialize(utils::buffer_deserializer& buffer, KUSER_SHARED_DATA64& kusd)
{
buffer.read(&kusd, KUSD_SIZE);
}

View File

@@ -24,12 +24,12 @@ public:
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);
KUSER_SHARED_DATA& get()
KUSER_SHARED_DATA64& get()
{
return this->kusd_;
}
const KUSER_SHARED_DATA& get() const
const KUSER_SHARED_DATA64& get() const
{
return this->kusd_;
}
@@ -45,7 +45,7 @@ private:
bool registered_{};
bool use_relative_time_{};
KUSER_SHARED_DATA kusd_{};
KUSER_SHARED_DATA64 kusd_{};
std::chrono::system_clock::time_point start_time_{};
uint64_t read(uint64_t addr, size_t size);

View File

@@ -7,9 +7,14 @@
namespace
{
uint64_t get_first_section_offset(const IMAGE_NT_HEADERS& nt_headers, const uint64_t nt_headers_offset)
uint64_t get_first_section_offset(const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
{
const auto first_section_absolute = reinterpret_cast<uint64_t>(IMAGE_FIRST_SECTION(&nt_headers));
const uint8_t* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
size_t optional_header_offset = reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<uintptr_t>(&nt_headers);
size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader;
const uint8_t* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size;
const auto first_section_absolute = reinterpret_cast<uint64_t>(first_section_addr);
const auto absolute_base = reinterpret_cast<uint64_t>(&nt_headers);
return nt_headers_offset + (first_section_absolute - absolute_base);
}
@@ -24,7 +29,7 @@ namespace
}
void collect_exports(mapped_module& binary, const utils::safe_buffer_accessor<const uint8_t> buffer,
const IMAGE_OPTIONAL_HEADER& optional_header)
const PEOptionalHeader_t<std::uint64_t>& optional_header)
{
auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0)
@@ -71,7 +76,7 @@ namespace
}
void apply_relocations(const mapped_module& binary, const utils::safe_buffer_accessor<uint8_t> buffer,
const IMAGE_OPTIONAL_HEADER& optional_header)
const PEOptionalHeader_t<std::uint64_t>& optional_header)
{
const auto delta = binary.image_base - optional_header.ImageBase;
if (delta == 0)
@@ -134,7 +139,7 @@ namespace
void map_sections(emulator& emu, const mapped_module& binary,
const utils::safe_buffer_accessor<const uint8_t> buffer,
const IMAGE_NT_HEADERS& nt_headers, const uint64_t nt_headers_offset)
const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
{
const auto first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset);
const auto sections = buffer.as<IMAGE_SECTION_HEADER>(first_section_offset);
@@ -183,10 +188,10 @@ namespace
utils::safe_buffer_accessor buffer{data};
const auto dos_header = buffer.as<IMAGE_DOS_HEADER>(0).get();
const auto dos_header = buffer.as<PEDosHeader_t>(0).get();
const auto nt_headers_offset = dos_header.e_lfanew;
const auto nt_headers = buffer.as<IMAGE_NT_HEADERS>(nt_headers_offset).get();
const auto nt_headers = buffer.as<PENTHeaders_t<std::uint64_t>>(nt_headers_offset).get();
auto& optional_header = nt_headers.OptionalHeader;
binary.image_base = optional_header.ImageBase;

View File

@@ -229,7 +229,7 @@ public:
std::optional<NTSTATUS> pending_status{};
std::optional<emulator_allocator> gs_segment;
std::optional<emulator_object<TEB>> teb;
std::optional<emulator_object<TEB64>> teb;
std::vector<std::byte> last_registers{};
@@ -325,7 +325,7 @@ public:
buffer.read_optional(this->await_time);
buffer.read_optional(this->pending_status);
buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->emu_ptr); });
buffer.read_optional(this->teb, [this] { return emulator_object<TEB>(*this->emu_ptr); });
buffer.read_optional(this->teb, [this] { return emulator_object<TEB64>(*this->emu_ptr); });
buffer.read_vector(this->last_registers);
}
@@ -381,8 +381,8 @@ struct process_context
emulator_allocator base_allocator;
emulator_object<PEB> peb;
emulator_object<RTL_USER_PROCESS_PARAMETERS> process_params;
emulator_object<PEB64> peb;
emulator_object<RTL_USER_PROCESS_PARAMETERS64> process_params;
kusd_mmio kusd;
module_manager module_manager;

View File

@@ -161,12 +161,12 @@ syscall_handler make_syscall_handler()
};
}
template <typename T>
void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& value)
template <typename T, typename Traits>
void write_attribute(emulator& emu, const PS_ATTRIBUTE<Traits>& attribute, const T& value)
{
if (attribute.ReturnLength)
{
emulator_object<SIZE_T>{emu, attribute.ReturnLength}.write(sizeof(T));
emulator_object<typename Traits::SIZE_T>{emu, attribute.ReturnLength}.write(sizeof(T));
}
if (attribute.Size >= sizeof(T))

View File

@@ -5,7 +5,9 @@
#include "syscall_utils.hpp"
#include <numeric>
#include <ranges>
#include <cwctype>
#include <algorithm>
#include <utils/io.hpp>
#include "utils/finally.hpp"
@@ -61,14 +63,14 @@ namespace
NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object<handle> key_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
auto key = read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
if (attributes.RootDirectory)
{
const auto* parent_handle = c.proc.registry_keys.get(reinterpret_cast<uint64_t>(attributes.RootDirectory));
const auto* parent_handle = c.proc.registry_keys.get(attributes.RootDirectory);
if (!parent_handle)
{
return STATUS_INVALID_HANDLE;
@@ -95,7 +97,7 @@ namespace
NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, const emulator_object<handle> key_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
ULONG /*open_options*/)
{
return handle_NtOpenKey(c, key_handle, desired_access, object_attributes);
@@ -180,9 +182,8 @@ namespace
}
const auto query_name = read_unicode_string(c.emu, value_name);
const std::string name(query_name.begin(), query_name.end());
const auto value = c.proc.registry.get_value(*key, name);
const auto value = c.proc.registry.get_value(*key, u16_to_u8(query_name));
if (!value)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
@@ -313,12 +314,12 @@ namespace
if (info_class == ThreadNameInformation)
{
if (thread_information_length != sizeof(THREAD_NAME_INFORMATION))
if (thread_information_length != sizeof(THREAD_NAME_INFORMATION<EmulatorTraits<Emu64>>))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<THREAD_NAME_INFORMATION> info{c.emu, thread_information};
const emulator_object<THREAD_NAME_INFORMATION<EmulatorTraits<Emu64>>> info{c.emu, thread_information};
const auto i = info.read();
thread->name = read_unicode_string(c.emu, i.ThreadName);
@@ -403,7 +404,7 @@ namespace
NTSTATUS handle_NtCreateEvent(const syscall_context& c, const emulator_object<handle> event_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const EVENT_TYPE event_type, const BOOLEAN initial_state)
{
std::u16string name{};
@@ -432,7 +433,7 @@ namespace
NTSTATUS handle_NtOpenEvent(const syscall_context& c, const emulator_object<uint64_t> event_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto name = read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
@@ -482,20 +483,20 @@ namespace
NTSTATUS handle_NtOpenSection(const syscall_context& c, const emulator_object<handle> section_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
auto filename = read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
c.win_emu.logger.print(color::gray, "Opening section: %S\n", filename.c_str());
if (filename == L"\\Windows\\SharedSection")
if (filename == u"\\Windows\\SharedSection")
{
section_handle.write(SHARED_SECTION);
return STATUS_SUCCESS;
}
if (reinterpret_cast<uint64_t>(attributes.RootDirectory) != KNOWN_DLLS_DIRECTORY)
if (attributes.RootDirectory != KNOWN_DLLS_DIRECTORY)
{
puts("Unsupported section");
c.emu.stop();
@@ -519,9 +520,9 @@ namespace
NTSTATUS handle_NtMapViewOfSection(const syscall_context& c, const handle section_handle,
const handle process_handle, const emulator_object<uint64_t> base_address,
const ULONG_PTR /*zero_bits*/, const SIZE_T /*commit_size*/,
const EMULATOR_CAST(EmulatorTraits<Emu64>::ULONG_PTR, ULONG_PTR) /*zero_bits*/, const EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T) /*commit_size*/,
const emulator_object<LARGE_INTEGER> /*section_offset*/,
const emulator_object<SIZE_T> view_size,
const emulator_object<EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T)> view_size,
const SECTION_INHERIT /*inherit_disposition*/, const ULONG /*allocation_type*/,
const ULONG /*win32_protect*/)
{
@@ -547,7 +548,7 @@ namespace
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> windir_obj{c.emu, obj_address};
windir_obj.access([&](UNICODE_STRING<EmulatorTraits<Emu64>>& ucs)
{
const auto dir_address = kusd_mmio::address() + offsetof(KUSER_SHARED_DATA, NtSystemRoot);
const auto dir_address = kusd_mmio::address() + offsetof(KUSER_SHARED_DATA64, NtSystemRoot);
ucs.Buffer = dir_address - obj_address;
ucs.Length = static_cast<uint16_t>(windows_dir_size);
@@ -597,7 +598,7 @@ namespace
NTSTATUS handle_NtCreateIoCompletion(const syscall_context& c, const emulator_object<handle> event_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const uint32_t /*number_of_concurrent_threads*/)
{
return handle_NtCreateEvent(c, event_handle, desired_access, object_attributes, NotificationEvent, FALSE);
@@ -605,7 +606,7 @@ namespace
NTSTATUS handle_NtCreateWaitCompletionPacket(const syscall_context& c, const emulator_object<handle> event_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
return handle_NtCreateEvent(c, event_handle, desired_access, object_attributes, NotificationEvent, FALSE);
}
@@ -630,17 +631,17 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(MEMORY_BASIC_INFORMATION));
return_length.write(sizeof(EMU_MEMORY_BASIC_INFORMATION64));
}
if (memory_information_length != sizeof(MEMORY_BASIC_INFORMATION))
if (memory_information_length != sizeof(EMU_MEMORY_BASIC_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<MEMORY_BASIC_INFORMATION> info{c.emu, memory_information};
const emulator_object<EMU_MEMORY_BASIC_INFORMATION64> info{c.emu, memory_information};
info.access([&](MEMORY_BASIC_INFORMATION& image_info)
info.access([&](EMU_MEMORY_BASIC_INFORMATION64& image_info)
{
const auto region_info = c.emu.get_region_info(base_address);
@@ -667,10 +668,10 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(MEMORY_IMAGE_INFORMATION));
return_length.write(sizeof(MEMORY_IMAGE_INFORMATION64));
}
if (memory_information_length != sizeof(MEMORY_IMAGE_INFORMATION))
if (memory_information_length != sizeof(MEMORY_IMAGE_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
}
@@ -678,13 +679,13 @@ namespace
const auto mod = c.proc.module_manager.find_by_address(base_address);
if (!mod)
{
printf("Bad address for memory image request: 0x%llX\n", base_address);
printf("Bad address for memory image request: 0x%zX\n", base_address);
return STATUS_INVALID_ADDRESS;
}
const emulator_object<MEMORY_IMAGE_INFORMATION> info{c.emu, memory_information};
const emulator_object<MEMORY_IMAGE_INFORMATION64> info{c.emu, memory_information};
info.access([&](MEMORY_IMAGE_INFORMATION& image_info)
info.access([&](MEMORY_IMAGE_INFORMATION64& image_info)
{
image_info.ImageBase = reinterpret_cast<void*>(mod->image_base);
image_info.SizeOfImage = mod->size_of_image;
@@ -697,10 +698,10 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(MEMORY_REGION_INFORMATION));
return_length.write(sizeof(MEMORY_REGION_INFORMATION64));
}
if (memory_information_length != sizeof(MEMORY_REGION_INFORMATION))
if (memory_information_length != sizeof(MEMORY_REGION_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
}
@@ -711,9 +712,9 @@ namespace
return STATUS_INVALID_ADDRESS;
}
const emulator_object<MEMORY_REGION_INFORMATION> info{c.emu, memory_information};
const emulator_object<MEMORY_REGION_INFORMATION64> info{c.emu, memory_information};
info.access([&](MEMORY_REGION_INFORMATION& image_info)
info.access([&](MEMORY_REGION_INFORMATION64& image_info)
{
memset(&image_info, 0, sizeof(image_info));
@@ -749,17 +750,17 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
return_length.write(sizeof(SYSTEM_TIMEOFDAY_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
if (system_information_length != sizeof(SYSTEM_TIMEOFDAY_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_TIMEOFDAY_INFORMATION> info_obj{c.emu, system_information};
const emulator_object<SYSTEM_TIMEOFDAY_INFORMATION64> info_obj{c.emu, system_information};
info_obj.access([&](SYSTEM_TIMEOFDAY_INFORMATION& info)
info_obj.access([&](SYSTEM_TIMEOFDAY_INFORMATION64& info)
{
info.BootTime.QuadPart = 0;
// TODO: Fill
@@ -772,17 +773,17 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(SYSTEM_RANGE_START_INFORMATION));
return_length.write(sizeof(SYSTEM_RANGE_START_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_RANGE_START_INFORMATION))
if (system_information_length != sizeof(SYSTEM_RANGE_START_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_RANGE_START_INFORMATION> info_obj{c.emu, system_information};
const emulator_object<SYSTEM_RANGE_START_INFORMATION64> info_obj{c.emu, system_information};
info_obj.access([&](SYSTEM_RANGE_START_INFORMATION& info)
info_obj.access([&](SYSTEM_RANGE_START_INFORMATION64& info)
{
info.SystemRangeStart = 0xFFFF800000000000;
});
@@ -794,17 +795,17 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(SYSTEM_PROCESSOR_INFORMATION));
return_length.write(sizeof(SYSTEM_PROCESSOR_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_PROCESSOR_INFORMATION))
if (system_information_length != sizeof(SYSTEM_PROCESSOR_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_PROCESSOR_INFORMATION> info_obj{c.emu, system_information};
const emulator_object<SYSTEM_PROCESSOR_INFORMATION64> info_obj{c.emu, system_information};
info_obj.access([&](SYSTEM_PROCESSOR_INFORMATION& info)
info_obj.access([&](SYSTEM_PROCESSOR_INFORMATION64& info)
{
memset(&info, 0, sizeof(info));
info.MaximumProcessors = 2;
@@ -818,17 +819,17 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(SYSTEM_NUMA_INFORMATION));
return_length.write(sizeof(SYSTEM_NUMA_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_NUMA_INFORMATION))
if (system_information_length != sizeof(SYSTEM_NUMA_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_NUMA_INFORMATION> info_obj{c.emu, system_information};
const emulator_object<SYSTEM_NUMA_INFORMATION64> info_obj{c.emu, system_information};
info_obj.access([&](SYSTEM_NUMA_INFORMATION& info)
info_obj.access([&](SYSTEM_NUMA_INFORMATION64& info)
{
memset(&info, 0, sizeof(info));
info.ActiveProcessorsGroupAffinity->Mask = 0xFFF;
@@ -871,17 +872,17 @@ namespace
if (return_length)
{
return_length.write(sizeof(SYSTEM_BASIC_INFORMATION));
return_length.write(sizeof(SYSTEM_BASIC_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION))
if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_BASIC_INFORMATION> info{c.emu, system_information};
const emulator_object<SYSTEM_BASIC_INFORMATION64> info{c.emu, system_information};
info.access([&](SYSTEM_BASIC_INFORMATION& basic_info)
info.access([&](SYSTEM_BASIC_INFORMATION64& basic_info)
{
basic_info.Reserved = 0;
basic_info.TimerResolution = 0x0002625a;
@@ -944,10 +945,15 @@ namespace
return_length.access([&](uint32_t& len)
{
#ifdef OS_WINDOWS
code = NtQuerySystemInformationEx(static_cast<SYSTEM_INFORMATION_CLASS>(info_class), buffer,
input_buffer_length,
res_buff,
system_information_length, reinterpret_cast<ULONG*>(&len));
#else
// TODO: unsupported
code = STATUS_SUCCESS;
#endif
});
if (code == 0)
@@ -970,17 +976,17 @@ namespace
if (return_length)
{
return_length.write(sizeof(SYSTEM_BASIC_INFORMATION));
return_length.write(sizeof(SYSTEM_BASIC_INFORMATION64));
}
if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION))
if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION64))
{
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<SYSTEM_BASIC_INFORMATION> info{c.emu, system_information};
const emulator_object<SYSTEM_BASIC_INFORMATION64> info{c.emu, system_information};
info.access([&](SYSTEM_BASIC_INFORMATION& basic_info)
info.access([&](SYSTEM_BASIC_INFORMATION64& basic_info)
{
basic_info.Reserved = 0;
basic_info.TimerResolution = 0x0002625a;
@@ -1011,29 +1017,29 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(SECTION_IMAGE_INFORMATION));
return_length.write(sizeof(SECTION_IMAGE_INFORMATION<EmulatorTraits<Emu64>>));
}
if (process_information_length != sizeof(SECTION_IMAGE_INFORMATION))
if (process_information_length != sizeof(SECTION_IMAGE_INFORMATION<EmulatorTraits<Emu64>>))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<SECTION_IMAGE_INFORMATION> info{c.emu, process_information};
info.access([&](SECTION_IMAGE_INFORMATION& i)
const emulator_object<SECTION_IMAGE_INFORMATION<EmulatorTraits<Emu64>>> info{c.emu, process_information};
info.access([&](SECTION_IMAGE_INFORMATION<EmulatorTraits<Emu64>>& i)
{
const auto& mod = *c.proc.executable;
const emulator_object<IMAGE_DOS_HEADER> dos_header_obj{c.emu, mod.image_base};
const emulator_object<PEDosHeader_t> dos_header_obj{c.emu, mod.image_base};
const auto dos_header = dos_header_obj.read();
const emulator_object<IMAGE_NT_HEADERS> nt_headers_obj{c.emu, mod.image_base + dos_header.e_lfanew};
const emulator_object<PENTHeaders_t<uint64_t>> nt_headers_obj{c.emu, mod.image_base + dos_header.e_lfanew};
const auto nt_headers = nt_headers_obj.read();
const auto& file_header = nt_headers.FileHeader;
const auto& optional_header = nt_headers.OptionalHeader;
i.TransferAddress = nullptr;
i.TransferAddress = 0;
i.MaximumStackSize = optional_header.SizeOfStackReserve;
i.CommittedStackSize = optional_header.SizeOfStackCommit;
i.SubSystemType = optional_header.Subsystem;
@@ -1076,15 +1082,15 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(DWORD_PTR));
return_length.write(sizeof(EmulatorTraits<Emu64>::PVOID));
}
if (process_information_length != sizeof(DWORD_PTR))
if (process_information_length != sizeof(EmulatorTraits<Emu64>::PVOID))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<DWORD_PTR> info{c.emu, process_information};
const emulator_object<EmulatorTraits<Emu64>::PVOID> info{c.emu, process_information};
info.write(0);
return STATUS_SUCCESS;
@@ -1118,19 +1124,19 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(PROCESS_BASIC_INFORMATION));
return_length.write(sizeof(PROCESS_BASIC_INFORMATION64));
}
if (process_information_length != sizeof(PROCESS_BASIC_INFORMATION))
if (process_information_length != sizeof(PROCESS_BASIC_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<PROCESS_BASIC_INFORMATION> info{c.emu, process_information};
info.access([&](PROCESS_BASIC_INFORMATION& basic_info)
const emulator_object<PROCESS_BASIC_INFORMATION64> info{c.emu, process_information};
info.access([&](PROCESS_BASIC_INFORMATION64& basic_info)
{
basic_info.PebBaseAddress = c.proc.peb.ptr();
basic_info.UniqueProcessId = reinterpret_cast<HANDLE>(1);
basic_info.UniqueProcessId = 1;
});
return STATUS_SUCCESS;
@@ -1139,7 +1145,7 @@ namespace
if (info_class == ProcessImageFileNameWin32)
{
const auto peb = c.proc.peb.read();
emulator_object<RTL_USER_PROCESS_PARAMETERS> proc_params{c.emu, peb.ProcessParameters};
emulator_object<RTL_USER_PROCESS_PARAMETERS64> proc_params{c.emu, peb.ProcessParameters};
const auto params = proc_params.read();
const auto length = params.ImagePathName.Length + sizeof(UNICODE_STRING<EmulatorTraits<Emu64>>) + 2;
@@ -1153,10 +1159,10 @@ namespace
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<UNICODE_STRING> info{c.emu, process_information};
info.access([&](UNICODE_STRING& str)
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> info{c.emu, process_information};
info.access([&](UNICODE_STRING<EmulatorTraits<Emu64>>& str)
{
const auto buffer_start = static_cast<uint64_t>(process_information) + sizeof(UNICODE_STRING);
const auto buffer_start = static_cast<uint64_t>(process_information) + sizeof(UNICODE_STRING<EmulatorTraits<Emu64>>);
const auto string = read_unicode_string(c.emu, params.ImagePathName);
c.emu.write_memory(buffer_start, string.c_str(), (string.size() + 1) * 2);
str.Length = params.ImagePathName.Length;
@@ -1187,16 +1193,16 @@ namespace
{
if (return_length)
{
return_length.write(sizeof(THREAD_BASIC_INFORMATION));
return_length.write(sizeof(THREAD_BASIC_INFORMATION64));
}
if (thread_information_length != sizeof(THREAD_BASIC_INFORMATION))
if (thread_information_length != sizeof(THREAD_BASIC_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<THREAD_BASIC_INFORMATION> info{c.emu, thread_information};
info.access([&](THREAD_BASIC_INFORMATION& i)
const emulator_object<THREAD_BASIC_INFORMATION64> info{c.emu, thread_information};
info.access([&](THREAD_BASIC_INFORMATION64& i)
{
i.TebBaseAddress = c.win_emu.current_thread().teb->ptr();
i.ClientId = c.win_emu.current_thread().teb->read().ClientId;
@@ -1230,7 +1236,7 @@ namespace
}
NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const uint64_t file_information,
const ULONG length, const FILE_INFORMATION_CLASS info_class)
{
@@ -1249,7 +1255,7 @@ namespace
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = sizeof(FILE_POSITION_INFORMATION);
io_status_block.write(block);
}
@@ -1277,7 +1283,7 @@ namespace
}
NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, const handle file_handle,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const uint64_t file_information, const uint32_t length,
const uint32_t info_class)
{
@@ -1291,7 +1297,7 @@ namespace
{
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = sizeof(FILE_STANDARD_INFORMATION);
io_status_block.write(block);
}
@@ -1324,7 +1330,7 @@ namespace
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = sizeof(FILE_POSITION_INFORMATION);
io_status_block.write(block);
}
@@ -1425,12 +1431,12 @@ namespace
NTSTATUS handle_NtOpenDirectoryObject(const syscall_context& c,
const emulator_object<handle> directory_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto object_name = read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
if (object_name == L"\\KnownDlls")
if (object_name == u"\\KnownDlls")
{
directory_handle.write(KNOWN_DLLS_DIRECTORY);
return STATUS_SUCCESS;
@@ -1441,12 +1447,12 @@ namespace
NTSTATUS handle_NtOpenSymbolicLinkObject(const syscall_context& c, const emulator_object<handle> link_handle,
ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto object_name = read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
if (object_name == L"KnownDllPath")
if (object_name == u"KnownDllPath")
{
link_handle.write(KNOWN_DLLS_SYMLINK);
return STATUS_SUCCESS;
@@ -1455,8 +1461,9 @@ namespace
return STATUS_NOT_SUPPORTED;
}
// TODO: warning stdcall problem
NTSTATUS WINAPI handle_NtQuerySymbolicLinkObject(const syscall_context& c, const handle link_handle,
const emulator_object<UNICODE_STRING> link_target,
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> link_target,
const emulator_object<ULONG> returned_length)
{
if (link_handle == KNOWN_DLLS_SYMLINK)
@@ -1477,7 +1484,7 @@ namespace
}
str.Length = str_length;
c.emu.write_memory(reinterpret_cast<uint64_t>(str.Buffer), system32.data(), max_length);
c.emu.write_memory(str.Buffer, system32.data(), max_length);
});
return too_small
@@ -1576,7 +1583,7 @@ namespace
NTSTATUS handle_NtCreateSection(const syscall_context& c, const emulator_object<handle> section_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> /*object_attributes*/,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> /*object_attributes*/,
const emulator_object<ULARGE_INTEGER> maximum_size,
const ULONG /*section_page_protection*/, const ULONG /*allocation_attributes*/,
const handle /*file_handle*/)
@@ -1596,8 +1603,8 @@ namespace
NTSTATUS handle_NtConnectPort(const syscall_context& c, const emulator_object<handle> client_port_handle,
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
const emulator_object<SECURITY_QUALITY_OF_SERVICE> /*security_qos*/,
const emulator_object<PORT_VIEW> client_shared_memory,
const emulator_object<REMOTE_PORT_VIEW> /*server_shared_memory*/,
const emulator_object<PORT_VIEW64> client_shared_memory,
const emulator_object<REMOTE_PORT_VIEW64> /*server_shared_memory*/,
const emulator_object<ULONG> /*maximum_message_length*/,
const emulator_pointer connection_info,
const emulator_object<ULONG> connection_info_length)
@@ -1615,10 +1622,10 @@ namespace
c.emu.write_memory(connection_info, zero_mem.data(), zero_mem.size());
}
client_shared_memory.access([&](PORT_VIEW& view)
client_shared_memory.access([&](PORT_VIEW64& view)
{
p.view_base = c.emu.allocate_memory(view.ViewSize, memory_permission::read_write);
view.ViewBase = reinterpret_cast<void*>(p.view_base);
view.ViewBase = p.view_base;
view.ViewRemoteBase = view.ViewBase;
});
@@ -1657,7 +1664,7 @@ namespace
const handle event,
const emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine,
const emulator_pointer apc_context,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const ULONG io_control_code,
const emulator_pointer input_buffer,
const ULONG input_buffer_length, const emulator_pointer output_buffer,
@@ -1751,11 +1758,11 @@ namespace
return STATUS_BUFFER_TOO_SMALL;
}
TOKEN_USER user{};
TOKEN_USER64 user{};
user.User.Attributes = 0;
user.User.Sid = reinterpret_cast<void*>(token_information + 0x10);
user.User.Sid = token_information + 0x10;
emulator_object<TOKEN_USER>{c.emu, token_information}.write(user);
emulator_object<TOKEN_USER64>{c.emu, token_information}.write(user);
c.emu.write_memory(token_information + 0x10, sid, sizeof(sid));
return STATUS_SUCCESS;
}
@@ -1774,7 +1781,7 @@ namespace
return STATUS_SUCCESS;
}
printf("Unsupported token info class: %lX\n", token_information_class);
printf("Unsupported token info class: %X\n", token_information_class);
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
@@ -1798,11 +1805,11 @@ namespace
NTSTATUS handle_NtGdiInit2(const syscall_context& c)
{
c.proc.peb.access([&](PEB& peb)
c.proc.peb.access([&](PEB64& peb)
{
if (!peb.GdiSharedHandleTable)
{
peb.GdiSharedHandleTable = c.proc.base_allocator.reserve<GDI_SHARED_MEMORY>().ptr();
peb.GdiSharedHandleTable = reinterpret_cast<EmulatorTraits<Emu64>::PVOID*>(c.proc.base_allocator.reserve<GDI_SHARED_MEMORY64>().ptr());
}
});
@@ -1841,12 +1848,12 @@ namespace
NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, const handle port_handle,
const ULONG /*flags*/,
const emulator_object<PORT_MESSAGE> /*send_message*/,
const emulator_object<PORT_MESSAGE64> /*send_message*/,
const emulator_object<ALPC_MESSAGE_ATTRIBUTES>
/*send_message_attributes*/
,
const emulator_object<PORT_MESSAGE> receive_message,
const emulator_object<SIZE_T> /*buffer_length*/,
const emulator_object<PORT_MESSAGE64> receive_message,
const emulator_object<EmulatorTraits<Emu64>::SIZE_T> /*buffer_length*/,
const emulator_object<ALPC_MESSAGE_ATTRIBUTES>
/*receive_message_attributes*/,
const emulator_object<LARGE_INTEGER> /*timeout*/)
@@ -1863,9 +1870,9 @@ namespace
return STATUS_NOT_SUPPORTED;
}
const emulator_object<PORT_DATA_ENTRY> data{c.emu, receive_message.value() + 0x48};
const emulator_object<PORT_DATA_ENTRY<EmulatorTraits<Emu64>>> data{c.emu, receive_message.value() + 0x48};
const auto dest = data.read();
const auto base = reinterpret_cast<uint64_t>(dest.Base);
const auto base = dest.Base;
const auto value = base + 0x10;
c.emu.write_memory(base + 8, &value, sizeof(value));
@@ -1893,7 +1900,7 @@ namespace
return STATUS_SUCCESS;
}
NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object<CONTEXT> thread_context,
NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object<CONTEXT64> thread_context,
const BOOLEAN /*raise_alert*/)
{
c.write_status = false;
@@ -1933,7 +1940,7 @@ namespace
NTSTATUS handle_NtReadFile(const syscall_context& c, const handle file_handle, const uint64_t /*event*/,
const uint64_t /*apc_routine*/,
const uint64_t /*apc_context*/,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
uint64_t buffer, const ULONG length,
const emulator_object<LARGE_INTEGER> /*byte_offset*/,
const emulator_object<ULONG> /*key*/)
@@ -1951,7 +1958,7 @@ namespace
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = bytes_read;
io_status_block.write(block);
}
@@ -1963,7 +1970,7 @@ namespace
NTSTATUS handle_NtWriteFile(const syscall_context& c, const handle file_handle, const uint64_t /*event*/,
const uint64_t /*apc_routine*/,
const uint64_t /*apc_context*/,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
uint64_t buffer, const ULONG length,
const emulator_object<LARGE_INTEGER> /*byte_offset*/,
const emulator_object<ULONG> /*key*/)
@@ -1977,7 +1984,7 @@ namespace
{
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = length;
io_status_block.write(block);
}
@@ -2003,7 +2010,7 @@ namespace
if (io_status_block)
{
IO_STATUS_BLOCK block{};
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = bytes_written;
io_status_block.write(block);
}
@@ -2060,8 +2067,8 @@ namespace
NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object<handle> file_handle,
ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<IO_STATUS_BLOCK> /*io_status_block*/,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/,
const emulator_object<LARGE_INTEGER> /*allocation_size*/, ULONG /*file_attributes*/,
ULONG /*share_access*/, ULONG create_disposition, ULONG create_options,
uint64_t ea_buffer,
@@ -2093,7 +2100,7 @@ namespace
}
handle root_handle{};
root_handle.bits = reinterpret_cast<uint64_t>(attributes.RootDirectory);
root_handle.bits = attributes.RootDirectory;
if (root_handle.value.is_pseudo && (filename == u"\\Reference" || filename == u"\\Connect"))
{
file_handle.write(root_handle);
@@ -2105,7 +2112,7 @@ namespace
if (attributes.RootDirectory)
{
const auto* root = c.proc.files.get(reinterpret_cast<uint64_t>(attributes.RootDirectory));
const auto* root = c.proc.files.get(attributes.RootDirectory);
if (!root)
{
return STATUS_INVALID_HANDLE;
@@ -2181,8 +2188,8 @@ namespace
NTSTATUS handle_NtOpenFile(const syscall_context& c,
const emulator_object<handle> file_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<IO_STATUS_BLOCK> io_status_block,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const ULONG share_access,
const ULONG open_options)
{
@@ -2234,8 +2241,8 @@ namespace
}
NTSTATUS handle_NtRaiseException(const syscall_context& c,
const emulator_object<EXCEPTION_RECORD> /*exception_record*/,
const emulator_object<CONTEXT> thread_context, BOOLEAN handle_exception)
const emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> /*exception_record*/,
const emulator_object<CONTEXT64> thread_context, BOOLEAN handle_exception)
{
if (handle_exception)
{
@@ -2252,7 +2259,7 @@ namespace
NTSTATUS handle_NtCreateSemaphore(const syscall_context& c, const emulator_object<handle> semaphore_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const ULONG initial_count, const ULONG maximum_count)
{
semaphore s{};
@@ -2350,11 +2357,11 @@ namespace
NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, const emulator_object<handle> thread_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> /*object_attributes*/,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> /*object_attributes*/,
const handle process_handle, const uint64_t start_routine,
const uint64_t argument, const ULONG /*create_flags*/, const SIZE_T /*zero_bits*/,
const SIZE_T stack_size, const SIZE_T /*maximum_stack_size*/,
const emulator_object<PS_ATTRIBUTE_LIST> attribute_list)
const uint64_t argument, const ULONG /*create_flags*/, const EmulatorTraits<Emu64>::SIZE_T /*zero_bits*/,
const EmulatorTraits<Emu64>::SIZE_T stack_size, const EmulatorTraits<Emu64>::SIZE_T /*maximum_stack_size*/,
const emulator_object<PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>> attribute_list)
{
if (process_handle != ~0ULL)
{
@@ -2371,19 +2378,19 @@ namespace
const auto* thread = c.proc.threads.get(h);
const emulator_object<PS_ATTRIBUTE> attributes{
c.emu, attribute_list.value() + offsetof(PS_ATTRIBUTE_LIST, Attributes)
const emulator_object<PS_ATTRIBUTE<EmulatorTraits<Emu64>>> attributes{
c.emu, attribute_list.value() + offsetof(PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>, Attributes)
};
const auto total_length = attribute_list.read().TotalLength;
constexpr auto entry_size = sizeof(PS_ATTRIBUTE);
constexpr auto header_size = sizeof(PS_ATTRIBUTE_LIST) - entry_size;
constexpr auto entry_size = sizeof(PS_ATTRIBUTE<EmulatorTraits<Emu64>>);
constexpr auto header_size = sizeof(PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>) - entry_size;
const auto attribute_count = (total_length - header_size) / entry_size;
for (size_t i = 0; i < attribute_count; ++i)
{
attributes.access([&](const PS_ATTRIBUTE& attribute)
attributes.access([&](const PS_ATTRIBUTE<EmulatorTraits<Emu64>>& attribute)
{
const auto type = attribute.Attribute & ~PS_ATTRIBUTE_THREAD;
@@ -2398,7 +2405,7 @@ namespace
}
else
{
printf("Unsupported thread attribute type: %llX\n", type);
printf("Unsupported thread attribute type: %zX\n", type);
}
}, i);
}
@@ -2492,7 +2499,7 @@ namespace
}
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id,
const emulator_object<RTL_SRWLOCK> lock)
const emulator_object<EMU_RTL_SRWLOCK<EmulatorTraits<Emu64>>> lock)
{
if (lock.value())
{

View File

@@ -14,8 +14,8 @@ namespace
emulator_object<T> allocate_object_on_stack(x64_emulator& emu)
{
const auto old_sp = emu.reg(x64_register::rsp);
const auto new_sp = align_down(old_sp - sizeof(CONTEXT),
std::max(alignof(CONTEXT), alignof(x64_emulator::pointer_type)));
const auto new_sp = align_down(old_sp - sizeof(CONTEXT64),
std::max(alignof(CONTEXT64), alignof(x64_emulator::pointer_type)));
emu.reg(x64_register::rsp, new_sp);
return {emu, new_sp};
@@ -143,8 +143,11 @@ namespace
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);
// TODO: fix
// const auto& orig_api_set_map = *NtCurrentTeb()->ProcessEnvironmentBlock->ApiSetMap;
// return clone_api_set_map(emu, allocator, orig_api_set_map);
return clone_api_set_map(emu, allocator, {});
}
emulator_allocator create_allocator(emulator& emu, const size_t size)
@@ -187,7 +190,7 @@ namespace
context.base_allocator = create_allocator(emu, PEB_SEGMENT_SIZE);
auto& allocator = context.base_allocator;
context.peb = allocator.reserve<PEB>();
context.peb = allocator.reserve<PEB64>();
/* Values of the following fields must be
* allocated relative to the process_params themselves
@@ -204,9 +207,9 @@ namespace
* RedirectionDllName
*/
context.process_params = allocator.reserve<RTL_USER_PROCESS_PARAMETERS>();
context.process_params = allocator.reserve<RTL_USER_PROCESS_PARAMETERS64>();
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params)
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params)
{
proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer
@@ -249,7 +252,7 @@ namespace
proc_params.MaximumLength = proc_params.Length;
});
context.peb.access([&](PEB& peb)
context.peb.access([&](PEB64& peb)
{
peb.ImageBaseAddress = nullptr;
peb.ProcessParameters = context.process_params.ptr();
@@ -266,21 +269,21 @@ namespace
});
}
using exception_record_map = std::unordered_map<const EXCEPTION_RECORD*, emulator_object<EXCEPTION_RECORD>>;
using exception_record_map = std::unordered_map<const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*, emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>>>;
emulator_object<EXCEPTION_RECORD> save_exception_record(emulator_allocator& allocator,
const EXCEPTION_RECORD& record,
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record,
exception_record_map& record_mapping)
{
const auto record_obj = allocator.reserve<EXCEPTION_RECORD>();
const auto record_obj = allocator.reserve<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>>();
record_obj.write(record);
if (record.ExceptionRecord)
{
record_mapping.emplace(&record, record_obj);
emulator_object<EXCEPTION_RECORD> nested_record_obj{allocator.get_emulator()};
const auto nested_record = record_mapping.find(record.ExceptionRecord);
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> nested_record_obj{allocator.get_emulator()};
const auto nested_record = record_mapping.find(reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(record.ExceptionRecord));
if (nested_record != record_mapping.end())
{
@@ -288,21 +291,21 @@ namespace
}
else
{
nested_record_obj = save_exception_record(allocator, *record.ExceptionRecord,
nested_record_obj = save_exception_record(allocator, *reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(record.ExceptionRecord),
record_mapping);
}
record_obj.access([&](EXCEPTION_RECORD& r)
record_obj.access([&](EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& r)
{
r.ExceptionRecord = nested_record_obj.ptr();
r.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(nested_record_obj.ptr());
});
}
return record_obj;
}
emulator_object<EXCEPTION_RECORD> save_exception_record(emulator_allocator& allocator,
const EXCEPTION_RECORD& record)
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record)
{
exception_record_map record_mapping{};
return save_exception_record(allocator, record, record_mapping);
@@ -321,12 +324,12 @@ namespace
}
}
size_t calculate_exception_record_size(const EXCEPTION_RECORD& record)
size_t calculate_exception_record_size(const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record)
{
std::unordered_set<const EXCEPTION_RECORD*> records{};
std::unordered_set<const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*> records{};
size_t total_size = 0;
const EXCEPTION_RECORD* current_record = &record;
const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>* current_record = &record;
while (current_record)
{
if (!records.insert(current_record).second)
@@ -335,7 +338,7 @@ namespace
}
total_size += sizeof(*current_record);
current_record = record.ExceptionRecord;
current_record = reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(record.ExceptionRecord);
}
return total_size;
@@ -350,11 +353,11 @@ namespace
uint64_t ss;
};
void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher, const EXCEPTION_POINTERS pointers)
void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher, const EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers)
{
constexpr auto mach_frame_size = 0x40;
constexpr auto context_record_size = 0x4F0;
const auto exception_record_size = calculate_exception_record_size(*pointers.ExceptionRecord);
const auto exception_record_size = calculate_exception_record_size(*reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(pointers.ExceptionRecord));
const auto combined_size = align_up(exception_record_size + context_record_size, 0x10);
assert(combined_size == 0x590);
@@ -375,11 +378,11 @@ namespace
emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, dispatcher);
const emulator_object<CONTEXT> context_record_obj{emu, new_sp};
context_record_obj.write(*pointers.ContextRecord);
const emulator_object<CONTEXT64> context_record_obj{emu, new_sp};
context_record_obj.write(*reinterpret_cast<CONTEXT64*>(pointers.ContextRecord));
emulator_allocator allocator{emu, new_sp + context_record_size, exception_record_size};
const auto exception_record_obj = save_exception_record(allocator, *pointers.ExceptionRecord);
const auto exception_record_obj = save_exception_record(allocator, *reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(pointers.ExceptionRecord));
if (exception_record_obj.value() != allocator.get_base())
{
@@ -389,34 +392,34 @@ namespace
const emulator_object<machine_frame> machine_frame_obj{emu, new_sp + combined_size};
machine_frame_obj.access([&](machine_frame& frame)
{
frame.rip = pointers.ContextRecord->Rip;
frame.rsp = pointers.ContextRecord->Rsp;
frame.ss = pointers.ContextRecord->SegSs;
frame.cs = pointers.ContextRecord->SegCs;
frame.eflags = pointers.ContextRecord->EFlags;
frame.rip = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->Rip;
frame.rsp = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->Rsp;
frame.ss = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->SegSs;
frame.cs = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->SegCs;
frame.eflags = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->EFlags;
});
}
void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address,
const memory_operation operation)
{
CONTEXT ctx{};
ctx.ContextFlags = CONTEXT_ALL;
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
context_frame::save(emu, ctx);
EXCEPTION_RECORD record{};
EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ACCESS_VIOLATION);
record.ExceptionFlags = 0;
record.ExceptionRecord = nullptr;
record.ExceptionAddress = reinterpret_cast<void*>(emu.read_instruction_pointer());
record.ExceptionRecord = 0;
record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 2;
record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation);
record.ExceptionInformation[1] = address;
EXCEPTION_POINTERS pointers{};
pointers.ContextRecord = &ctx;
pointers.ExceptionRecord = &record;
EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers);
}
@@ -560,7 +563,7 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte
const uint64_t argument,
const uint64_t stack_size, const uint32_t id)
: emu_ptr(&emu)
, stack_size(page_align_up(std::max(stack_size, STACK_SIZE)))
, stack_size(page_align_up(std::max(stack_size, static_cast<uint64_t>(STACK_SIZE))))
, start_address(start_address)
, argument(argument)
, id(id)
@@ -574,14 +577,14 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte
GS_SEGMENT_SIZE,
};
this->teb = this->gs_segment->reserve<TEB>();
this->teb = this->gs_segment->reserve<TEB64>();
this->teb->access([&](TEB& teb_obj)
this->teb->access([&](TEB64& teb_obj)
{
teb_obj.ClientId.UniqueProcess = reinterpret_cast<HANDLE>(1);
teb_obj.ClientId.UniqueThread = reinterpret_cast<HANDLE>(static_cast<uint64_t>(this->id));
teb_obj.NtTib.StackLimit = reinterpret_cast<void*>(this->stack_base);
teb_obj.NtTib.StackBase = reinterpret_cast<void*>(this->stack_base + this->stack_size);
teb_obj.ClientId.UniqueProcess = 1ul;
teb_obj.ClientId.UniqueThread = static_cast<uint64_t>(this->id);
teb_obj.NtTib.StackLimit = reinterpret_cast<std::uint64_t*>(this->stack_base);
teb_obj.NtTib.StackBase = reinterpret_cast<std::uint64_t*>(this->stack_base + this->stack_size);
teb_obj.NtTib.Self = &this->teb->ptr()->NtTib;
teb_obj.ProcessEnvironmentBlock = context.peb.ptr();
});
@@ -661,8 +664,8 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
setup_stack(emu, this->stack_base, this->stack_size);
setup_gs_segment(emu, *this->gs_segment);
CONTEXT ctx{};
ctx.ContextFlags = CONTEXT_ALL;
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
unalign_stack(emu);
context_frame::save(emu, ctx);
@@ -671,7 +674,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
ctx.Rcx = this->start_address;
ctx.Rdx = this->argument;
const auto ctx_obj = allocate_object_on_stack<CONTEXT>(emu);
const auto ctx_obj = allocate_object_on_stack<CONTEXT64>(emu);
ctx_obj.write(ctx);
unalign_stack(emu);
@@ -714,9 +717,9 @@ void windows_emulator::setup_process(const emulator_settings& settings)
context.executable = context.module_manager.map_module(settings.application, this->logger);
context.peb.access([&](PEB& peb)
context.peb.access([&](PEB64& peb)
{
peb.ImageBaseAddress = reinterpret_cast<void*>(context.executable->image_base);
peb.ImageBaseAddress = reinterpret_cast<std::uint64_t*>(context.executable->image_base);
});
context.ntdll = context.module_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->logger);
@@ -777,14 +780,14 @@ void windows_emulator::setup_hooks()
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&]
{
const auto ip = this->emu().read_instruction_pointer();
printf("Invalid instruction at: 0x%llX\n", ip);
printf("Invalid instruction at: 0x%zX\n", ip);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_interrupt([&](const int interrupt)
{
const auto rip = this->emu().read_instruction_pointer();
printf("Interrupt: %i 0x%llX\n", interrupt, rip);
printf("Interrupt: %i 0x%zX\n", interrupt, rip);
if (this->fuzzing)
{
@@ -889,7 +892,7 @@ void windows_emulator::setup_hooks()
auto& emu = this->emu();
printf(
"Inst: %16llX - RAX: %16llX - RBX: %16llX - RCX: %16llX - RDX: %16llX - R8: %16llX - R9: %16llX - RDI: %16llX - RSI: %16llX - %s\n",
"Inst: %16zX - RAX: %16zX - RBX: %16zX - RCX: %16zX - RDX: %16zX - R8: %16zX - R9: %16zX - RDI: %16zX - RSI: %16zX - %s\n",
address,
emu.reg(x64_register::rax), emu.reg(x64_register::rbx),
emu.reg(x64_register::rcx),