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); //watch_object(win_emu, win_emu.process().kusd);
auto* params_hook = watch_object(win_emu, win_emu.process().process_params); 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 uint64_t address, size_t, const uint64_t value)
{ {
const auto target_address = win_emu.process().peb.value() + offsetof( const auto target_address = win_emu.process().peb.value() + offsetof(
PEB, ProcessParameters); PEB64, ProcessParameters);
if (address == target_address) if (address == target_address)
{ {
const emulator_object<RTL_USER_PROCESS_PARAMETERS> obj{ const emulator_object<RTL_USER_PROCESS_PARAMETERS64> obj{
win_emu.emu(), value win_emu.emu(), value
}; };

View File

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

View File

@@ -3,9 +3,9 @@
namespace context_frame 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::dr0, context.Dr0);
emu.reg(x64_register::dr1, context.Dr1); emu.reg(x64_register::dr1, context.Dr1);
@@ -15,7 +15,7 @@ namespace context_frame
emu.reg(x64_register::dr7, context.Dr7); 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::ss, context.SegSs);
emu.reg<uint16_t>(x64_register::cs, context.SegCs); 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); 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::rax, context.Rax);
emu.reg(x64_register::rbx, context.Rbx); emu.reg(x64_register::rbx, context.Rbx);
@@ -53,7 +53,7 @@ namespace context_frame
emu.reg<uint16_t>(x64_register::gs, context.SegGs); 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::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x64_register::fpsw, context.FltSave.StatusWord); 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); 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.Dr0 = emu.reg(x64_register::dr0);
context.Dr1 = emu.reg(x64_register::dr1); context.Dr1 = emu.reg(x64_register::dr1);
@@ -90,7 +90,7 @@ namespace context_frame
context.Dr7 = emu.reg(x64_register::dr7); 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.SegSs = emu.reg<uint16_t>(x64_register::ss);
context.SegCs = emu.reg<uint16_t>(x64_register::cs); 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); 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.Rax = emu.reg(x64_register::rax);
context.Rbx = emu.reg(x64_register::rbx); context.Rbx = emu.reg(x64_register::rbx);
@@ -118,7 +118,7 @@ namespace context_frame
context.R15 = emu.reg(x64_register::r15); 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.SegDs = emu.reg<uint16_t>(x64_register::ds);
context.SegEs = emu.reg<uint16_t>(x64_register::es); 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); 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.ControlWord = emu.reg<uint16_t>(x64_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x64_register::fpsw); 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); context.MxCsr = emu.reg<uint32_t>(x64_register::mxcsr);
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)

View File

@@ -3,6 +3,6 @@
namespace context_frame namespace context_frame
{ {
void save(x64_emulator& emu, CONTEXT& context); void save(x64_emulator& emu, CONTEXT64& context);
void restore(x64_emulator& emu, const CONTEXT& 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); 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) 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) if (!c.input_buffer || c.input_buffer_length < info_size)
{ {
throw std::runtime_error("Bad AFD poll data"); 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); 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"); 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, NTSTATUS perform_poll(windows_emulator& win_emu, const io_device_context& c,
const std::span<const SOCKET> endpoints, 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{}; std::vector<pollfd> poll_data{};
poll_data.resize(endpoints.size()); poll_data.resize(endpoints.size());
@@ -147,8 +147,8 @@ namespace
return STATUS_PENDING; return STATUS_PENDING;
} }
constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles); constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles);
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};
size_t current_index = 0; size_t current_index = 0;
@@ -170,7 +170,7 @@ namespace
assert(current_index == static_cast<size_t>(count)); 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); info.NumberOfHandles = static_cast<ULONG>(current_index);
}); });
@@ -367,7 +367,7 @@ namespace
} }
static std::vector<SOCKET> resolve_endpoints(windows_emulator& win_emu, 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(); auto& proc = win_emu.process();
@@ -376,7 +376,7 @@ namespace
for (const auto& handle : handles) 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) if (!device)
{ {
throw std::runtime_error("Bad device!"); throw std::runtime_error("Bad device!");
@@ -428,17 +428,17 @@ namespace
{ {
auto& emu = win_emu.emu(); 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; return STATUS_BUFFER_TOO_SMALL;
} }
const auto receive_info = emu.read_memory<AFD_RECV_DATAGRAM_INFO>(c.input_buffer); const auto receive_info = emu.read_memory<AFD_RECV_DATAGRAM_INFO<EmulatorTraits<Emu64>>>(c.input_buffer);
const auto buffer = emu.read_memory<WSABUF>(receive_info.BufferArray); const auto buffer = emu.read_memory<EMU_WSABUF<EmulatorTraits<Emu64>>>(receive_info.BufferArray);
std::vector<std::byte> address{}; std::vector<std::byte> address{};
ULONG address_length = 0x1000; unsigned long address_length = 0x1000;
if (receive_info.AddressLength) if (receive_info.AddressLength)
{ {
address_length = emu.read_memory<ULONG>(receive_info.AddressLength); address_length = emu.read_memory<ULONG>(receive_info.AddressLength);
@@ -456,8 +456,13 @@ namespace
std::vector<char> data{}; std::vector<char> data{};
data.resize(buffer.len); data.resize(buffer.len);
#ifdef OS_WINDOWS
const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast<int>(data.size()), 0, const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast<int>(data.size()), 0,
reinterpret_cast<sockaddr*>(address.data()), &fromlength); 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) if (recevied_data < 0)
{ {
@@ -482,7 +487,7 @@ namespace
if (c.io_status_block) if (c.io_status_block)
{ {
IO_STATUS_BLOCK block{}; IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = static_cast<uint32_t>(recevied_data); block.Information = static_cast<uint32_t>(recevied_data);
c.io_status_block.write(block); c.io_status_block.write(block);
} }
@@ -494,13 +499,13 @@ namespace
{ {
const auto& emu = win_emu.emu(); 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; return STATUS_BUFFER_TOO_SMALL;
} }
const auto send_info = emu.read_memory<AFD_SEND_DATAGRAM_INFO>(c.input_buffer); const auto send_info = emu.read_memory<AFD_SEND_DATAGRAM_INFO<EmulatorTraits<Emu64>>>(c.input_buffer);
const auto buffer = emu.read_memory<WSABUF>(send_info.BufferArray); const auto buffer = emu.read_memory<EMU_WSABUF<EmulatorTraits<Emu64>>>(send_info.BufferArray);
const auto address = emu.read_memory(send_info.TdiConnInfo.RemoteAddress, const auto address = emu.read_memory(send_info.TdiConnInfo.RemoteAddress,
send_info.TdiConnInfo.RemoteAddressLength); send_info.TdiConnInfo.RemoteAddressLength);
@@ -528,7 +533,7 @@ namespace
if (c.io_status_block) if (c.io_status_block)
{ {
IO_STATUS_BLOCK block{}; IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = static_cast<uint32_t>(sent_data); block.Information = static_cast<uint32_t>(sent_data);
c.io_status_block.write(block); c.io_status_block.write(block);
} }

View File

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

View File

@@ -31,11 +31,12 @@ struct handle_value
static_assert(sizeof(handle_value) == 8); static_assert(sizeof(handle_value) == 8);
// TODO: this is a concrete 64bit handle
union handle union handle
{ {
handle_value value; handle_value value;
uint64_t bits; uint64_t bits;
HANDLE h; std::uint64_t h;
}; };
inline void serialize(utils::buffer_serializer& buffer, const handle& 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" if (device == u"CNG"
|| device == u"KsecDD" || device == u"KsecDD"
@@ -27,5 +27,5 @@ std::unique_ptr<io_device<EmulatorTraits<Emu64>>> create_device64(const std::u16
return create_afd_endpoint(); 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{}; handle event{};
emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine{}; emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine{};
emulator_pointer apc_context{}; 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{}; ULONG io_control_code{};
emulator_pointer input_buffer{}; emulator_pointer input_buffer{};
ULONG input_buffer_length{}; ULONG input_buffer_length{};
@@ -65,11 +65,11 @@ struct io_device_creation_data
uint32_t length; 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) 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; 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 class io_device_container : public io_device
{ {
public: public:
io_device_container() = default; 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)) : device_name_(std::move(device))
{ {
this->setup(); this->setup();
@@ -182,7 +182,7 @@ public:
} }
private: private:
std::wstring device_name_{}; std::u16string device_name_{};
std::unique_ptr<io_device> device_{}; std::unique_ptr<io_device> device_{};
void setup() void setup()

View File

@@ -5,12 +5,12 @@
#include <address_utils.hpp> #include <address_utils.hpp>
constexpr auto KUSD_ADDRESS = 0x7ffe0000ULL; 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); constexpr auto KUSD_BUFFER_SIZE = page_align_up(KUSD_SIZE);
namespace 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)); 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)); static_assert(KUSD_SIZE == sizeof(kusd));
buffer.write(&kusd, KUSD_SIZE); 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); buffer.read(&kusd, KUSD_SIZE);
} }

View File

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

View File

@@ -7,9 +7,14 @@
namespace 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); const auto absolute_base = reinterpret_cast<uint64_t>(&nt_headers);
return nt_headers_offset + (first_section_absolute - absolute_base); 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, 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]; auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0) 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, 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; const auto delta = binary.image_base - optional_header.ImageBase;
if (delta == 0) if (delta == 0)
@@ -134,7 +139,7 @@ namespace
void map_sections(emulator& emu, const mapped_module& binary, void map_sections(emulator& emu, const mapped_module& binary,
const utils::safe_buffer_accessor<const uint8_t> buffer, 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 first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset);
const auto sections = buffer.as<IMAGE_SECTION_HEADER>(first_section_offset); const auto sections = buffer.as<IMAGE_SECTION_HEADER>(first_section_offset);
@@ -183,10 +188,10 @@ namespace
utils::safe_buffer_accessor buffer{data}; 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_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; auto& optional_header = nt_headers.OptionalHeader;
binary.image_base = optional_header.ImageBase; binary.image_base = optional_header.ImageBase;

View File

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

View File

@@ -161,12 +161,12 @@ syscall_handler make_syscall_handler()
}; };
} }
template <typename T> template <typename T, typename Traits>
void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& value) void write_attribute(emulator& emu, const PS_ATTRIBUTE<Traits>& attribute, const T& value)
{ {
if (attribute.ReturnLength) 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)) if (attribute.Size >= sizeof(T))

View File

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

View File

@@ -14,8 +14,8 @@ namespace
emulator_object<T> allocate_object_on_stack(x64_emulator& emu) emulator_object<T> allocate_object_on_stack(x64_emulator& emu)
{ {
const auto old_sp = emu.reg(x64_register::rsp); const auto old_sp = emu.reg(x64_register::rsp);
const auto new_sp = align_down(old_sp - sizeof(CONTEXT), const auto new_sp = align_down(old_sp - sizeof(CONTEXT64),
std::max(alignof(CONTEXT), alignof(x64_emulator::pointer_type))); std::max(alignof(CONTEXT64), alignof(x64_emulator::pointer_type)));
emu.reg(x64_register::rsp, new_sp); emu.reg(x64_register::rsp, new_sp);
return {emu, 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) emulator_object<API_SET_NAMESPACE> build_api_set_map(x64_emulator& emu, emulator_allocator& allocator)
{ {
const auto& orig_api_set_map = *NtCurrentTeb()->ProcessEnvironmentBlock->ApiSetMap; // TODO: fix
return clone_api_set_map(emu, allocator, orig_api_set_map); // 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) emulator_allocator create_allocator(emulator& emu, const size_t size)
@@ -187,7 +190,7 @@ namespace
context.base_allocator = create_allocator(emu, PEB_SEGMENT_SIZE); context.base_allocator = create_allocator(emu, PEB_SEGMENT_SIZE);
auto& allocator = context.base_allocator; auto& allocator = context.base_allocator;
context.peb = allocator.reserve<PEB>(); context.peb = allocator.reserve<PEB64>();
/* Values of the following fields must be /* Values of the following fields must be
* allocated relative to the process_params themselves * allocated relative to the process_params themselves
@@ -204,9 +207,9 @@ namespace
* RedirectionDllName * 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 proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer
@@ -249,7 +252,7 @@ namespace
proc_params.MaximumLength = proc_params.Length; proc_params.MaximumLength = proc_params.Length;
}); });
context.peb.access([&](PEB& peb) context.peb.access([&](PEB64& peb)
{ {
peb.ImageBaseAddress = nullptr; peb.ImageBaseAddress = nullptr;
peb.ProcessParameters = context.process_params.ptr(); 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, emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EXCEPTION_RECORD& record, const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record,
exception_record_map& record_mapping) 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); record_obj.write(record);
if (record.ExceptionRecord) if (record.ExceptionRecord)
{ {
record_mapping.emplace(&record, record_obj); record_mapping.emplace(&record, record_obj);
emulator_object<EXCEPTION_RECORD> nested_record_obj{allocator.get_emulator()}; emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> nested_record_obj{allocator.get_emulator()};
const auto nested_record = record_mapping.find(record.ExceptionRecord); const auto nested_record = record_mapping.find(reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(record.ExceptionRecord));
if (nested_record != record_mapping.end()) if (nested_record != record_mapping.end())
{ {
@@ -288,21 +291,21 @@ namespace
} }
else 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_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; return record_obj;
} }
emulator_object<EXCEPTION_RECORD> save_exception_record(emulator_allocator& allocator, emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> save_exception_record(emulator_allocator& allocator,
const EXCEPTION_RECORD& record) const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>& record)
{ {
exception_record_map record_mapping{}; exception_record_map record_mapping{};
return save_exception_record(allocator, record, 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; size_t total_size = 0;
const EXCEPTION_RECORD* current_record = &record; const EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>* current_record = &record;
while (current_record) while (current_record)
{ {
if (!records.insert(current_record).second) if (!records.insert(current_record).second)
@@ -335,7 +338,7 @@ namespace
} }
total_size += sizeof(*current_record); total_size += sizeof(*current_record);
current_record = record.ExceptionRecord; current_record = reinterpret_cast<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>*>(record.ExceptionRecord);
} }
return total_size; return total_size;
@@ -350,11 +353,11 @@ namespace
uint64_t ss; 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 mach_frame_size = 0x40;
constexpr auto context_record_size = 0x4F0; 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); const auto combined_size = align_up(exception_record_size + context_record_size, 0x10);
assert(combined_size == 0x590); assert(combined_size == 0x590);
@@ -375,11 +378,11 @@ namespace
emu.reg(x64_register::rsp, new_sp); emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, dispatcher); emu.reg(x64_register::rip, dispatcher);
const emulator_object<CONTEXT> context_record_obj{emu, new_sp}; const emulator_object<CONTEXT64> context_record_obj{emu, new_sp};
context_record_obj.write(*pointers.ContextRecord); context_record_obj.write(*reinterpret_cast<CONTEXT64*>(pointers.ContextRecord));
emulator_allocator allocator{emu, new_sp + context_record_size, exception_record_size}; 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()) 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}; const emulator_object<machine_frame> machine_frame_obj{emu, new_sp + combined_size};
machine_frame_obj.access([&](machine_frame& frame) machine_frame_obj.access([&](machine_frame& frame)
{ {
frame.rip = pointers.ContextRecord->Rip; frame.rip = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->Rip;
frame.rsp = pointers.ContextRecord->Rsp; frame.rsp = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->Rsp;
frame.ss = pointers.ContextRecord->SegSs; frame.ss = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->SegSs;
frame.cs = pointers.ContextRecord->SegCs; frame.cs = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->SegCs;
frame.eflags = pointers.ContextRecord->EFlags; frame.eflags = reinterpret_cast<CONTEXT64*>(pointers.ContextRecord)->EFlags;
}); });
} }
void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address, void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address,
const memory_operation operation) const memory_operation operation)
{ {
CONTEXT ctx{}; CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT_ALL; ctx.ContextFlags = CONTEXT64_ALL;
context_frame::save(emu, ctx); context_frame::save(emu, ctx);
EXCEPTION_RECORD record{}; EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record)); memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ACCESS_VIOLATION); record.ExceptionCode = static_cast<DWORD>(STATUS_ACCESS_VIOLATION);
record.ExceptionFlags = 0; record.ExceptionFlags = 0;
record.ExceptionRecord = nullptr; record.ExceptionRecord = 0;
record.ExceptionAddress = reinterpret_cast<void*>(emu.read_instruction_pointer()); record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 2; record.NumberParameters = 2;
record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation); record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation);
record.ExceptionInformation[1] = address; record.ExceptionInformation[1] = address;
EXCEPTION_POINTERS pointers{}; EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = &ctx; pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = &record; pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers); 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 argument,
const uint64_t stack_size, const uint32_t id) const uint64_t stack_size, const uint32_t id)
: emu_ptr(&emu) : 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) , start_address(start_address)
, argument(argument) , argument(argument)
, id(id) , id(id)
@@ -574,14 +577,14 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte
GS_SEGMENT_SIZE, 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.UniqueProcess = 1ul;
teb_obj.ClientId.UniqueThread = reinterpret_cast<HANDLE>(static_cast<uint64_t>(this->id)); teb_obj.ClientId.UniqueThread = static_cast<uint64_t>(this->id);
teb_obj.NtTib.StackLimit = reinterpret_cast<void*>(this->stack_base); teb_obj.NtTib.StackLimit = reinterpret_cast<std::uint64_t*>(this->stack_base);
teb_obj.NtTib.StackBase = reinterpret_cast<void*>(this->stack_base + this->stack_size); 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.NtTib.Self = &this->teb->ptr()->NtTib;
teb_obj.ProcessEnvironmentBlock = context.peb.ptr(); 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_stack(emu, this->stack_base, this->stack_size);
setup_gs_segment(emu, *this->gs_segment); setup_gs_segment(emu, *this->gs_segment);
CONTEXT ctx{}; CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT_ALL; ctx.ContextFlags = CONTEXT64_ALL;
unalign_stack(emu); unalign_stack(emu);
context_frame::save(emu, ctx); 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.Rcx = this->start_address;
ctx.Rdx = this->argument; 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); ctx_obj.write(ctx);
unalign_stack(emu); 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.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); 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, [&] this->emu().hook_instruction(x64_hookable_instructions::invalid, [&]
{ {
const auto ip = this->emu().read_instruction_pointer(); 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; return instruction_hook_continuation::skip_instruction;
}); });
this->emu().hook_interrupt([&](const int interrupt) this->emu().hook_interrupt([&](const int interrupt)
{ {
const auto rip = this->emu().read_instruction_pointer(); 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) if (this->fuzzing)
{ {
@@ -889,7 +892,7 @@ void windows_emulator::setup_hooks()
auto& emu = this->emu(); auto& emu = this->emu();
printf( 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, address,
emu.reg(x64_register::rax), emu.reg(x64_register::rbx), emu.reg(x64_register::rax), emu.reg(x64_register::rbx),
emu.reg(x64_register::rcx), emu.reg(x64_register::rcx),