mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-29 07:51:01 +00:00
Merge remote-tracking branch 'origin/main' into unicorn-upgrade-2
This commit is contained in:
@@ -14,8 +14,8 @@ namespace apiset
|
||||
{
|
||||
namespace
|
||||
{
|
||||
uint64_t copy_string(x86_64_emulator& emu, emulator_allocator& allocator, const void* base_ptr,
|
||||
const uint64_t offset, const size_t length)
|
||||
uint64_t copy_string(x86_64_emulator& emu, emulator_allocator& allocator, const void* base_ptr, const uint64_t offset,
|
||||
const size_t length)
|
||||
{
|
||||
if (!length)
|
||||
{
|
||||
@@ -29,8 +29,8 @@ namespace apiset
|
||||
return str_obj;
|
||||
}
|
||||
|
||||
ULONG copy_string_as_relative(x86_64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
|
||||
const void* base_ptr, const uint64_t offset, const size_t length)
|
||||
ULONG copy_string_as_relative(x86_64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base, const void* base_ptr,
|
||||
const uint64_t offset, const size_t length)
|
||||
{
|
||||
const auto address = copy_string(emu, allocator, base_ptr, offset, length);
|
||||
if (!address)
|
||||
@@ -115,14 +115,12 @@ namespace apiset
|
||||
return obtain(apiset_loc, root);
|
||||
}
|
||||
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
|
||||
const container& container)
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator, const container& container)
|
||||
{
|
||||
return clone(emu, allocator, container.get());
|
||||
}
|
||||
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
|
||||
const API_SET_NAMESPACE& orig_api_set_map)
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator, const API_SET_NAMESPACE& orig_api_set_map)
|
||||
{
|
||||
const auto api_set_map_obj = allocator.reserve<API_SET_NAMESPACE>();
|
||||
const auto ns_entries_obj = allocator.reserve<API_SET_NAMESPACE_ENTRY>(orig_api_set_map.Count);
|
||||
@@ -134,18 +132,16 @@ namespace apiset
|
||||
api_set.HashOffset = static_cast<ULONG>(hash_entries_obj.value() - api_set_map_obj.value());
|
||||
});
|
||||
|
||||
const auto* orig_ns_entries =
|
||||
offset_pointer<API_SET_NAMESPACE_ENTRY>(&orig_api_set_map, orig_api_set_map.EntryOffset);
|
||||
const auto* orig_hash_entries =
|
||||
offset_pointer<API_SET_HASH_ENTRY>(&orig_api_set_map, orig_api_set_map.HashOffset);
|
||||
const auto* orig_ns_entries = offset_pointer<API_SET_NAMESPACE_ENTRY>(&orig_api_set_map, orig_api_set_map.EntryOffset);
|
||||
const auto* orig_hash_entries = offset_pointer<API_SET_HASH_ENTRY>(&orig_api_set_map, orig_api_set_map.HashOffset);
|
||||
|
||||
for (ULONG i = 0; i < orig_api_set_map.Count; ++i)
|
||||
{
|
||||
auto ns_entry = orig_ns_entries[i];
|
||||
const auto hash_entry = orig_hash_entries[i];
|
||||
|
||||
ns_entry.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map,
|
||||
ns_entry.NameOffset, ns_entry.NameLength);
|
||||
ns_entry.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map, ns_entry.NameOffset,
|
||||
ns_entry.NameLength);
|
||||
|
||||
if (!ns_entry.ValueCount)
|
||||
{
|
||||
@@ -161,13 +157,13 @@ namespace apiset
|
||||
{
|
||||
auto value = orig_values[j];
|
||||
|
||||
value.ValueOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map,
|
||||
value.ValueOffset, value.ValueLength);
|
||||
value.ValueOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map, value.ValueOffset,
|
||||
value.ValueLength);
|
||||
|
||||
if (value.NameLength)
|
||||
{
|
||||
value.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(),
|
||||
&orig_api_set_map, value.NameOffset, value.NameLength);
|
||||
value.NameOffset = copy_string_as_relative(emu, allocator, api_set_map_obj.value(), &orig_api_set_map, value.NameOffset,
|
||||
value.NameLength);
|
||||
}
|
||||
|
||||
values_obj.write(value, j);
|
||||
|
||||
@@ -32,6 +32,5 @@ namespace apiset
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
|
||||
const API_SET_NAMESPACE& orig_api_set_map);
|
||||
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
|
||||
const container& container);
|
||||
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator, const container& container);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -221,8 +221,7 @@ namespace
|
||||
return win_emu.emu().read_memory<afd_creation_data>(data.buffer);
|
||||
}
|
||||
|
||||
std::pair<AFD_POLL_INFO64, std::vector<AFD_POLL_HANDLE_INFO64>> get_poll_info(windows_emulator& win_emu,
|
||||
const io_device_context& c)
|
||||
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_INFO64, Handles);
|
||||
if (!c.input_buffer || c.input_buffer_length < info_size || c.input_buffer != c.output_buffer)
|
||||
@@ -272,8 +271,8 @@ namespace
|
||||
return socket_events;
|
||||
}
|
||||
|
||||
ULONG map_socket_response_events_to_afd(const int16_t socket_events, const ULONG afd_poll_events,
|
||||
const bool is_listening, const bool is_connecting)
|
||||
ULONG map_socket_response_events_to_afd(const int16_t socket_events, const ULONG afd_poll_events, const bool is_listening,
|
||||
const bool is_connecting)
|
||||
{
|
||||
ULONG afd_events = 0;
|
||||
|
||||
@@ -306,8 +305,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
if ((socket_events & (POLLHUP | POLLERR)) == (POLLHUP | POLLERR) &&
|
||||
afd_poll_events & (AFD_POLL_CONNECT_FAIL | AFD_POLL_ABORT))
|
||||
if ((socket_events & (POLLHUP | POLLERR)) == (POLLHUP | POLLERR) && afd_poll_events & (AFD_POLL_CONNECT_FAIL | AFD_POLL_ABORT))
|
||||
{
|
||||
afd_events |= (AFD_POLL_CONNECT_FAIL | AFD_POLL_ABORT);
|
||||
}
|
||||
@@ -388,8 +386,7 @@ namespace
|
||||
|
||||
void delay_ioctrl(const io_device_context& c, const std::optional<bool> require_poll = {},
|
||||
const std::optional<std::chrono::steady_clock::time_point> timeout = {},
|
||||
const std::optional<std::function<void(windows_emulator&, const io_device_context&)>>&
|
||||
timeout_callback = {})
|
||||
const std::optional<std::function<void(windows_emulator&, const io_device_context&)>>& timeout_callback = {})
|
||||
{
|
||||
if (this->executing_delayed_ioctl_)
|
||||
{
|
||||
@@ -426,8 +423,7 @@ namespace
|
||||
}
|
||||
if (this->event_select_mask_)
|
||||
{
|
||||
pfd.events =
|
||||
static_cast<int16_t>(pfd.events | map_afd_request_events_to_socket(this->event_select_mask_));
|
||||
pfd.events = static_cast<int16_t>(pfd.events | map_afd_request_events_to_socket(this->event_select_mask_));
|
||||
}
|
||||
pfd.revents = pfd.events;
|
||||
|
||||
@@ -440,10 +436,9 @@ namespace
|
||||
|
||||
if (socket_events && this->event_select_mask_)
|
||||
{
|
||||
const bool is_connecting =
|
||||
this->delayed_ioctl_ && _AFD_REQUEST(this->delayed_ioctl_->io_control_code) == AFD_CONNECT;
|
||||
ULONG current_events = map_socket_response_events_to_afd(socket_events, this->event_select_mask_,
|
||||
pfd.s->is_listening(), is_connecting);
|
||||
const bool is_connecting = this->delayed_ioctl_ && _AFD_REQUEST(this->delayed_ioctl_->io_control_code) == AFD_CONNECT;
|
||||
ULONG current_events =
|
||||
map_socket_response_events_to_afd(socket_events, this->event_select_mask_, pfd.s->is_listening(), is_connecting);
|
||||
|
||||
if ((current_events & ~this->triggered_events_) != 0)
|
||||
{
|
||||
@@ -463,8 +458,7 @@ namespace
|
||||
|
||||
if (this->require_poll_.has_value())
|
||||
{
|
||||
const auto is_ready =
|
||||
socket_events & ((*this->require_poll_ ? POLLIN : POLLOUT) | POLLHUP | POLLERR);
|
||||
const auto is_ready = socket_events & ((*this->require_poll_ ? POLLIN : POLLOUT) | POLLHUP | POLLERR);
|
||||
if (!is_ready)
|
||||
{
|
||||
return;
|
||||
@@ -955,8 +949,7 @@ namespace
|
||||
endpoint->delayed_ioctl_ && _AFD_REQUEST(endpoint->delayed_ioctl_->io_control_code) == AFD_CONNECT;
|
||||
|
||||
auto entry = handle_info_obj.read(i);
|
||||
entry.PollEvents = map_socket_response_events_to_afd(pfd.revents, handle.PollEvents,
|
||||
pfd.s->is_listening(), is_connecting);
|
||||
entry.PollEvents = map_socket_response_events_to_afd(pfd.revents, handle.PollEvents, pfd.s->is_listening(), is_connecting);
|
||||
entry.Status = STATUS_SUCCESS;
|
||||
|
||||
handle_info_obj.write(entry, current_index++);
|
||||
@@ -1102,8 +1095,8 @@ namespace
|
||||
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);
|
||||
|
||||
auto address_buffer = emu.read_memory(send_info.TdiConnInfo.RemoteAddress,
|
||||
static_cast<size_t>(send_info.TdiConnInfo.RemoteAddressLength));
|
||||
auto address_buffer =
|
||||
emu.read_memory(send_info.TdiConnInfo.RemoteAddress, static_cast<size_t>(send_info.TdiConnInfo.RemoteAddressLength));
|
||||
|
||||
const auto target = convert_to_host_address(win_emu, address_buffer);
|
||||
const auto data = emu.read_memory(buffer.buf, buffer.len);
|
||||
|
||||
@@ -76,8 +76,7 @@ namespace
|
||||
MOUNTMGR_MOUNT_POINT point{};
|
||||
const auto symlink = write_string<char16_t>(buffer, make_volume(drive, 0));
|
||||
const auto id = write_string<char>(buffer, make_drive_id(drive, 0));
|
||||
const auto name = write_string<char16_t>(buffer, u"\\Device\\HarddiskVolume" +
|
||||
u8_to_u16(std::to_string(drive - 'a' + 1)));
|
||||
const auto name = write_string<char16_t>(buffer, u"\\Device\\HarddiskVolume" + u8_to_u16(std::to_string(drive - 'a' + 1)));
|
||||
|
||||
point.SymbolicLinkNameOffset = symlink.first;
|
||||
point.SymbolicLinkNameLength = symlink.second;
|
||||
|
||||
@@ -2,45 +2,33 @@
|
||||
|
||||
// NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
#define MOUNTMGRCONTROLTYPE 0x0000006D // 'm'
|
||||
#define MOUNTDEVCONTROLTYPE 0x0000004D // 'M'
|
||||
#define MOUNTMGRCONTROLTYPE 0x0000006D // 'm'
|
||||
#define MOUNTDEVCONTROLTYPE 0x0000004D // 'M'
|
||||
|
||||
#define IOCTL_MOUNTMGR_CREATE_POINT \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DELETE_POINTS \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_POINTS CTL_CODE(MOUNTMGRCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY CTL_CODE(MOUNTMGRCONTROLTYPE, 8, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 9, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_CREATE_POINT CTL_CODE(MOUNTMGRCONTROLTYPE, 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DELETE_POINTS CTL_CODE(MOUNTMGRCONTROLTYPE, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_POINTS CTL_CODE(MOUNTMGRCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY CTL_CODE(MOUNTMGRCONTROLTYPE, 3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER CTL_CODE(MOUNTMGRCONTROLTYPE, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS CTL_CODE(MOUNTMGRCONTROLTYPE, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED CTL_CODE(MOUNTMGRCONTROLTYPE, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED CTL_CODE(MOUNTMGRCONTROLTYPE, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_CHANGE_NOTIFY CTL_CODE(MOUNTMGRCONTROLTYPE, 8, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE CTL_CODE(MOUNTMGRCONTROLTYPE, 9, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES CTL_CODE(MOUNTMGRCONTROLTYPE, 10, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION CTL_CODE(MOUNTMGRCONTROLTYPE, 11, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH CTL_CODE(MOUNTMGRCONTROLTYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS CTL_CODE(MOUNTMGRCONTROLTYPE, 13, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 14, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT CTL_CODE(MOUNTMGRCONTROLTYPE, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_SCRUB_REGISTRY CTL_CODE(MOUNTMGRCONTROLTYPE, 14, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT CTL_CODE(MOUNTMGRCONTROLTYPE, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT CTL_CODE(MOUNTMGRCONTROLTYPE, 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_BOOT_DL_ASSIGNMENT \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 17, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) // since WIN7
|
||||
#define IOCTL_MOUNTMGR_TRACELOG_CACHE CTL_CODE(MOUNTMGRCONTROLTYPE, 18, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_PREPARE_VOLUME_DELETE \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 19, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_TRACELOG_CACHE CTL_CODE(MOUNTMGRCONTROLTYPE, 18, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_PREPARE_VOLUME_DELETE CTL_CODE(MOUNTMGRCONTROLTYPE, 19, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MOUNTMGR_CANCEL_VOLUME_DELETE \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 20, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) // since WIN8
|
||||
#define IOCTL_MOUNTMGR_SILO_ARRIVAL \
|
||||
CTL_CODE(MOUNTMGRCONTROLTYPE, 21, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) // since RS1
|
||||
#define IOCTL_MOUNTMGR_SILO_ARRIVAL CTL_CODE(MOUNTMGRCONTROLTYPE, 21, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) // since RS1
|
||||
|
||||
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME CTL_CODE(MOUNTDEVCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
35
src/windows-emulator/devices/named_pipe.hpp
Normal file
35
src/windows-emulator/devices/named_pipe.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "../io_device.hpp"
|
||||
|
||||
class named_pipe : public io_device_container
|
||||
{
|
||||
public:
|
||||
std::u16string name;
|
||||
std::deque<std::string> write_queue;
|
||||
ACCESS_MASK access = 0;
|
||||
ULONG pipe_type;
|
||||
ULONG read_mode;
|
||||
ULONG completion_mode;
|
||||
ULONG max_instances;
|
||||
ULONG inbound_quota;
|
||||
ULONG outbound_quota;
|
||||
LARGE_INTEGER default_timeout;
|
||||
|
||||
void create(windows_emulator&, const io_device_creation_data&) override
|
||||
{
|
||||
}
|
||||
void work(windows_emulator&) override
|
||||
{
|
||||
}
|
||||
NTSTATUS io_control(windows_emulator&, const io_device_context&) override
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void serialize_object(utils::buffer_serializer&) const override
|
||||
{
|
||||
}
|
||||
void deserialize_object(utils::buffer_deserializer&) override
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -10,19 +10,17 @@ namespace
|
||||
// RNG Microsoft Primitive Provider
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
std::uint8_t output_data[216] = //
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x4E, 0x00, 0x47,
|
||||
0x00, 0x00, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00,
|
||||
0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x74,
|
||||
0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00,
|
||||
0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00,
|
||||
0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x70, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D,
|
||||
0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2E, 0x00, 0x64, 0x00,
|
||||
0x6C, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x52, 0x00, 0x4E, 0x00, 0x47, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00,
|
||||
0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x74, 0x00,
|
||||
0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00,
|
||||
0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00,
|
||||
0x70, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x73, 0x00,
|
||||
0x2E, 0x00, 0x64, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& c) override
|
||||
{
|
||||
|
||||
@@ -10,8 +10,7 @@ namespace
|
||||
emulator_object<T> allocate_object_on_stack(x86_64_emulator& emu)
|
||||
{
|
||||
const auto old_sp = emu.reg(x86_register::rsp);
|
||||
const auto new_sp =
|
||||
align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x86_64_emulator::pointer_type)));
|
||||
const auto new_sp = align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x86_64_emulator::pointer_type)));
|
||||
emu.reg(x86_register::rsp, new_sp);
|
||||
return {emu, new_sp};
|
||||
}
|
||||
@@ -88,8 +87,7 @@ namespace
|
||||
}
|
||||
|
||||
emulator_thread::emulator_thread(memory_manager& memory, const process_context& context, const uint64_t start_address,
|
||||
const uint64_t argument, const uint64_t stack_size, const bool suspended,
|
||||
const uint32_t id)
|
||||
const uint64_t argument, const uint64_t stack_size, const bool suspended, const uint32_t id)
|
||||
: memory_ptr(&memory),
|
||||
stack_size(page_align_up(std::max(stack_size, static_cast<uint64_t>(STACK_SIZE)))),
|
||||
start_address(start_address),
|
||||
@@ -119,6 +117,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
|
||||
teb_obj.NtTib.StackLimit = this->stack_base;
|
||||
teb_obj.NtTib.StackBase = this->stack_base + this->stack_size;
|
||||
teb_obj.NtTib.Self = this->teb->value();
|
||||
teb_obj.CurrentLocale = 0x409;
|
||||
teb_obj.ProcessEnvironmentBlock = context.peb.value();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ class emulator_thread : public ref_counted_object
|
||||
{
|
||||
}
|
||||
|
||||
emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument,
|
||||
uint64_t stack_size, bool suspended, uint32_t id);
|
||||
emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument, uint64_t stack_size,
|
||||
bool suspended, uint32_t id);
|
||||
|
||||
emulator_thread(const emulator_thread&) = delete;
|
||||
emulator_thread& operator=(const emulator_thread&) = delete;
|
||||
@@ -74,6 +74,9 @@ class emulator_thread : public ref_counted_object
|
||||
|
||||
uint32_t id{};
|
||||
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
std::u16string name{};
|
||||
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
@@ -144,6 +147,8 @@ class emulator_thread : public ref_counted_object
|
||||
buffer.write(this->argument);
|
||||
buffer.write(this->executed_instructions);
|
||||
buffer.write(this->id);
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
|
||||
buffer.write_string(this->name);
|
||||
|
||||
@@ -182,6 +187,8 @@ class emulator_thread : public ref_counted_object
|
||||
buffer.read(this->argument);
|
||||
buffer.read(this->executed_instructions);
|
||||
buffer.read(this->id);
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
|
||||
buffer.read_string(this->name);
|
||||
|
||||
|
||||
@@ -251,8 +251,8 @@ class emulator_allocator
|
||||
result.MaximumLength = static_cast<USHORT>(max_length);
|
||||
}
|
||||
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> make_unicode_string(
|
||||
const std::u16string_view str, const std::optional<size_t> maximum_length = std::nullopt)
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> make_unicode_string(const std::u16string_view str,
|
||||
const std::optional<size_t> maximum_length = std::nullopt)
|
||||
{
|
||||
const auto unicode_string = this->reserve<UNICODE_STRING<EmulatorTraits<Emu64>>>();
|
||||
|
||||
@@ -316,8 +316,7 @@ class emulator_allocator
|
||||
};
|
||||
|
||||
template <typename Element>
|
||||
std::basic_string<Element> read_string(memory_interface& mem, const uint64_t address,
|
||||
const std::optional<size_t> size = {})
|
||||
std::basic_string<Element> read_string(memory_interface& mem, const uint64_t address, const std::optional<size_t> size = {})
|
||||
{
|
||||
std::basic_string<Element> result{};
|
||||
|
||||
@@ -357,8 +356,7 @@ inline std::u16string read_unicode_string(const emulator& emu, const UNICODE_STR
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u16string read_unicode_string(const emulator& emu,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> uc_string)
|
||||
inline std::u16string read_unicode_string(const emulator& emu, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> uc_string)
|
||||
{
|
||||
const auto ucs = uc_string.read();
|
||||
return read_unicode_string(emu, ucs);
|
||||
@@ -369,7 +367,7 @@ inline std::u16string read_unicode_string(emulator& emu, const uint64_t uc_strin
|
||||
return read_unicode_string(emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{emu, uc_string});
|
||||
}
|
||||
|
||||
inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index, bool is_syscall = false)
|
||||
inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index, const bool is_syscall = false)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace
|
||||
using exception_record = EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>;
|
||||
using exception_record_map = std::unordered_map<const exception_record*, emulator_object<exception_record>>;
|
||||
|
||||
emulator_object<exception_record> save_exception_record(emulator_allocator& allocator,
|
||||
const exception_record& record,
|
||||
emulator_object<exception_record> save_exception_record(emulator_allocator& allocator, const exception_record& record,
|
||||
exception_record_map& record_mapping)
|
||||
{
|
||||
const auto record_obj = allocator.reserve<exception_record>();
|
||||
@@ -28,8 +27,8 @@ namespace
|
||||
}
|
||||
else
|
||||
{
|
||||
nested_record_obj = save_exception_record(
|
||||
allocator, *reinterpret_cast<exception_record*>(record.ExceptionRecord), record_mapping);
|
||||
nested_record_obj =
|
||||
save_exception_record(allocator, *reinterpret_cast<exception_record*>(record.ExceptionRecord), record_mapping);
|
||||
}
|
||||
|
||||
record_obj.access([&](exception_record& r) {
|
||||
@@ -40,8 +39,7 @@ namespace
|
||||
return record_obj;
|
||||
}
|
||||
|
||||
emulator_object<exception_record> save_exception_record(emulator_allocator& allocator,
|
||||
const exception_record& record)
|
||||
emulator_object<exception_record> save_exception_record(emulator_allocator& allocator, const exception_record& record)
|
||||
{
|
||||
exception_record_map record_mapping{};
|
||||
return save_exception_record(allocator, record, record_mapping);
|
||||
@@ -94,8 +92,7 @@ namespace
|
||||
{
|
||||
constexpr auto mach_frame_size = 0x40;
|
||||
constexpr auto context_record_size = 0x4F0;
|
||||
const auto exception_record_size =
|
||||
calculate_exception_record_size(*reinterpret_cast<exception_record*>(pointers.ExceptionRecord));
|
||||
const auto exception_record_size = calculate_exception_record_size(*reinterpret_cast<exception_record*>(pointers.ExceptionRecord));
|
||||
const auto combined_size = align_up(exception_record_size + context_record_size, 0x10);
|
||||
|
||||
assert(combined_size == 0x590);
|
||||
@@ -120,8 +117,7 @@ namespace
|
||||
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, *reinterpret_cast<exception_record*>(pointers.ExceptionRecord));
|
||||
const auto exception_record_obj = save_exception_record(allocator, *reinterpret_cast<exception_record*>(pointers.ExceptionRecord));
|
||||
|
||||
if (exception_record_obj.value() != allocator.get_base())
|
||||
{
|
||||
@@ -172,8 +168,7 @@ void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const
|
||||
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
|
||||
}
|
||||
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address,
|
||||
const memory_operation operation)
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address, const memory_operation operation)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
|
||||
{
|
||||
@@ -182,6 +177,16 @@ void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc
|
||||
});
|
||||
}
|
||||
|
||||
void dispatch_guard_page_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address,
|
||||
const memory_operation operation)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_GUARD_PAGE_VIOLATION,
|
||||
{
|
||||
map_violation_operation_to_parameter(operation),
|
||||
address,
|
||||
});
|
||||
}
|
||||
|
||||
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
|
||||
|
||||
@@ -17,8 +17,8 @@ void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const
|
||||
dispatch_exception(emu, proc, static_cast<DWORD>(status), parameters);
|
||||
}
|
||||
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address,
|
||||
memory_operation operation);
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address, memory_operation operation);
|
||||
void dispatch_guard_page_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address, memory_operation operation);
|
||||
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc);
|
||||
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc);
|
||||
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "devices/afd_endpoint.hpp"
|
||||
#include "devices/mount_point_manager.hpp"
|
||||
#include "devices/security_support_provider.hpp"
|
||||
#include "devices/named_pipe.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -49,6 +51,11 @@ std::unique_ptr<io_device> create_device(const std::u16string_view device)
|
||||
return create_security_support_provider();
|
||||
}
|
||||
|
||||
if (device == u"NamedPipe")
|
||||
{
|
||||
return std::make_unique<named_pipe>();
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported device: " + u16_to_u8(device));
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ struct io_device_creation_data
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
inline NTSTATUS write_io_status(const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const NTSTATUS status, const bool clear_struct = false)
|
||||
inline NTSTATUS write_io_status(const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const NTSTATUS status,
|
||||
const bool clear_struct = false)
|
||||
{
|
||||
io_status_block.access([=](IO_STATUS_BLOCK<EmulatorTraits<Emu64>>& status_block) {
|
||||
if (clear_struct)
|
||||
|
||||
@@ -27,16 +27,16 @@ namespace
|
||||
kusd.TimeZoneBias.High2Time = -17;
|
||||
kusd.TimeZoneId = 0x00000002;
|
||||
kusd.LargePageMinimum = 0x00200000;
|
||||
kusd.RNGSeedVersion = 0x0000000000000013;
|
||||
kusd.RNGSeedVersion = 0;
|
||||
kusd.TimeZoneBiasStamp = 0x00000004;
|
||||
kusd.NtBuildNumber = 0x00006c51;
|
||||
kusd.NtBuildNumber = 19045;
|
||||
kusd.NtProductType = NtProductWinNt;
|
||||
kusd.ProductTypeIsValid = 0x01;
|
||||
kusd.NativeProcessorArchitecture = 0x0009;
|
||||
kusd.NtMajorVersion = 0x0000000a;
|
||||
kusd.BootId = 0x0000000b;
|
||||
kusd.SystemExpirationDate.QuadPart = 0x01dc26860a9ff300;
|
||||
kusd.SuiteMask = 0x00000110;
|
||||
kusd.BootId = 0;
|
||||
kusd.SystemExpirationDate.QuadPart = 0;
|
||||
kusd.SuiteMask = 0;
|
||||
kusd.MitigationPolicies.MitigationPolicies = 0x0a;
|
||||
kusd.MitigationPolicies.NXSupportPolicy = 0x02;
|
||||
kusd.MitigationPolicies.SEHValidationPolicy = 0x02;
|
||||
@@ -48,7 +48,7 @@ namespace
|
||||
kusd.FullNumberOfPhysicalPages = 0x0000000000bf0958;
|
||||
kusd.TickCount.TickCount.LowPart = 0x001f7f05;
|
||||
kusd.TickCount.TickCountQuad = 0x00000000001f7f05;
|
||||
kusd.Cookie = 0x1c3471da;
|
||||
kusd.Cookie = 0;
|
||||
kusd.ConsoleSessionForegroundProcessId = 0x00000000000028f4;
|
||||
kusd.TimeUpdateLock = 0x0000000002b28586;
|
||||
kusd.BaselineSystemTimeQpc = 0x0000004b17cd596c;
|
||||
@@ -61,7 +61,7 @@ namespace
|
||||
kusd.TelemetryCoverageRound = 0x00000001;
|
||||
kusd.LangGenerationCount = 0x00000003;
|
||||
kusd.InterruptTimeBias = 0x00000015a5d56406;
|
||||
kusd.ActiveProcessorCount = 0x0000000c;
|
||||
kusd.ActiveProcessorCount = 0x00000004;
|
||||
kusd.ActiveGroupCount = 0x01;
|
||||
kusd.TimeZoneBiasEffectiveStart.QuadPart = 0x01db276e654cb2ff;
|
||||
kusd.TimeZoneBiasEffectiveEnd.QuadPart = 0x01db280b8c3b2800;
|
||||
|
||||
@@ -74,29 +74,47 @@ namespace
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
||||
std::string_view format(va_list* ap, const char* message)
|
||||
int format_internal(const char* message, std::span<char> buffer, va_list* ap)
|
||||
{
|
||||
return vsnprintf(buffer.data(), buffer.size(), message, *ap);
|
||||
}
|
||||
|
||||
std::string_view format(const char* message, std::string& reserve_buffer, va_list* ap1, va_list* ap2)
|
||||
{
|
||||
thread_local std::array<char, 0x1000> buffer{};
|
||||
|
||||
#ifdef _WIN32
|
||||
const int count = _vsnprintf_s(buffer.data(), buffer.size(), buffer.size(), message, *ap);
|
||||
#else
|
||||
const int count = vsnprintf(buffer.data(), buffer.size(), message, *ap);
|
||||
#endif
|
||||
auto count = format_internal(message, buffer, ap1);
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {buffer.data(), static_cast<size_t>(count)};
|
||||
if (static_cast<size_t>(count) < buffer.size())
|
||||
{
|
||||
return {buffer.data(), static_cast<size_t>(count)};
|
||||
}
|
||||
|
||||
reserve_buffer.resize(count + 1);
|
||||
count = format_internal(message, reserve_buffer, ap2);
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {reserve_buffer.data(), std::min(static_cast<size_t>(count), reserve_buffer.size() - 1)};
|
||||
}
|
||||
|
||||
#define format_to_string(msg, str) \
|
||||
va_list ap; \
|
||||
va_start(ap, msg); \
|
||||
const auto str = format(&ap, msg); \
|
||||
va_end(ap)
|
||||
#define format_to_string(msg, str) \
|
||||
std::string buf{}; \
|
||||
va_list ap1; \
|
||||
va_list ap2; \
|
||||
va_start(ap1, msg); \
|
||||
va_start(ap2, msg); \
|
||||
const auto str = format(msg, buf, &ap1, &ap2); \
|
||||
va_end(ap2); \
|
||||
va_end(ap1)
|
||||
|
||||
void print_colored(const std::string_view& line, const color_type base_color)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "memory_region.hpp"
|
||||
#include "address_utils.hpp"
|
||||
#include "memory_permission_ext.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
@@ -24,8 +25,7 @@ namespace
|
||||
|
||||
i->second.length = static_cast<size_t>(first_length);
|
||||
|
||||
regions[split_point] =
|
||||
memory_manager::committed_region{static_cast<size_t>(second_length), i->second.permissions};
|
||||
regions[split_point] = memory_manager::committed_region{static_cast<size_t>(second_length), i->second.permissions};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace utils
|
||||
static void deserialize(buffer_deserializer& buffer, memory_manager::committed_region& region)
|
||||
{
|
||||
region.length = static_cast<size_t>(buffer.read<uint64_t>());
|
||||
region.permissions = buffer.read<memory_permission>();
|
||||
region.permissions = buffer.read<nt_memory_permission>();
|
||||
}
|
||||
|
||||
static void serialize(buffer_serializer& buffer, const memory_manager::reserved_region& region)
|
||||
@@ -189,8 +189,8 @@ void memory_manager::deserialize_memory_state(utils::buffer_deserializer& buffer
|
||||
}
|
||||
}
|
||||
|
||||
bool memory_manager::protect_memory(const uint64_t address, const size_t size, const memory_permission permissions,
|
||||
memory_permission* old_permissions)
|
||||
bool memory_manager::protect_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions,
|
||||
nt_memory_permission* old_permissions)
|
||||
{
|
||||
const auto entry = this->find_reserved_region(address);
|
||||
if (entry == this->reserved_regions_.end())
|
||||
@@ -243,8 +243,7 @@ bool memory_manager::protect_memory(const uint64_t address, const size_t size, c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_manager::allocate_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
|
||||
mmio_write_callback write_cb)
|
||||
bool memory_manager::allocate_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb)
|
||||
{
|
||||
if (this->overlaps_reserved_region(address, size))
|
||||
{
|
||||
@@ -268,7 +267,7 @@ bool memory_manager::allocate_mmio(const uint64_t address, const size_t size, mm
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_manager::allocate_memory(const uint64_t address, const size_t size, const memory_permission permissions,
|
||||
bool memory_manager::allocate_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions,
|
||||
const bool reserve_only)
|
||||
{
|
||||
if (this->overlaps_reserved_region(address, size))
|
||||
@@ -286,8 +285,8 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size,
|
||||
|
||||
if (!reserve_only)
|
||||
{
|
||||
this->map_memory(address, size, permissions);
|
||||
entry->second.committed_regions[address] = committed_region{size, memory_permission::read_write};
|
||||
this->map_memory(address, size, permissions.is_guarded() ? memory_permission::none : permissions.common);
|
||||
entry->second.committed_regions[address] = committed_region{size, permissions};
|
||||
}
|
||||
|
||||
this->update_layout_version();
|
||||
@@ -295,7 +294,7 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_manager::commit_memory(const uint64_t address, const size_t size, const memory_permission permissions)
|
||||
bool memory_manager::commit_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions)
|
||||
{
|
||||
const auto entry = this->find_reserved_region(address);
|
||||
if (entry == this->reserved_regions_.end())
|
||||
@@ -473,8 +472,7 @@ void memory_manager::unmap_all_memory()
|
||||
this->reserved_regions_.clear();
|
||||
}
|
||||
|
||||
uint64_t memory_manager::allocate_memory(const size_t size, const memory_permission permissions,
|
||||
const bool reserve_only)
|
||||
uint64_t memory_manager::allocate_memory(const size_t size, const nt_memory_permission permissions, const bool reserve_only)
|
||||
{
|
||||
const auto allocation_base = this->find_free_allocation_base(size);
|
||||
if (!allocate_memory(allocation_base, size, permissions, reserve_only))
|
||||
@@ -519,8 +517,8 @@ region_info memory_manager::get_region_info(const uint64_t address)
|
||||
region_info result{};
|
||||
result.start = MIN_ALLOCATION_ADDRESS;
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
|
||||
result.permissions = memory_permission::none;
|
||||
result.initial_permissions = memory_permission::none;
|
||||
result.permissions = nt_memory_permission();
|
||||
result.initial_permissions = nt_memory_permission();
|
||||
result.allocation_base = {};
|
||||
result.allocation_length = result.length;
|
||||
result.is_committed = false;
|
||||
@@ -637,8 +635,7 @@ void memory_manager::write_memory(const uint64_t address, const void* data, cons
|
||||
this->memory_->write_memory(address, data, size);
|
||||
}
|
||||
|
||||
void memory_manager::map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
|
||||
mmio_write_callback write_cb)
|
||||
void memory_manager::map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb)
|
||||
{
|
||||
this->memory_->map_mmio(address, size, std::move(read_cb), std::move(write_cb));
|
||||
}
|
||||
@@ -653,8 +650,7 @@ void memory_manager::unmap_memory(const uint64_t address, const size_t size)
|
||||
this->memory_->unmap_memory(address, size);
|
||||
}
|
||||
|
||||
void memory_manager::apply_memory_protection(const uint64_t address, const size_t size,
|
||||
const memory_permission permissions)
|
||||
void memory_manager::apply_memory_protection(const uint64_t address, const size_t size, const memory_permission permissions)
|
||||
{
|
||||
this->memory_->apply_memory_protection(address, size, permissions);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#include "memory_permission_ext.hpp"
|
||||
#include "memory_region.hpp"
|
||||
#include "serialization.hpp"
|
||||
|
||||
@@ -12,13 +13,15 @@ constexpr auto ALLOCATION_GRANULARITY = 0x0000000000010000ULL;
|
||||
constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL;
|
||||
constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL;
|
||||
|
||||
struct region_info : basic_memory_region
|
||||
// This maps to the `basic_memory_region` struct defined in
|
||||
// emulator\memory_region.hpp
|
||||
struct region_info : basic_memory_region<nt_memory_permission>
|
||||
{
|
||||
uint64_t allocation_base{};
|
||||
size_t allocation_length{};
|
||||
bool is_reserved{};
|
||||
bool is_committed{};
|
||||
memory_permission initial_permissions{};
|
||||
nt_memory_permission initial_permissions{};
|
||||
};
|
||||
|
||||
using mmio_read_callback = std::function<void(uint64_t addr, void* data, size_t size)>;
|
||||
@@ -41,7 +44,7 @@ class memory_manager : public memory_interface
|
||||
struct committed_region
|
||||
{
|
||||
size_t length{};
|
||||
memory_permission permissions{};
|
||||
nt_memory_permission permissions{};
|
||||
};
|
||||
|
||||
using committed_region_map = std::map<uint64_t, committed_region>;
|
||||
@@ -60,20 +63,19 @@ class memory_manager : public memory_interface
|
||||
bool try_read_memory(uint64_t address, void* data, size_t size) const final;
|
||||
void write_memory(uint64_t address, const void* data, size_t size) final;
|
||||
|
||||
bool protect_memory(uint64_t address, size_t size, memory_permission permissions,
|
||||
memory_permission* old_permissions = nullptr);
|
||||
bool protect_memory(uint64_t address, size_t size, nt_memory_permission permissions, nt_memory_permission* old_permissions = nullptr);
|
||||
|
||||
bool allocate_mmio(uint64_t address, size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb);
|
||||
bool allocate_memory(uint64_t address, size_t size, memory_permission permissions, bool reserve_only = false);
|
||||
bool allocate_memory(uint64_t address, size_t size, nt_memory_permission permissions, bool reserve_only = false);
|
||||
|
||||
bool commit_memory(uint64_t address, size_t size, memory_permission permissions);
|
||||
bool commit_memory(uint64_t address, size_t size, nt_memory_permission permissions);
|
||||
bool decommit_memory(uint64_t address, size_t size);
|
||||
|
||||
bool release_memory(uint64_t address, size_t size);
|
||||
|
||||
void unmap_all_memory();
|
||||
|
||||
uint64_t allocate_memory(size_t size, memory_permission permissions, bool reserve_only = false);
|
||||
uint64_t allocate_memory(size_t size, nt_memory_permission permissions, bool reserve_only = false);
|
||||
|
||||
uint64_t find_free_allocation_base(size_t size, uint64_t start = 0) const;
|
||||
|
||||
|
||||
180
src/windows-emulator/memory_permission_ext.hpp
Normal file
180
src/windows-emulator/memory_permission_ext.hpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
#include "memory_permission.hpp"
|
||||
|
||||
enum class memory_permission_ext : uint8_t
|
||||
{
|
||||
none = 0,
|
||||
guard = 1 << 0,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
constexpr memory_permission_ext operator&(const memory_permission_ext x, const memory_permission_ext y)
|
||||
{
|
||||
return static_cast<memory_permission_ext>(static_cast<uint8_t>(x) & static_cast<uint8_t>(y));
|
||||
}
|
||||
|
||||
constexpr memory_permission_ext operator|(const memory_permission_ext x, const memory_permission_ext y)
|
||||
{
|
||||
return static_cast<memory_permission_ext>(static_cast<uint8_t>(x) | static_cast<uint8_t>(y));
|
||||
}
|
||||
|
||||
constexpr memory_permission_ext operator^(const memory_permission_ext x, const memory_permission_ext y)
|
||||
{
|
||||
return static_cast<memory_permission_ext>(static_cast<uint8_t>(x) ^ static_cast<uint8_t>(y));
|
||||
}
|
||||
|
||||
constexpr memory_permission_ext operator~(memory_permission_ext x)
|
||||
{
|
||||
return static_cast<memory_permission_ext>(~static_cast<uint8_t>(x));
|
||||
}
|
||||
|
||||
inline memory_permission_ext& operator&=(memory_permission_ext& x, const memory_permission_ext y)
|
||||
{
|
||||
x = x & y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline memory_permission_ext& operator|=(memory_permission_ext& x, const memory_permission_ext y)
|
||||
{
|
||||
x = x | y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline memory_permission_ext& operator^=(memory_permission_ext& x, const memory_permission_ext y)
|
||||
{
|
||||
x = x ^ y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct nt_memory_permission
|
||||
{
|
||||
memory_permission common;
|
||||
memory_permission_ext extended;
|
||||
|
||||
constexpr nt_memory_permission()
|
||||
: common(memory_permission::none),
|
||||
extended(memory_permission_ext::none)
|
||||
{
|
||||
}
|
||||
constexpr nt_memory_permission(memory_permission common)
|
||||
: common(common),
|
||||
extended(memory_permission_ext::none)
|
||||
{
|
||||
}
|
||||
constexpr nt_memory_permission(memory_permission common, memory_permission_ext ext)
|
||||
: common(common),
|
||||
extended(ext)
|
||||
{
|
||||
}
|
||||
|
||||
// Implicit coercions
|
||||
operator memory_permission() const
|
||||
{
|
||||
return common;
|
||||
}
|
||||
operator memory_permission_ext() const
|
||||
{
|
||||
return extended;
|
||||
}
|
||||
|
||||
// This just does memberwise equality on each of the members in declaration order
|
||||
bool operator==(nt_memory_permission const&) const = default;
|
||||
|
||||
nt_memory_permission& operator=(memory_permission const& y)
|
||||
{
|
||||
this->common = y;
|
||||
this->extended = memory_permission_ext::none;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool is_guarded() const
|
||||
{
|
||||
return (this->extended & memory_permission_ext::guard) == memory_permission_ext::guard;
|
||||
}
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
constexpr nt_memory_permission operator&(const nt_memory_permission x, const memory_permission y)
|
||||
{
|
||||
return nt_memory_permission{x.common & y, x.extended};
|
||||
}
|
||||
|
||||
constexpr nt_memory_permission operator&(const nt_memory_permission x, const memory_permission_ext y)
|
||||
{
|
||||
return nt_memory_permission{x.common, x.extended & y};
|
||||
}
|
||||
|
||||
constexpr nt_memory_permission operator|(const nt_memory_permission x, const memory_permission y)
|
||||
{
|
||||
return nt_memory_permission{x.common | y, x.extended};
|
||||
}
|
||||
|
||||
constexpr nt_memory_permission operator|(const nt_memory_permission x, const memory_permission_ext y)
|
||||
{
|
||||
return nt_memory_permission{x.common, x.extended | y};
|
||||
}
|
||||
|
||||
constexpr nt_memory_permission operator^(const nt_memory_permission x, const memory_permission y)
|
||||
{
|
||||
return nt_memory_permission{x.common ^ y, x.extended};
|
||||
}
|
||||
|
||||
constexpr nt_memory_permission operator^(const nt_memory_permission x, const memory_permission_ext y)
|
||||
{
|
||||
return nt_memory_permission{x.common, x.extended ^ y};
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator&=(nt_memory_permission& x, const memory_permission y)
|
||||
{
|
||||
x = x & y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator&=(nt_memory_permission& x, const memory_permission_ext y)
|
||||
{
|
||||
x = x & y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator|=(nt_memory_permission& x, const memory_permission y)
|
||||
{
|
||||
x.common | y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator|=(nt_memory_permission& x, const nt_memory_permission y)
|
||||
{
|
||||
x.extended | y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator^=(nt_memory_permission& x, const memory_permission y)
|
||||
{
|
||||
x.common ^ y;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline nt_memory_permission& operator^=(nt_memory_permission& x, const nt_memory_permission y)
|
||||
{
|
||||
x.extended ^ y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
inline bool is_guarded(const memory_permission_ext permission)
|
||||
{
|
||||
return (permission & memory_permission_ext::guard) != memory_permission_ext::none;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <emulator.hpp>
|
||||
#include "memory_permission_ext.hpp"
|
||||
|
||||
inline std::string get_permission_string(const memory_permission permission)
|
||||
{
|
||||
@@ -19,28 +20,55 @@ inline std::string get_permission_string(const memory_permission permission)
|
||||
return res;
|
||||
}
|
||||
|
||||
inline memory_permission map_nt_to_emulator_protection(uint32_t nt_protection)
|
||||
inline std::optional<nt_memory_permission> try_map_nt_to_emulator_protection(uint32_t nt_protection)
|
||||
{
|
||||
nt_protection &= ~static_cast<uint32_t>(PAGE_GUARD); // TODO: Implement that
|
||||
memory_permission_ext ext = memory_permission_ext::none;
|
||||
// TODO: Check for invalid combinations
|
||||
if (nt_protection & PAGE_GUARD)
|
||||
{
|
||||
// Unset the guard flag so the following switch statement will still work
|
||||
nt_protection &= ~static_cast<uint32_t>(PAGE_GUARD);
|
||||
ext = memory_permission_ext::guard;
|
||||
}
|
||||
|
||||
memory_permission common = memory_permission::none;
|
||||
switch (nt_protection)
|
||||
{
|
||||
case PAGE_NOACCESS:
|
||||
return memory_permission::none;
|
||||
common = memory_permission::none;
|
||||
break;
|
||||
case PAGE_READONLY:
|
||||
return memory_permission::read;
|
||||
common = memory_permission::read;
|
||||
break;
|
||||
case PAGE_READWRITE:
|
||||
case PAGE_WRITECOPY:
|
||||
return memory_permission::read | memory_permission::write;
|
||||
common = memory_permission::read | memory_permission::write;
|
||||
break;
|
||||
case PAGE_EXECUTE:
|
||||
case PAGE_EXECUTE_READ:
|
||||
return memory_permission::read | memory_permission::exec;
|
||||
common = memory_permission::read | memory_permission::exec;
|
||||
break;
|
||||
case PAGE_EXECUTE_READWRITE:
|
||||
return memory_permission::all;
|
||||
common = memory_permission::all;
|
||||
break;
|
||||
case 0:
|
||||
case PAGE_EXECUTE_WRITECOPY:
|
||||
default:
|
||||
throw std::runtime_error("Failed to map protection");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return nt_memory_permission{common, ext};
|
||||
}
|
||||
|
||||
inline nt_memory_permission map_nt_to_emulator_protection(uint32_t nt_protection)
|
||||
{
|
||||
const auto protection = try_map_nt_to_emulator_protection(nt_protection);
|
||||
if (protection.has_value())
|
||||
{
|
||||
return *protection;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Failed to map protection: " + std::to_string(nt_protection));
|
||||
}
|
||||
|
||||
inline uint32_t map_emulator_to_nt_protection(const memory_permission permission)
|
||||
|
||||
@@ -51,8 +51,7 @@ namespace minidump_loader
|
||||
}
|
||||
|
||||
bool parse_minidump_file(windows_emulator& win_emu, const std::filesystem::path& minidump_path,
|
||||
std::unique_ptr<minidump::minidump_file>& dump_file,
|
||||
std::unique_ptr<minidump::minidump_reader>& dump_reader)
|
||||
std::unique_ptr<minidump::minidump_file>& dump_file, std::unique_ptr<minidump::minidump_reader>& dump_reader)
|
||||
{
|
||||
win_emu.log.info("Parsing minidump file\n");
|
||||
|
||||
@@ -160,10 +159,9 @@ namespace minidump_loader
|
||||
stats.total_memory_size += segment.size;
|
||||
}
|
||||
|
||||
win_emu.log.info(
|
||||
"Summary: %s, %zu threads, %zu modules, %zu regions, %zu segments, %zu handles, %" PRIu64 " bytes memory\n",
|
||||
get_architecture_string(dump_file).c_str(), stats.thread_count, stats.module_count,
|
||||
stats.memory_region_count, stats.memory_segment_count, stats.handle_count, stats.total_memory_size);
|
||||
win_emu.log.info("Summary: %s, %zu threads, %zu modules, %zu regions, %zu segments, %zu handles, %" PRIu64 " bytes memory\n",
|
||||
get_architecture_string(dump_file).c_str(), stats.thread_count, stats.module_count, stats.memory_region_count,
|
||||
stats.memory_segment_count, stats.handle_count, stats.total_memory_size);
|
||||
}
|
||||
|
||||
void process_streams(windows_emulator& win_emu, const minidump::minidump_file* dump_file)
|
||||
@@ -177,9 +175,8 @@ namespace minidump_loader
|
||||
const auto* sys_info = dump_file->get_system_info();
|
||||
if (sys_info)
|
||||
{
|
||||
win_emu.log.info("System: OS %u.%u.%u, %u processors, type %u, platform %u\n", sys_info->major_version,
|
||||
sys_info->minor_version, sys_info->build_number, sys_info->number_of_processors,
|
||||
sys_info->product_type, sys_info->platform_id);
|
||||
win_emu.log.info("System: OS %u.%u.%u, %u processors, type %u, platform %u\n", sys_info->major_version, sys_info->minor_version,
|
||||
sys_info->build_number, sys_info->number_of_processors, sys_info->product_type, sys_info->platform_id);
|
||||
}
|
||||
|
||||
// Process memory info
|
||||
@@ -199,8 +196,7 @@ namespace minidump_loader
|
||||
guard_pages++;
|
||||
}
|
||||
}
|
||||
win_emu.log.info("Memory: %zu regions, %" PRIu64 " bytes reserved, %" PRIu64
|
||||
" bytes committed, %zu guard pages\n",
|
||||
win_emu.log.info("Memory: %zu regions, %" PRIu64 " bytes reserved, %" PRIu64 " bytes committed, %zu guard pages\n",
|
||||
memory_regions.size(), total_reserved, total_committed, guard_pages);
|
||||
|
||||
// Process memory content
|
||||
@@ -214,25 +210,23 @@ namespace minidump_loader
|
||||
}
|
||||
if (!memory_segments.empty())
|
||||
{
|
||||
win_emu.log.info("Content: %zu segments, range 0x%" PRIx64 "-0x%" PRIx64 " (%" PRIu64 " bytes span)\n",
|
||||
memory_segments.size(), min_addr, max_addr, max_addr - min_addr);
|
||||
win_emu.log.info("Content: %zu segments, range 0x%" PRIx64 "-0x%" PRIx64 " (%" PRIu64 " bytes span)\n", memory_segments.size(),
|
||||
min_addr, max_addr, max_addr - min_addr);
|
||||
}
|
||||
|
||||
// Process modules
|
||||
const auto& modules = dump_file->modules();
|
||||
for (const auto& mod : modules)
|
||||
{
|
||||
win_emu.log.info("Module: %s at 0x%" PRIx64 " (%u bytes)\n", mod.module_name.c_str(), mod.base_of_image,
|
||||
mod.size_of_image);
|
||||
win_emu.log.info("Module: %s at 0x%" PRIx64 " (%u bytes)\n", mod.module_name.c_str(), mod.base_of_image, mod.size_of_image);
|
||||
}
|
||||
|
||||
// Process threads
|
||||
const auto& threads = dump_file->threads();
|
||||
for (const auto& thread : threads)
|
||||
{
|
||||
win_emu.log.info("Thread %u: TEB 0x%" PRIx64 ", stack 0x%" PRIx64 " (%u bytes), context %u bytes\n",
|
||||
thread.thread_id, thread.teb, thread.stack_start_of_memory_range, thread.stack_data_size,
|
||||
thread.context_data_size);
|
||||
win_emu.log.info("Thread %u: TEB 0x%" PRIx64 ", stack 0x%" PRIx64 " (%u bytes), context %u bytes\n", thread.thread_id,
|
||||
thread.teb, thread.stack_start_of_memory_range, thread.stack_data_size, thread.context_data_size);
|
||||
}
|
||||
|
||||
// Process handles
|
||||
@@ -272,8 +266,7 @@ namespace minidump_loader
|
||||
const auto& memory_regions = dump_file->memory_regions();
|
||||
const auto& memory_segments = dump_file->memory_segments();
|
||||
|
||||
win_emu.log.info("Reconstructing memory: %zu regions, %zu data segments\n", memory_regions.size(),
|
||||
memory_segments.size());
|
||||
win_emu.log.info("Reconstructing memory: %zu regions, %zu data segments\n", memory_regions.size(), memory_segments.size());
|
||||
size_t reserved_count = 0;
|
||||
size_t committed_count = 0;
|
||||
size_t failed_count = 0;
|
||||
@@ -281,8 +274,8 @@ namespace minidump_loader
|
||||
for (const auto& region : memory_regions)
|
||||
{
|
||||
// Log the memory region details
|
||||
win_emu.log.info("Region: 0x%" PRIx64 ", size=%" PRIu64 ", state=0x%08X, protect=0x%08X\n",
|
||||
region.base_address, region.region_size, region.state, region.protect);
|
||||
win_emu.log.info("Region: 0x%" PRIx64 ", size=%" PRIu64 ", state=0x%08X, protect=0x%08X\n", region.base_address,
|
||||
region.region_size, region.state, region.protect);
|
||||
|
||||
const bool is_reserved = (region.state & MEM_RESERVE) != 0;
|
||||
const bool is_committed = (region.state & MEM_COMMIT) != 0;
|
||||
@@ -297,8 +290,7 @@ namespace minidump_loader
|
||||
if (protect_value == 0)
|
||||
{
|
||||
protect_value = PAGE_READONLY;
|
||||
win_emu.log.warn(" Region 0x%" PRIx64 " has zero protection, using PAGE_READONLY\n",
|
||||
region.base_address);
|
||||
win_emu.log.warn(" Region 0x%" PRIx64 " has zero protection, using PAGE_READONLY\n", region.base_address);
|
||||
}
|
||||
|
||||
memory_permission perms = map_nt_to_emulator_protection(protect_value);
|
||||
@@ -307,35 +299,31 @@ namespace minidump_loader
|
||||
{
|
||||
if (is_committed)
|
||||
{
|
||||
if (win_emu.memory.allocate_memory(region.base_address, static_cast<size_t>(region.region_size),
|
||||
perms, false))
|
||||
if (win_emu.memory.allocate_memory(region.base_address, static_cast<size_t>(region.region_size), perms, false))
|
||||
{
|
||||
committed_count++;
|
||||
win_emu.log.info(" Allocated committed 0x%" PRIx64 ": size=%" PRIu64
|
||||
", state=0x%08X, protect=0x%08X\n",
|
||||
win_emu.log.info(" Allocated committed 0x%" PRIx64 ": size=%" PRIu64 ", state=0x%08X, protect=0x%08X\n",
|
||||
region.base_address, region.region_size, region.state, region.protect);
|
||||
}
|
||||
else
|
||||
{
|
||||
failed_count++;
|
||||
win_emu.log.warn(" Failed to allocate committed 0x%" PRIx64 ": size=%" PRIu64 "\n",
|
||||
region.base_address, region.region_size);
|
||||
win_emu.log.warn(" Failed to allocate committed 0x%" PRIx64 ": size=%" PRIu64 "\n", region.base_address,
|
||||
region.region_size);
|
||||
}
|
||||
}
|
||||
else if (is_reserved)
|
||||
{
|
||||
if (win_emu.memory.allocate_memory(region.base_address, static_cast<size_t>(region.region_size),
|
||||
perms, true))
|
||||
if (win_emu.memory.allocate_memory(region.base_address, static_cast<size_t>(region.region_size), perms, true))
|
||||
{
|
||||
reserved_count++;
|
||||
win_emu.log.info(" Reserved 0x%" PRIx64 ": size=%" PRIu64 ", state=0x%08X, protect=0x%08X\n",
|
||||
region.base_address, region.region_size, region.state, region.protect);
|
||||
win_emu.log.info(" Reserved 0x%" PRIx64 ": size=%" PRIu64 ", state=0x%08X, protect=0x%08X\n", region.base_address,
|
||||
region.region_size, region.state, region.protect);
|
||||
}
|
||||
else
|
||||
{
|
||||
failed_count++;
|
||||
win_emu.log.warn(" Failed to reserve 0x%" PRIx64 ": size=%" PRIu64 "\n", region.base_address,
|
||||
region.region_size);
|
||||
win_emu.log.warn(" Failed to reserve 0x%" PRIx64 ": size=%" PRIu64 "\n", region.base_address, region.region_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,8 +334,7 @@ namespace minidump_loader
|
||||
}
|
||||
}
|
||||
|
||||
win_emu.log.info("Regions: %zu reserved, %zu committed, %zu failed\n", reserved_count, committed_count,
|
||||
failed_count);
|
||||
win_emu.log.info("Regions: %zu reserved, %zu committed, %zu failed\n", reserved_count, committed_count, failed_count);
|
||||
size_t written_count = 0;
|
||||
size_t write_failed_count = 0;
|
||||
uint64_t total_bytes_written = 0;
|
||||
@@ -356,25 +343,21 @@ namespace minidump_loader
|
||||
{
|
||||
try
|
||||
{
|
||||
auto memory_data =
|
||||
dump_reader->read_memory(segment.start_virtual_address, static_cast<size_t>(segment.size));
|
||||
win_emu.memory.write_memory(segment.start_virtual_address, memory_data.data(),
|
||||
static_cast<size_t>(memory_data.size()));
|
||||
auto memory_data = dump_reader->read_memory(segment.start_virtual_address, static_cast<size_t>(segment.size));
|
||||
win_emu.memory.write_memory(segment.start_virtual_address, memory_data.data(), static_cast<size_t>(memory_data.size()));
|
||||
written_count++;
|
||||
total_bytes_written += memory_data.size();
|
||||
win_emu.log.info(" Written segment 0x%" PRIx64 ": %zu bytes\n", segment.start_virtual_address,
|
||||
memory_data.size());
|
||||
win_emu.log.info(" Written segment 0x%" PRIx64 ": %zu bytes\n", segment.start_virtual_address, memory_data.size());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
write_failed_count++;
|
||||
win_emu.log.error(" Failed to write segment 0x%" PRIx64 ": %s\n", segment.start_virtual_address,
|
||||
e.what());
|
||||
win_emu.log.error(" Failed to write segment 0x%" PRIx64 ": %s\n", segment.start_virtual_address, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
win_emu.log.info("Content: %zu segments written (%" PRIu64 " bytes), %zu failed\n", written_count,
|
||||
total_bytes_written, write_failed_count);
|
||||
win_emu.log.info("Content: %zu segments written (%" PRIu64 " bytes), %zu failed\n", written_count, total_bytes_written,
|
||||
write_failed_count);
|
||||
}
|
||||
|
||||
bool is_main_executable(const minidump::module_info& mod)
|
||||
@@ -414,15 +397,14 @@ namespace minidump_loader
|
||||
{
|
||||
try
|
||||
{
|
||||
auto* mapped_module = win_emu.mod_manager.map_memory_module(mod.base_of_image, mod.size_of_image,
|
||||
mod.module_name, win_emu.log);
|
||||
auto* mapped_module =
|
||||
win_emu.mod_manager.map_memory_module(mod.base_of_image, mod.size_of_image, mod.module_name, win_emu.log);
|
||||
|
||||
if (mapped_module)
|
||||
{
|
||||
mapped_count++;
|
||||
win_emu.log.info(" Mapped %s at 0x%" PRIx64 " (%u bytes, %zu sections, %zu exports)\n",
|
||||
mod.module_name.c_str(), mod.base_of_image, mod.size_of_image,
|
||||
mapped_module->sections.size(), mapped_module->exports.size());
|
||||
win_emu.log.info(" Mapped %s at 0x%" PRIx64 " (%u bytes, %zu sections, %zu exports)\n", mod.module_name.c_str(),
|
||||
mod.base_of_image, mod.size_of_image, mapped_module->sections.size(), mapped_module->exports.size());
|
||||
|
||||
if (is_main_executable(mod))
|
||||
{
|
||||
@@ -446,8 +428,7 @@ namespace minidump_loader
|
||||
else
|
||||
{
|
||||
failed_count++;
|
||||
win_emu.log.warn(" Failed to map %s at 0x%" PRIx64 "\n", mod.module_name.c_str(),
|
||||
mod.base_of_image);
|
||||
win_emu.log.warn(" Failed to map %s at 0x%" PRIx64 "\n", mod.module_name.c_str(), mod.base_of_image);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@@ -457,8 +438,8 @@ namespace minidump_loader
|
||||
}
|
||||
}
|
||||
|
||||
win_emu.log.info("Module reconstruction: %zu mapped, %zu failed, %zu system modules identified\n", mapped_count,
|
||||
failed_count, identified_count);
|
||||
win_emu.log.info("Module reconstruction: %zu mapped, %zu failed, %zu system modules identified\n", mapped_count, failed_count,
|
||||
identified_count);
|
||||
}
|
||||
|
||||
void setup_kusd_from_dump(windows_emulator& win_emu, const minidump::minidump_file* dump_file)
|
||||
@@ -483,8 +464,7 @@ namespace minidump_loader
|
||||
kusd.ProductTypeIsValid = 1;
|
||||
|
||||
win_emu.log.info("KUSD updated: Windows %u.%u.%u, %u processors, product type %u\n", sys_info->major_version,
|
||||
sys_info->minor_version, sys_info->build_number, sys_info->number_of_processors,
|
||||
sys_info->product_type);
|
||||
sys_info->minor_version, sys_info->build_number, sys_info->number_of_processors, sys_info->product_type);
|
||||
}
|
||||
|
||||
bool load_thread_context(const std::filesystem::path& minidump_path, const minidump::thread_info& thread_info,
|
||||
@@ -546,8 +526,8 @@ namespace minidump_loader
|
||||
thread.teb->set_address(thread_info.teb);
|
||||
}
|
||||
|
||||
win_emu.log.info(" Thread %u: TEB=0x%" PRIx64 ", stack=0x%" PRIx64 " (%u bytes), context=%s\n",
|
||||
thread_info.thread_id, thread_info.teb, thread.stack_base, thread_info.stack_data_size,
|
||||
win_emu.log.info(" Thread %u: TEB=0x%" PRIx64 ", stack=0x%" PRIx64 " (%u bytes), context=%s\n", thread_info.thread_id,
|
||||
thread_info.teb, thread.stack_base, thread_info.stack_data_size,
|
||||
context_loaded ? "loaded" : "unavailable");
|
||||
|
||||
win_emu.process.threads.store(std::move(thread));
|
||||
@@ -566,8 +546,8 @@ namespace minidump_loader
|
||||
win_emu.process.active_thread = &first_thread;
|
||||
}
|
||||
|
||||
win_emu.log.info("Thread reconstruction: %zu/%zu threads created, %zu with context\n", success_count,
|
||||
threads.size(), context_loaded_count);
|
||||
win_emu.log.info("Thread reconstruction: %zu/%zu threads created, %zu with context\n", success_count, threads.size(),
|
||||
context_loaded_count);
|
||||
}
|
||||
|
||||
void setup_peb_from_teb(windows_emulator& win_emu, const minidump::minidump_file* dump_file)
|
||||
@@ -652,8 +632,8 @@ namespace minidump_loader
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
win_emu.log.error(" Failed to create %s handle '%s': %s\n", handle_info.type_name.c_str(),
|
||||
handle_info.object_name.c_str(), e.what());
|
||||
win_emu.log.error(" Failed to create %s handle '%s': %s\n", handle_info.type_name.c_str(), handle_info.object_name.c_str(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,10 +654,9 @@ namespace minidump_loader
|
||||
return;
|
||||
}
|
||||
|
||||
win_emu.process.current_ip = exception_info->exception_record.exception_address;
|
||||
win_emu.log.info("Exception context: address=0x%" PRIx64 ", code=0x%08X, thread=%u\n",
|
||||
exception_info->exception_record.exception_address,
|
||||
exception_info->exception_record.exception_code, exception_info->thread_id);
|
||||
exception_info->exception_record.exception_address, exception_info->exception_record.exception_code,
|
||||
exception_info->thread_id);
|
||||
}
|
||||
|
||||
void load_minidump_into_emulator(windows_emulator& win_emu, const std::filesystem::path& minidump_path)
|
||||
@@ -724,4 +703,4 @@ namespace minidump_loader
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} // namespace minidump_loader
|
||||
} // namespace minidump_loader
|
||||
|
||||
@@ -9,13 +9,20 @@ struct exported_symbol
|
||||
uint64_t address{};
|
||||
};
|
||||
|
||||
struct imported_symbol
|
||||
{
|
||||
std::string name{};
|
||||
uint64_t address{};
|
||||
};
|
||||
|
||||
using exported_symbols = std::vector<exported_symbol>;
|
||||
using imported_symbols = std::map<std::string, std::vector<imported_symbol>>;
|
||||
using address_name_mapping = std::map<uint64_t, std::string>;
|
||||
|
||||
struct mapped_section
|
||||
{
|
||||
std::string name{};
|
||||
basic_memory_region region{};
|
||||
basic_memory_region<> region{};
|
||||
};
|
||||
|
||||
struct mapped_module
|
||||
@@ -28,6 +35,7 @@ struct mapped_module
|
||||
uint64_t entry_point{};
|
||||
|
||||
exported_symbols exports{};
|
||||
imported_symbols imports{};
|
||||
address_name_mapping address_names{};
|
||||
|
||||
std::vector<mapped_section> sections{};
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace utils
|
||||
buffer.read(sym.address);
|
||||
}
|
||||
|
||||
static void serialize(buffer_serializer& buffer, const basic_memory_region& region)
|
||||
static void serialize(buffer_serializer& buffer, const basic_memory_region<>& region)
|
||||
{
|
||||
buffer.write(region.start);
|
||||
buffer.write<uint64_t>(region.length);
|
||||
buffer.write(region.permissions);
|
||||
}
|
||||
|
||||
static void deserialize(buffer_deserializer& buffer, basic_memory_region& region)
|
||||
static void deserialize(buffer_deserializer& buffer, basic_memory_region<>& region)
|
||||
{
|
||||
buffer.read(region.start);
|
||||
region.length = static_cast<size_t>(buffer.read<uint64_t>());
|
||||
@@ -91,8 +91,8 @@ module_manager::module_manager(memory_manager& memory, file_system& file_sys, ca
|
||||
{
|
||||
}
|
||||
|
||||
void module_manager::map_main_modules(const windows_path& executable_path, const windows_path& ntdll_path,
|
||||
const windows_path& win32u_path, const logger& logger)
|
||||
void module_manager::map_main_modules(const windows_path& executable_path, const windows_path& ntdll_path, const windows_path& win32u_path,
|
||||
const logger& logger)
|
||||
{
|
||||
this->executable = this->map_module(executable_path, logger, true);
|
||||
this->ntdll = this->map_module(ntdll_path, logger, true);
|
||||
@@ -104,8 +104,7 @@ mapped_module* module_manager::map_module(const windows_path& file, const logger
|
||||
return this->map_local_module(this->file_sys_->translate(file), logger, is_static);
|
||||
}
|
||||
|
||||
mapped_module* module_manager::map_local_module(const std::filesystem::path& file, const logger& logger,
|
||||
const bool is_static)
|
||||
mapped_module* module_manager::map_local_module(const std::filesystem::path& file, const logger& logger, const bool is_static)
|
||||
{
|
||||
auto local_file = weakly_canonical(absolute(file));
|
||||
|
||||
@@ -139,8 +138,8 @@ mapped_module* module_manager::map_local_module(const std::filesystem::path& fil
|
||||
}
|
||||
}
|
||||
|
||||
mapped_module* module_manager::map_memory_module(uint64_t base_address, uint64_t image_size,
|
||||
const std::string& module_name, const logger& logger, bool is_static)
|
||||
mapped_module* module_manager::map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name,
|
||||
const logger& logger, bool is_static)
|
||||
{
|
||||
for (auto& mod : this->modules_ | std::views::values)
|
||||
{
|
||||
@@ -162,14 +161,12 @@ mapped_module* module_manager::map_memory_module(uint64_t base_address, uint64_t
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
logger.error("Failed to map module from memory %s at 0x%016" PRIx64 ": %s\n", module_name.c_str(), base_address,
|
||||
e.what());
|
||||
logger.error("Failed to map module from memory %s at 0x%016" PRIx64 ": %s\n", module_name.c_str(), base_address, e.what());
|
||||
return nullptr;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
logger.error("Failed to map module from memory %s at 0x%016" PRIx64 ": Unknown error\n", module_name.c_str(),
|
||||
base_address);
|
||||
logger.error("Failed to map module from memory %s at 0x%016" PRIx64 ": Unknown error\n", module_name.c_str(), base_address);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ class module_manager
|
||||
|
||||
module_manager(memory_manager& memory, file_system& file_sys, callbacks& cb);
|
||||
|
||||
void map_main_modules(const windows_path& executable_path, const windows_path& ntdll_path,
|
||||
const windows_path& win32u_path, const logger& logger);
|
||||
void map_main_modules(const windows_path& executable_path, const windows_path& ntdll_path, const windows_path& win32u_path,
|
||||
const logger& logger);
|
||||
|
||||
mapped_module* map_module(const windows_path& file, const logger& logger, bool is_static = false);
|
||||
mapped_module* map_local_module(const std::filesystem::path& file, const logger& logger, bool is_static = false);
|
||||
mapped_module* map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name,
|
||||
const logger& logger, bool is_static = false);
|
||||
mapped_module* map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name, const logger& logger,
|
||||
bool is_static = false);
|
||||
|
||||
mapped_module* find_by_address(const uint64_t address)
|
||||
{
|
||||
@@ -39,6 +39,19 @@ class module_manager
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mapped_module* find_by_name(const std::string_view name)
|
||||
{
|
||||
for (auto& mod : this->modules_ | std::views::values)
|
||||
{
|
||||
if (mod.name == name)
|
||||
{
|
||||
return &mod;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* find_name(const uint64_t address)
|
||||
{
|
||||
const auto* mod = this->find_by_address(address);
|
||||
|
||||
@@ -29,6 +29,63 @@ namespace
|
||||
return mem;
|
||||
}
|
||||
|
||||
void collect_imports(mapped_module& binary, const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
const PEOptionalHeader_t<std::uint64_t>& optional_header)
|
||||
{
|
||||
const auto& import_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
if (import_directory_entry.VirtualAddress == 0 || import_directory_entry.Size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto import_descriptors = buffer.as<IMAGE_IMPORT_DESCRIPTOR>(import_directory_entry.VirtualAddress);
|
||||
|
||||
for (size_t i = 0;; ++i)
|
||||
{
|
||||
const auto descriptor = import_descriptors.get(i);
|
||||
if (!descriptor.Name)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const auto module_name = buffer.as_string(descriptor.Name);
|
||||
auto& imports = binary.imports[module_name];
|
||||
|
||||
auto original_thunk_data = buffer.as<IMAGE_THUNK_DATA64>(descriptor.FirstThunk);
|
||||
if (descriptor.OriginalFirstThunk)
|
||||
{
|
||||
original_thunk_data = buffer.as<IMAGE_THUNK_DATA64>(descriptor.OriginalFirstThunk);
|
||||
}
|
||||
|
||||
for (size_t j = 0;; ++j)
|
||||
{
|
||||
const auto original_thunk = original_thunk_data.get(j);
|
||||
if (!original_thunk.u1.AddressOfData)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
imported_symbol sym{};
|
||||
|
||||
static_assert(sizeof(IMAGE_THUNK_DATA64) == sizeof(uint64_t));
|
||||
const auto thunk_rva = descriptor.FirstThunk + sizeof(IMAGE_THUNK_DATA64) * j;
|
||||
sym.address = thunk_rva + binary.image_base;
|
||||
|
||||
if (IMAGE_SNAP_BY_ORDINAL64(original_thunk.u1.Ordinal))
|
||||
{
|
||||
sym.name = "#" + std::to_string(IMAGE_ORDINAL64(original_thunk.u1.Ordinal));
|
||||
}
|
||||
else
|
||||
{
|
||||
sym.name =
|
||||
buffer.as_string(static_cast<size_t>(original_thunk.u1.AddressOfData + offsetof(IMAGE_IMPORT_BY_NAME, Name)));
|
||||
}
|
||||
|
||||
imports.push_back(std::move(sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collect_exports(mapped_module& binary, const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
const PEOptionalHeader_t<std::uint64_t>& optional_header)
|
||||
{
|
||||
@@ -70,8 +127,7 @@ namespace
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_integral_v<T>)
|
||||
void apply_relocation(const utils::safe_buffer_accessor<std::byte> buffer, const uint64_t offset,
|
||||
const uint64_t delta)
|
||||
void apply_relocation(const utils::safe_buffer_accessor<std::byte> buffer, const uint64_t offset, const uint64_t delta)
|
||||
{
|
||||
const auto obj = buffer.as<T>(static_cast<size_t>(offset));
|
||||
const auto value = obj.get();
|
||||
@@ -141,8 +197,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void map_sections(memory_manager& memory, mapped_module& binary,
|
||||
const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
void map_sections(memory_manager& memory, mapped_module& binary, const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
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);
|
||||
@@ -196,8 +251,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
mapped_module map_module_from_data(memory_manager& memory, const std::span<const std::byte> data,
|
||||
std::filesystem::path file)
|
||||
mapped_module map_module_from_data(memory_manager& memory, const std::span<const std::byte> data, std::filesystem::path file)
|
||||
{
|
||||
mapped_module binary{};
|
||||
binary.path = std::move(file);
|
||||
@@ -226,8 +280,8 @@ mapped_module map_module_from_data(memory_manager& memory, const std::span<const
|
||||
const auto has_dynamic_base = optional_header.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
|
||||
const auto is_relocatable = is_dll || has_dynamic_base;
|
||||
|
||||
if (!is_relocatable || !memory.allocate_memory(binary.image_base, static_cast<size_t>(binary.size_of_image),
|
||||
memory_permission::all))
|
||||
if (!is_relocatable ||
|
||||
!memory.allocate_memory(binary.image_base, static_cast<size_t>(binary.size_of_image), memory_permission::all))
|
||||
{
|
||||
throw std::runtime_error("Memory range not allocatable");
|
||||
}
|
||||
@@ -248,6 +302,7 @@ mapped_module map_module_from_data(memory_manager& memory, const std::span<const
|
||||
|
||||
apply_relocations(binary, mapped_buffer, optional_header);
|
||||
collect_exports(binary, mapped_buffer, optional_header);
|
||||
collect_imports(binary, mapped_buffer, optional_header);
|
||||
|
||||
memory.write_memory(binary.image_base, mapped_memory.data(), mapped_memory.size());
|
||||
|
||||
@@ -265,8 +320,7 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path
|
||||
return map_module_from_data(memory, data, std::move(file));
|
||||
}
|
||||
|
||||
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size,
|
||||
const std::string& module_name)
|
||||
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size, const std::string& module_name)
|
||||
{
|
||||
mapped_module binary{};
|
||||
binary.name = module_name;
|
||||
@@ -295,8 +349,7 @@ mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_addre
|
||||
|
||||
mapped_section section_info{};
|
||||
section_info.region.start = binary.image_base + section.VirtualAddress;
|
||||
section_info.region.length =
|
||||
static_cast<size_t>(page_align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize)));
|
||||
section_info.region.length = static_cast<size_t>(page_align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize)));
|
||||
|
||||
auto permissions = memory_permission::none;
|
||||
if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
mapped_module map_module_from_data(memory_manager& memory, std::span<const uint8_t> data, std::filesystem::path file);
|
||||
mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path file);
|
||||
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size,
|
||||
const std::string& module_name);
|
||||
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size, const std::string& module_name);
|
||||
|
||||
bool unmap_module(memory_manager& memory, const mapped_module& mod);
|
||||
|
||||
@@ -37,8 +37,7 @@ namespace network
|
||||
|
||||
int val{};
|
||||
socklen_t len = sizeof(val);
|
||||
const auto res =
|
||||
getsockopt(this->socket_.get_socket(), SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&val), &len);
|
||||
const auto res = getsockopt(this->socket_.get_socket(), SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&val), &len);
|
||||
|
||||
return res != SOCKET_ERROR && val == 1;
|
||||
}
|
||||
@@ -92,27 +91,25 @@ namespace network
|
||||
|
||||
sent_size socket_wrapper::send(const std::span<const std::byte> data)
|
||||
{
|
||||
return ::send(this->socket_.get_socket(), reinterpret_cast<const char*>(data.data()),
|
||||
static_cast<send_size>(data.size()), 0);
|
||||
return ::send(this->socket_.get_socket(), reinterpret_cast<const char*>(data.data()), static_cast<send_size>(data.size()), 0);
|
||||
}
|
||||
|
||||
sent_size socket_wrapper::sendto(const address& destination, const std::span<const std::byte> data)
|
||||
{
|
||||
return ::sendto(this->socket_.get_socket(), reinterpret_cast<const char*>(data.data()),
|
||||
static_cast<send_size>(data.size()), 0, &destination.get_addr(), destination.get_size());
|
||||
return ::sendto(this->socket_.get_socket(), reinterpret_cast<const char*>(data.data()), static_cast<send_size>(data.size()), 0,
|
||||
&destination.get_addr(), destination.get_size());
|
||||
}
|
||||
|
||||
sent_size socket_wrapper::recv(std::span<std::byte> data)
|
||||
{
|
||||
return ::recv(this->socket_.get_socket(), reinterpret_cast<char*>(data.data()),
|
||||
static_cast<send_size>(data.size()), 0);
|
||||
return ::recv(this->socket_.get_socket(), reinterpret_cast<char*>(data.data()), static_cast<send_size>(data.size()), 0);
|
||||
}
|
||||
|
||||
sent_size socket_wrapper::recvfrom(address& source, std::span<std::byte> data)
|
||||
{
|
||||
auto source_length = source.get_max_size();
|
||||
const auto res = ::recvfrom(this->socket_.get_socket(), reinterpret_cast<char*>(data.data()),
|
||||
static_cast<send_size>(data.size()), 0, &source.get_addr(), &source_length);
|
||||
const auto res = ::recvfrom(this->socket_.get_socket(), reinterpret_cast<char*>(data.data()), static_cast<send_size>(data.size()),
|
||||
0, &source.get_addr(), &source_length);
|
||||
|
||||
assert(source.get_size() == source_length);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace
|
||||
|
||||
void setup_gdt(x86_64_emulator& emu, memory_manager& memory)
|
||||
{
|
||||
memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read);
|
||||
memory.allocate_memory(GDT_ADDR, static_cast<size_t>(page_align_up(GDT_LIMIT)), memory_permission::read);
|
||||
emu.load_gdt(GDT_ADDR, GDT_LIMIT);
|
||||
|
||||
emu.write_memory<uint64_t>(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF);
|
||||
@@ -73,8 +73,7 @@ namespace
|
||||
utils::unordered_insensitive_u16string_map<std::u16string> env_map;
|
||||
std::unordered_set<std::u16string_view> keys_to_expand;
|
||||
|
||||
const auto env_key =
|
||||
registry.get_key({R"(\Registry\Machine\System\CurrentControlSet\Control\Session Manager\Environment)"});
|
||||
const auto env_key = registry.get_key({R"(\Registry\Machine\System\CurrentControlSet\Control\Session Manager\Environment)"});
|
||||
if (env_key)
|
||||
{
|
||||
for (size_t i = 0; const auto value_opt = registry.get_value(*env_key, i); i++)
|
||||
@@ -98,8 +97,7 @@ namespace
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto [it, inserted] =
|
||||
env_map.emplace(u8_to_u16(value.name), std::u16string(data_ptr, char_count - 1));
|
||||
const auto [it, inserted] = env_map.emplace(u8_to_u16(value.name), std::u16string(data_ptr, char_count - 1));
|
||||
if (inserted && value.type == REG_EXPAND_SZ)
|
||||
{
|
||||
keys_to_expand.insert(it->first);
|
||||
@@ -142,8 +140,8 @@ namespace
|
||||
}
|
||||
|
||||
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry,
|
||||
const application_settings& app_settings, const mapped_module& executable,
|
||||
const mapped_module& ntdll, const apiset::container& apiset_container)
|
||||
const application_settings& app_settings, const mapped_module& executable, const mapped_module& ntdll,
|
||||
const apiset::container& apiset_container)
|
||||
{
|
||||
setup_gdt(emu, memory);
|
||||
|
||||
@@ -204,8 +202,7 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
}
|
||||
|
||||
allocator.make_unicode_string(proc_params.CommandLine, command_line);
|
||||
allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath,
|
||||
app_settings.working_directory.u16string() + u"\\", 1024);
|
||||
allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, app_settings.working_directory.u16string() + u"\\", 1024);
|
||||
allocator.make_unicode_string(proc_params.ImagePathName, application_str);
|
||||
|
||||
const auto total_length = allocator.get_next_address() - this->process_params.value();
|
||||
@@ -228,6 +225,8 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
p.HeapDeCommitFreeBlockThreshold = 0x0000000000001000;
|
||||
p.NumberOfHeaps = 0x00000000;
|
||||
p.MaximumNumberOfHeaps = 0x00000010;
|
||||
p.NumberOfProcessors = 4;
|
||||
p.ImageSubsystemMajorVersion = 6;
|
||||
|
||||
p.OSPlatformId = 2;
|
||||
p.OSMajorVersion = 0x0000000a;
|
||||
@@ -249,8 +248,6 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
|
||||
void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
buffer.write(this->shared_section_address);
|
||||
buffer.write(this->shared_section_size);
|
||||
buffer.write(this->dbwin_buffer);
|
||||
@@ -288,8 +285,6 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
|
||||
void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
buffer.read(this->shared_section_address);
|
||||
buffer.read(this->shared_section_size);
|
||||
buffer.read(this->dbwin_buffer);
|
||||
|
||||
@@ -65,12 +65,10 @@ struct process_context
|
||||
{
|
||||
}
|
||||
|
||||
void setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry,
|
||||
const application_settings& app_settings, const mapped_module& executable, const mapped_module& ntdll,
|
||||
const apiset::container& apiset_container);
|
||||
void setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry, const application_settings& app_settings,
|
||||
const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container);
|
||||
|
||||
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,
|
||||
bool suspended);
|
||||
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, bool suspended);
|
||||
|
||||
std::optional<uint16_t> find_atom(std::u16string_view name);
|
||||
uint16_t add_or_find_atom(std::u16string name);
|
||||
@@ -85,9 +83,6 @@ struct process_context
|
||||
|
||||
callbacks* callbacks_{};
|
||||
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
uint64_t shared_section_address{0};
|
||||
uint64_t shared_section_size{0};
|
||||
uint64_t dbwin_buffer{0};
|
||||
|
||||
@@ -228,8 +228,8 @@ void hive_key::parse(std::ifstream& file)
|
||||
|
||||
std::string subkey_name(subkey.name, std::min(subkey.len, static_cast<int16_t>(sizeof(subkey.name))));
|
||||
|
||||
const auto [it, inserted] = this->sub_keys_.emplace(
|
||||
std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets});
|
||||
const auto [it, inserted] =
|
||||
this->sub_keys_.emplace(std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets});
|
||||
if (inserted)
|
||||
{
|
||||
this->sub_keys_by_index_.emplace_back(it->first);
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace
|
||||
hives[key] = std::make_unique<hive_parser>(file);
|
||||
}
|
||||
|
||||
std::pair<utils::path_key, bool> perform_path_substitution(
|
||||
const std::unordered_map<utils::path_key, utils::path_key>& path_mapping, utils::path_key path)
|
||||
std::pair<utils::path_key, bool> perform_path_substitution(const std::unordered_map<utils::path_key, utils::path_key>& path_mapping,
|
||||
utils::path_key path)
|
||||
{
|
||||
for (const auto& mapping : path_mapping)
|
||||
{
|
||||
|
||||
@@ -115,10 +115,8 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
||||
}
|
||||
}
|
||||
|
||||
syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports,
|
||||
const std::span<const std::byte> ntdll_data,
|
||||
const exported_symbols& win32u_exports,
|
||||
const std::span<const std::byte> win32u_data)
|
||||
syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports, const std::span<const std::byte> ntdll_data,
|
||||
const exported_symbols& win32u_exports, const std::span<const std::byte> win32u_data)
|
||||
{
|
||||
this->setup(ntdll_exports, ntdll_data, win32u_exports, win32u_data);
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ class syscall_dispatcher
|
||||
{
|
||||
public:
|
||||
syscall_dispatcher() = default;
|
||||
syscall_dispatcher(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data,
|
||||
const exported_symbols& win32u_exports, std::span<const std::byte> win32u_data);
|
||||
syscall_dispatcher(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data, const exported_symbols& win32u_exports,
|
||||
std::span<const std::byte> win32u_data);
|
||||
|
||||
void dispatch(windows_emulator& win_emu);
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const;
|
||||
void deserialize(utils::buffer_deserializer& buffer);
|
||||
|
||||
void setup(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data,
|
||||
const exported_symbols& win32u_exports, std::span<const std::byte> win32u_data);
|
||||
void setup(const exported_symbols& ntdll_exports, std::span<const std::byte> ntdll_data, const exported_symbols& win32u_exports,
|
||||
std::span<const std::byte> win32u_data);
|
||||
|
||||
std::string get_syscall_name(const uint64_t id)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "windows_emulator.hpp"
|
||||
#include <ctime>
|
||||
#include <platform/primitives.hpp>
|
||||
#include "devices/named_pipe.hpp"
|
||||
|
||||
struct syscall_context
|
||||
{
|
||||
@@ -28,6 +29,11 @@ inline bool is_syscall(const std::string_view name)
|
||||
return name.starts_with("Nt") && name.size() > 3 && is_uppercase(name[2]);
|
||||
}
|
||||
|
||||
inline bool is_named_pipe_path(const std::u16string_view& filename)
|
||||
{
|
||||
return filename == u"\\Device\\NamedPipe\\" || filename.starts_with(u"\\Device\\NamedPipe\\");
|
||||
}
|
||||
|
||||
inline std::optional<uint32_t> extract_syscall_id(const exported_symbol& symbol, std::span<const std::byte> data)
|
||||
{
|
||||
if (!is_syscall(symbol.name))
|
||||
@@ -42,8 +48,7 @@ inline std::optional<uint32_t> extract_syscall_id(const exported_symbol& symbol,
|
||||
|
||||
const auto instruction_rva = symbol.rva + instruction_offset;
|
||||
|
||||
if (data.size() < (instruction_rva + instruction_size) ||
|
||||
data[static_cast<size_t>(instruction_rva)] != instruction_opcode)
|
||||
if (data.size() < (instruction_rva + instruction_size) || data[static_cast<size_t>(instruction_rva)] != instruction_opcode)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -68,8 +73,8 @@ inline std::map<uint64_t, std::string> find_syscalls(const exported_symbols& exp
|
||||
|
||||
if (!entry.empty())
|
||||
{
|
||||
throw std::runtime_error("Syscall with id " + std::to_string(*id) + ", which is mapping to " +
|
||||
symbol.name + ", was already mapped to " + entry);
|
||||
throw std::runtime_error("Syscall with id " + std::to_string(*id) + ", which is mapping to " + symbol.name +
|
||||
", was already mapped to " + entry);
|
||||
}
|
||||
|
||||
entry = symbol.name;
|
||||
@@ -221,8 +226,8 @@ NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, cons
|
||||
|
||||
template <typename ResponseType, typename Action, typename LengthType>
|
||||
requires(std::is_integral_v<LengthType>)
|
||||
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
|
||||
const emulator_object<LengthType> return_length, const Action& action)
|
||||
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length, const emulator_object<LengthType> return_length,
|
||||
const Action& action)
|
||||
{
|
||||
const auto length_setter = [&](const size_t required_size) {
|
||||
if (return_length)
|
||||
@@ -236,8 +241,7 @@ NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_
|
||||
|
||||
template <typename ResponseType, typename Action>
|
||||
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const Action& action)
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const Action& action)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> status_block{};
|
||||
|
||||
|
||||
@@ -18,104 +18,85 @@ namespace syscalls
|
||||
NTSTATUS handle_NtTraceEvent();
|
||||
NTSTATUS handle_NtQueryEvent();
|
||||
NTSTATUS handle_NtClearEvent(const syscall_context& c, handle event_handle);
|
||||
NTSTATUS handle_NtCreateEvent(const syscall_context& c, emulator_object<handle> event_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
EVENT_TYPE event_type, BOOLEAN initial_state);
|
||||
NTSTATUS handle_NtOpenEvent(const syscall_context& c, emulator_object<uint64_t> event_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtCreateEvent(const syscall_context& c, emulator_object<handle> event_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, EVENT_TYPE event_type,
|
||||
BOOLEAN initial_state);
|
||||
NTSTATUS handle_NtOpenEvent(const syscall_context& c, emulator_object<uint64_t> event_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
|
||||
// syscalls/exception.cpp
|
||||
NTSTATUS handle_NtRaiseHardError(
|
||||
const syscall_context& c, NTSTATUS error_status, ULONG number_of_parameters,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> unicode_string_parameter_mask,
|
||||
emulator_object<DWORD> parameters, HARDERROR_RESPONSE_OPTION valid_response_option,
|
||||
emulator_object<HARDERROR_RESPONSE> response);
|
||||
NTSTATUS handle_NtRaiseHardError(const syscall_context& c, NTSTATUS error_status, ULONG number_of_parameters,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> unicode_string_parameter_mask,
|
||||
emulator_object<DWORD> parameters, HARDERROR_RESPONSE_OPTION valid_response_option,
|
||||
emulator_object<HARDERROR_RESPONSE> response);
|
||||
NTSTATUS handle_NtRaiseException(const syscall_context& c,
|
||||
emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> exception_record,
|
||||
emulator_object<CONTEXT64> thread_context, BOOLEAN handle_exception);
|
||||
|
||||
// syscalls/file.cpp
|
||||
NTSTATUS handle_NtSetInformationFile(const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, ULONG length, FILE_INFORMATION_CLASS info_class);
|
||||
NTSTATUS handle_NtQueryVolumeInformationFile(
|
||||
const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t fs_information, ULONG length,
|
||||
FS_INFORMATION_CLASS fs_information_class);
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t file_information,
|
||||
ULONG length, FILE_INFORMATION_CLASS info_class);
|
||||
NTSTATUS handle_NtQueryVolumeInformationFile(const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t fs_information, ULONG length, FS_INFORMATION_CLASS fs_information_class);
|
||||
NTSTATUS handle_NtQueryDirectoryFileEx(const syscall_context& c, handle file_handle, handle event_handle,
|
||||
EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) apc_routine,
|
||||
emulator_pointer apc_context,
|
||||
EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) apc_routine, emulator_pointer apc_context,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class,
|
||||
ULONG query_flags,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class, ULONG query_flags,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name);
|
||||
NTSTATUS handle_NtQueryDirectoryFile(const syscall_context& c, handle file_handle, handle event_handle,
|
||||
EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) apc_routine,
|
||||
emulator_pointer apc_context,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class,
|
||||
BOOLEAN return_single_entry,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name,
|
||||
BOOLEAN restart_scan);
|
||||
EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) apc_routine, emulator_pointer apc_context,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t file_information,
|
||||
uint32_t length, uint32_t info_class, BOOLEAN return_single_entry,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name, BOOLEAN restart_scan);
|
||||
NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class);
|
||||
NTSTATUS handle_NtQueryInformationByName(
|
||||
const syscall_context& c, emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t file_information,
|
||||
uint32_t length, uint32_t info_class);
|
||||
NTSTATUS handle_NtReadFile(const syscall_context& c, handle file_handle, uint64_t /*event*/,
|
||||
uint64_t /*apc_routine*/, uint64_t /*apc_context*/,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t buffer,
|
||||
ULONG length, emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
NTSTATUS handle_NtQueryInformationByName(const syscall_context& c,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class);
|
||||
NTSTATUS handle_NtReadFile(const syscall_context& c, handle file_handle, uint64_t /*event*/, uint64_t /*apc_routine*/,
|
||||
uint64_t /*apc_context*/, emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t buffer, ULONG length, emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
emulator_object<ULONG> /*key*/);
|
||||
NTSTATUS handle_NtWriteFile(const syscall_context& c, handle file_handle, uint64_t /*event*/,
|
||||
uint64_t /*apc_routine*/, uint64_t /*apc_context*/,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
NTSTATUS handle_NtWriteFile(const syscall_context& c, handle file_handle, uint64_t /*event*/, uint64_t /*apc_routine*/,
|
||||
uint64_t /*apc_context*/, emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t buffer, ULONG length, emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
emulator_object<ULONG> /*key*/);
|
||||
NTSTATUS handle_NtCreateFile(const syscall_context& c, emulator_object<handle> file_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtCreateFile(const syscall_context& c, emulator_object<handle> file_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/,
|
||||
emulator_object<LARGE_INTEGER> /*allocation_size*/, ULONG /*file_attributes*/,
|
||||
ULONG /*share_access*/, ULONG create_disposition, ULONG create_options,
|
||||
uint64_t ea_buffer, ULONG ea_length);
|
||||
emulator_object<LARGE_INTEGER> /*allocation_size*/, ULONG /*file_attributes*/, ULONG /*share_access*/,
|
||||
ULONG create_disposition, ULONG create_options, uint64_t ea_buffer, ULONG ea_length);
|
||||
NTSTATUS handle_NtQueryAttributesFile(const syscall_context& c,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<FILE_BASIC_INFORMATION> file_information);
|
||||
NTSTATUS handle_NtQueryFullAttributesFile(
|
||||
const syscall_context& c, emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<FILE_NETWORK_OPEN_INFORMATION> file_information);
|
||||
NTSTATUS handle_NtOpenFile(const syscall_context& c, emulator_object<handle> file_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtQueryFullAttributesFile(const syscall_context& c,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<FILE_NETWORK_OPEN_INFORMATION> file_information);
|
||||
NTSTATUS handle_NtOpenFile(const syscall_context& c, emulator_object<handle> file_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
ULONG share_access, ULONG open_options);
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, ULONG share_access,
|
||||
ULONG open_options);
|
||||
NTSTATUS handle_NtOpenDirectoryObject(const syscall_context& c, emulator_object<handle> directory_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtOpenSymbolicLinkObject(
|
||||
const syscall_context& c, emulator_object<handle> link_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtOpenSymbolicLinkObject(const syscall_context& c, emulator_object<handle> link_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtQuerySymbolicLinkObject(const syscall_context& c, handle link_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> link_target,
|
||||
emulator_object<ULONG> returned_length);
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(const syscall_context& c, emulator_object<handle> file_handle,
|
||||
ULONG desired_access,
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(const syscall_context& c, emulator_object<handle> file_handle, ULONG desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
ULONG share_access, ULONG create_disposition, ULONG create_options,
|
||||
ULONG named_pipe_type, ULONG read_mode, ULONG completion_mode,
|
||||
ULONG maximum_instances, ULONG inbound_quota, ULONG outbound_quota,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, ULONG share_access,
|
||||
ULONG create_disposition, ULONG create_options, ULONG named_pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG maximum_instances, ULONG inbound_quota, ULONG outbound_quota,
|
||||
emulator_object<LARGE_INTEGER> default_timeout);
|
||||
NTSTATUS handle_NtFsControlFile(const syscall_context& c, handle event_handle, uint64_t apc_routine,
|
||||
uint64_t app_context,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
ULONG fs_control_code, uint64_t input_buffer, ULONG input_buffer_length,
|
||||
uint64_t output_buffer, ULONG output_buffer_length);
|
||||
NTSTATUS handle_NtFsControlFile(const syscall_context& c, handle event_handle, uint64_t apc_routine, uint64_t app_context,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, ULONG fs_control_code,
|
||||
uint64_t input_buffer, ULONG input_buffer_length, uint64_t output_buffer, ULONG output_buffer_length);
|
||||
NTSTATUS handle_NtFlushBuffersFile(const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/);
|
||||
|
||||
@@ -123,11 +104,9 @@ namespace syscalls
|
||||
NTSTATUS handle_NtInitializeNlsFiles(const syscall_context& c, emulator_object<uint64_t> base_address,
|
||||
emulator_object<LCID> default_locale_id,
|
||||
emulator_object<LARGE_INTEGER> /*default_casing_table_size*/);
|
||||
NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/,
|
||||
emulator_object<LCID> default_locale_id);
|
||||
NTSTATUS handle_NtGetNlsSectionPtr(const syscall_context& c, ULONG section_type, ULONG section_data,
|
||||
emulator_pointer /*context_data*/, emulator_object<uint64_t> section_pointer,
|
||||
emulator_object<ULONG> section_size);
|
||||
NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/, emulator_object<LCID> default_locale_id);
|
||||
NTSTATUS handle_NtGetNlsSectionPtr(const syscall_context& c, ULONG section_type, ULONG section_data, emulator_pointer /*context_data*/,
|
||||
emulator_object<uint64_t> section_pointer, emulator_object<ULONG> section_size);
|
||||
NTSTATUS handle_NtGetMUIRegistryInfo();
|
||||
NTSTATUS handle_NtIsUILanguageComitted();
|
||||
NTSTATUS handle_NtUserGetKeyboardLayout();
|
||||
@@ -135,23 +114,19 @@ namespace syscalls
|
||||
NTSTATUS handle_NtQueryInstallUILanguage(const syscall_context&, emulator_object<LANGID> language_id);
|
||||
|
||||
// syscalls/memory.cpp:
|
||||
NTSTATUS handle_NtQueryVirtualMemory(const syscall_context& c, handle process_handle, uint64_t base_address,
|
||||
uint32_t info_class, uint64_t memory_information,
|
||||
uint64_t memory_information_length, emulator_object<uint64_t> return_length);
|
||||
NTSTATUS handle_NtProtectVirtualMemory(const syscall_context& c, handle process_handle,
|
||||
emulator_object<uint64_t> base_address,
|
||||
NTSTATUS handle_NtQueryVirtualMemory(const syscall_context& c, handle process_handle, uint64_t base_address, uint32_t info_class,
|
||||
uint64_t memory_information, uint64_t memory_information_length,
|
||||
emulator_object<uint64_t> return_length);
|
||||
NTSTATUS handle_NtProtectVirtualMemory(const syscall_context& c, handle process_handle, emulator_object<uint64_t> base_address,
|
||||
emulator_object<uint32_t> bytes_to_protect, uint32_t protection,
|
||||
emulator_object<uint32_t> old_protection);
|
||||
NTSTATUS handle_NtAllocateVirtualMemoryEx(const syscall_context& c, handle process_handle,
|
||||
emulator_object<uint64_t> base_address,
|
||||
NTSTATUS handle_NtAllocateVirtualMemoryEx(const syscall_context& c, handle process_handle, emulator_object<uint64_t> base_address,
|
||||
emulator_object<uint64_t> bytes_to_allocate, uint32_t allocation_type,
|
||||
uint32_t page_protection);
|
||||
NTSTATUS handle_NtAllocateVirtualMemory(const syscall_context& c, handle process_handle,
|
||||
emulator_object<uint64_t> base_address, uint64_t zero_bits,
|
||||
emulator_object<uint64_t> bytes_to_allocate, uint32_t allocation_type,
|
||||
NTSTATUS handle_NtAllocateVirtualMemory(const syscall_context& c, handle process_handle, emulator_object<uint64_t> base_address,
|
||||
uint64_t zero_bits, emulator_object<uint64_t> bytes_to_allocate, uint32_t allocation_type,
|
||||
uint32_t page_protection);
|
||||
NTSTATUS handle_NtFreeVirtualMemory(const syscall_context& c, handle process_handle,
|
||||
emulator_object<uint64_t> base_address,
|
||||
NTSTATUS handle_NtFreeVirtualMemory(const syscall_context& c, handle process_handle, emulator_object<uint64_t> base_address,
|
||||
emulator_object<uint64_t> bytes_to_allocate, uint32_t free_type);
|
||||
NTSTATUS handle_NtReadVirtualMemory(const syscall_context& c, handle process_handle, emulator_pointer base_address,
|
||||
emulator_pointer buffer, ULONG number_of_bytes_to_read,
|
||||
@@ -159,35 +134,26 @@ namespace syscalls
|
||||
NTSTATUS handle_NtSetInformationVirtualMemory();
|
||||
|
||||
// syscalls/mutant.cpp:
|
||||
NTSTATUS handle_NtReleaseMutant(const syscall_context& c, handle mutant_handle,
|
||||
emulator_object<LONG> previous_count);
|
||||
NTSTATUS handle_NtOpenMutant(const syscall_context& c, emulator_object<handle> mutant_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtReleaseMutant(const syscall_context& c, handle mutant_handle, emulator_object<LONG> previous_count);
|
||||
NTSTATUS handle_NtOpenMutant(const syscall_context& c, emulator_object<handle> mutant_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtCreateMutant(const syscall_context& c, emulator_object<handle> mutant_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
BOOLEAN initial_owner);
|
||||
NTSTATUS handle_NtCreateMutant(const syscall_context& c, emulator_object<handle> mutant_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, BOOLEAN initial_owner);
|
||||
|
||||
// syscalls/object.cpp:
|
||||
NTSTATUS handle_NtClose(const syscall_context& c, handle h);
|
||||
NTSTATUS handle_NtDuplicateObject(const syscall_context& c, handle source_process_handle, handle source_handle,
|
||||
handle target_process_handle, emulator_object<handle> target_handle,
|
||||
ACCESS_MASK desired_access, ULONG handle_attributes, ULONG options);
|
||||
NTSTATUS handle_NtQueryObject(const syscall_context& c, handle handle,
|
||||
OBJECT_INFORMATION_CLASS object_information_class,
|
||||
handle target_process_handle, emulator_object<handle> target_handle, ACCESS_MASK desired_access,
|
||||
ULONG handle_attributes, ULONG options);
|
||||
NTSTATUS handle_NtQueryObject(const syscall_context& c, handle handle, OBJECT_INFORMATION_CLASS object_information_class,
|
||||
emulator_pointer object_information, ULONG object_information_length,
|
||||
emulator_object<ULONG> return_length);
|
||||
NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, ULONG count, emulator_object<handle> handles,
|
||||
WAIT_TYPE wait_type, BOOLEAN alertable,
|
||||
emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtWaitForSingleObject(const syscall_context& c, handle h, BOOLEAN alertable,
|
||||
emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, ULONG count, emulator_object<handle> handles, WAIT_TYPE wait_type,
|
||||
BOOLEAN alertable, emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtWaitForSingleObject(const syscall_context& c, handle h, BOOLEAN alertable, emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtSetInformationObject();
|
||||
NTSTATUS handle_NtQuerySecurityObject(const syscall_context& c, handle /*h*/,
|
||||
SECURITY_INFORMATION /*security_information*/,
|
||||
emulator_pointer security_descriptor, ULONG length,
|
||||
emulator_object<ULONG> length_needed);
|
||||
NTSTATUS handle_NtQuerySecurityObject(const syscall_context& c, handle /*h*/, SECURITY_INFORMATION /*security_information*/,
|
||||
emulator_pointer security_descriptor, ULONG length, emulator_object<ULONG> length_needed);
|
||||
|
||||
// syscalls/port.cpp:
|
||||
NTSTATUS handle_NtConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
@@ -200,8 +166,7 @@ namespace syscalls
|
||||
NTSTATUS handle_NtSecureConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
|
||||
emulator_object<SECURITY_QUALITY_OF_SERVICE> security_qos,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory,
|
||||
emulator_pointer /*server_sid*/,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory, emulator_pointer /*server_sid*/,
|
||||
emulator_object<REMOTE_PORT_VIEW64> server_shared_memory,
|
||||
emulator_object<ULONG> maximum_message_length, emulator_pointer connection_info,
|
||||
emulator_object<ULONG> connection_info_length);
|
||||
@@ -215,6 +180,7 @@ namespace syscalls
|
||||
/*receive_message_attributes*/,
|
||||
emulator_object<LARGE_INTEGER> /*timeout*/);
|
||||
NTSTATUS handle_NtAlpcConnectPort();
|
||||
NTSTATUS handle_NtAlpcConnectPortEx();
|
||||
|
||||
// syscalls/process.cpp:
|
||||
NTSTATUS handle_NtQueryInformationProcess(const syscall_context& c, handle process_handle, uint32_t info_class,
|
||||
@@ -230,42 +196,34 @@ namespace syscalls
|
||||
NTSTATUS handle_NtTerminateProcess(const syscall_context& c, handle process_handle, NTSTATUS exit_status);
|
||||
|
||||
// syscalls/registry.cpp:
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, emulator_object<handle> key_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, emulator_object<handle> key_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, emulator_object<handle> key_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG /*open_options*/);
|
||||
NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, emulator_object<handle> key_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*open_options*/);
|
||||
NTSTATUS handle_NtQueryKey(const syscall_context& c, handle key_handle, KEY_INFORMATION_CLASS key_information_class,
|
||||
uint64_t key_information, ULONG length, emulator_object<ULONG> result_length);
|
||||
NTSTATUS handle_NtQueryValueKey(const syscall_context& c, handle key_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> value_name,
|
||||
KEY_VALUE_INFORMATION_CLASS key_value_information_class,
|
||||
uint64_t key_value_information, ULONG length, emulator_object<ULONG> result_length);
|
||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, emulator_object<handle> key_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG /*title_index*/, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
|
||||
ULONG /*create_options*/, emulator_object<ULONG> /*disposition*/);
|
||||
KEY_VALUE_INFORMATION_CLASS key_value_information_class, uint64_t key_value_information, ULONG length,
|
||||
emulator_object<ULONG> result_length);
|
||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, emulator_object<handle> key_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*title_index*/,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/, ULONG /*create_options*/,
|
||||
emulator_object<ULONG> /*disposition*/);
|
||||
NTSTATUS handle_NtNotifyChangeKey();
|
||||
NTSTATUS handle_NtSetInformationKey();
|
||||
NTSTATUS handle_NtEnumerateKey(const syscall_context& c, handle key_handle, ULONG index,
|
||||
KEY_INFORMATION_CLASS key_information_class, uint64_t key_information, ULONG length,
|
||||
emulator_object<ULONG> result_length);
|
||||
NTSTATUS handle_NtEnumerateKey(const syscall_context& c, handle key_handle, ULONG index, KEY_INFORMATION_CLASS key_information_class,
|
||||
uint64_t key_information, ULONG length, emulator_object<ULONG> result_length);
|
||||
NTSTATUS handle_NtEnumerateValueKey(const syscall_context& c, handle key_handle, ULONG index,
|
||||
KEY_VALUE_INFORMATION_CLASS key_value_information_class,
|
||||
uint64_t key_value_information, ULONG length,
|
||||
emulator_object<ULONG> result_length);
|
||||
KEY_VALUE_INFORMATION_CLASS key_value_information_class, uint64_t key_value_information,
|
||||
ULONG length, emulator_object<ULONG> result_length);
|
||||
|
||||
// syscalls/section.cpp:
|
||||
NTSTATUS handle_NtCreateSection(const syscall_context& c, emulator_object<handle> section_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtCreateSection(const syscall_context& c, emulator_object<handle> section_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<ULARGE_INTEGER> maximum_size, ULONG section_page_protection,
|
||||
ULONG allocation_attributes, handle file_handle);
|
||||
NTSTATUS handle_NtOpenSection(const syscall_context& c, emulator_object<handle> section_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtOpenSection(const syscall_context& c, emulator_object<handle> section_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtMapViewOfSection(const syscall_context& c, handle section_handle, handle process_handle,
|
||||
emulator_object<uint64_t> base_address,
|
||||
@@ -273,32 +231,26 @@ namespace syscalls
|
||||
EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T) /*commit_size*/,
|
||||
emulator_object<LARGE_INTEGER> /*section_offset*/,
|
||||
emulator_object<EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T)> view_size,
|
||||
SECTION_INHERIT /*inherit_disposition*/, ULONG /*allocation_type*/,
|
||||
ULONG /*win32_protect*/);
|
||||
SECTION_INHERIT /*inherit_disposition*/, ULONG /*allocation_type*/, ULONG /*win32_protect*/);
|
||||
NTSTATUS handle_NtUnmapViewOfSection(const syscall_context& c, handle process_handle, uint64_t base_address);
|
||||
NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, handle process_handle, uint64_t base_address,
|
||||
ULONG /*flags*/);
|
||||
NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, handle process_handle, uint64_t base_address, ULONG /*flags*/);
|
||||
NTSTATUS handle_NtAreMappedFilesTheSame();
|
||||
|
||||
// syscalls/semaphore.cpp:
|
||||
NTSTATUS handle_NtOpenSemaphore(const syscall_context& c, emulator_object<handle> semaphore_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtOpenSemaphore(const syscall_context& c, emulator_object<handle> semaphore_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes);
|
||||
NTSTATUS handle_NtReleaseSemaphore(const syscall_context& c, handle semaphore_handle, ULONG release_count,
|
||||
emulator_object<LONG> previous_count);
|
||||
NTSTATUS handle_NtCreateSemaphore(const syscall_context& c, emulator_object<handle> semaphore_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG initial_count, ULONG maximum_count);
|
||||
NTSTATUS handle_NtCreateSemaphore(const syscall_context& c, emulator_object<handle> semaphore_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG initial_count,
|
||||
ULONG maximum_count);
|
||||
|
||||
// syscalls/system.cpp:
|
||||
NTSTATUS handle_NtQuerySystemInformation(const syscall_context& c, uint32_t info_class, uint64_t system_information,
|
||||
uint32_t system_information_length,
|
||||
emulator_object<uint32_t> return_length);
|
||||
uint32_t system_information_length, emulator_object<uint32_t> return_length);
|
||||
NTSTATUS handle_NtQuerySystemInformationEx(const syscall_context& c, uint32_t info_class, uint64_t input_buffer,
|
||||
uint32_t input_buffer_length, uint64_t system_information,
|
||||
uint32_t system_information_length,
|
||||
emulator_object<uint32_t> return_length);
|
||||
uint32_t system_information_length, emulator_object<uint32_t> return_length);
|
||||
NTSTATUS handle_NtSetSystemInformation();
|
||||
|
||||
// syscalls/thread.cpp:
|
||||
@@ -313,64 +265,48 @@ namespace syscalls
|
||||
emulator_pointer /*client_id*/);
|
||||
NTSTATUS handle_NtOpenThreadToken(const syscall_context&, handle thread_handle, ACCESS_MASK /*desired_access*/,
|
||||
BOOLEAN /*open_as_self*/, emulator_object<handle> token_handle);
|
||||
NTSTATUS handle_NtOpenThreadTokenEx(const syscall_context& c, handle thread_handle, ACCESS_MASK desired_access,
|
||||
BOOLEAN open_as_self, ULONG /*handle_attributes*/,
|
||||
emulator_object<handle> token_handle);
|
||||
NTSTATUS handle_NtOpenThreadTokenEx(const syscall_context& c, handle thread_handle, ACCESS_MASK desired_access, BOOLEAN open_as_self,
|
||||
ULONG /*handle_attributes*/, emulator_object<handle> token_handle);
|
||||
NTSTATUS handle_NtTerminateThread(const syscall_context& c, handle thread_handle, NTSTATUS exit_status);
|
||||
NTSTATUS handle_NtDelayExecution(const syscall_context& c, BOOLEAN alertable,
|
||||
emulator_object<LARGE_INTEGER> delay_interval);
|
||||
NTSTATUS handle_NtDelayExecution(const syscall_context& c, BOOLEAN alertable, emulator_object<LARGE_INTEGER> delay_interval);
|
||||
NTSTATUS handle_NtAlertThreadByThreadId(const syscall_context& c, uint64_t thread_id);
|
||||
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, uint64_t thread_id,
|
||||
emulator_object<EMU_RTL_SRWLOCK<EmulatorTraits<Emu64>>> lock);
|
||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, uint64_t,
|
||||
emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, uint64_t, emulator_object<LARGE_INTEGER> timeout);
|
||||
NTSTATUS handle_NtYieldExecution(const syscall_context& c);
|
||||
NTSTATUS handle_NtResumeThread(const syscall_context& c, handle thread_handle,
|
||||
emulator_object<ULONG> previous_suspend_count);
|
||||
NTSTATUS handle_NtContinue(const syscall_context& c, emulator_object<CONTEXT64> thread_context,
|
||||
BOOLEAN raise_alert);
|
||||
NTSTATUS handle_NtContinueEx(const syscall_context& c, emulator_object<CONTEXT64> thread_context,
|
||||
uint64_t continue_argument);
|
||||
NTSTATUS handle_NtGetNextThread(const syscall_context& c, handle process_handle, handle thread_handle,
|
||||
ACCESS_MASK /*desired_access*/, ULONG /*handle_attributes*/, ULONG flags,
|
||||
emulator_object<handle> new_thread_handle);
|
||||
NTSTATUS handle_NtGetContextThread(const syscall_context& c, handle thread_handle,
|
||||
emulator_object<CONTEXT64> thread_context);
|
||||
NTSTATUS handle_NtSetContextThread(const syscall_context& c, handle thread_handle,
|
||||
emulator_object<CONTEXT64> thread_context);
|
||||
NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, emulator_object<handle> thread_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtResumeThread(const syscall_context& c, handle thread_handle, emulator_object<ULONG> previous_suspend_count);
|
||||
NTSTATUS handle_NtContinue(const syscall_context& c, emulator_object<CONTEXT64> thread_context, BOOLEAN raise_alert);
|
||||
NTSTATUS handle_NtContinueEx(const syscall_context& c, emulator_object<CONTEXT64> thread_context, uint64_t continue_argument);
|
||||
NTSTATUS handle_NtGetNextThread(const syscall_context& c, handle process_handle, handle thread_handle, ACCESS_MASK /*desired_access*/,
|
||||
ULONG /*handle_attributes*/, ULONG flags, emulator_object<handle> new_thread_handle);
|
||||
NTSTATUS handle_NtGetContextThread(const syscall_context& c, handle thread_handle, emulator_object<CONTEXT64> thread_context);
|
||||
NTSTATUS handle_NtSetContextThread(const syscall_context& c, handle thread_handle, emulator_object<CONTEXT64> thread_context);
|
||||
NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, emulator_object<handle> thread_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
|
||||
/*object_attributes*/,
|
||||
handle process_handle, uint64_t start_routine, uint64_t argument,
|
||||
ULONG create_flags, EmulatorTraits<Emu64>::SIZE_T /*zero_bits*/,
|
||||
EmulatorTraits<Emu64>::SIZE_T stack_size,
|
||||
handle process_handle, uint64_t start_routine, uint64_t argument, ULONG create_flags,
|
||||
EmulatorTraits<Emu64>::SIZE_T /*zero_bits*/, EmulatorTraits<Emu64>::SIZE_T stack_size,
|
||||
EmulatorTraits<Emu64>::SIZE_T /*maximum_stack_size*/,
|
||||
emulator_object<PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>> attribute_list);
|
||||
NTSTATUS handle_NtGetCurrentProcessorNumberEx(const syscall_context&,
|
||||
emulator_object<PROCESSOR_NUMBER> processor_number);
|
||||
NTSTATUS handle_NtGetCurrentProcessorNumberEx(const syscall_context&, emulator_object<PROCESSOR_NUMBER> processor_number);
|
||||
ULONG handle_NtGetCurrentProcessorNumber();
|
||||
NTSTATUS handle_NtQueueApcThreadEx2(const syscall_context& c, handle thread_handle, handle reserve_handle,
|
||||
uint32_t apc_flags, uint64_t apc_routine, uint64_t apc_argument1,
|
||||
uint64_t apc_argument2, uint64_t apc_argument3);
|
||||
NTSTATUS handle_NtQueueApcThreadEx(const syscall_context& c, handle thread_handle, handle reserve_handle,
|
||||
uint64_t apc_routine, uint64_t apc_argument1, uint64_t apc_argument2,
|
||||
uint64_t apc_argument3);
|
||||
NTSTATUS handle_NtQueueApcThread(const syscall_context& c, handle thread_handle, uint64_t apc_routine,
|
||||
uint64_t apc_argument1, uint64_t apc_argument2, uint64_t apc_argument3);
|
||||
NTSTATUS handle_NtQueueApcThreadEx2(const syscall_context& c, handle thread_handle, handle reserve_handle, uint32_t apc_flags,
|
||||
uint64_t apc_routine, uint64_t apc_argument1, uint64_t apc_argument2, uint64_t apc_argument3);
|
||||
NTSTATUS handle_NtQueueApcThreadEx(const syscall_context& c, handle thread_handle, handle reserve_handle, uint64_t apc_routine,
|
||||
uint64_t apc_argument1, uint64_t apc_argument2, uint64_t apc_argument3);
|
||||
NTSTATUS handle_NtQueueApcThread(const syscall_context& c, handle thread_handle, uint64_t apc_routine, uint64_t apc_argument1,
|
||||
uint64_t apc_argument2, uint64_t apc_argument3);
|
||||
|
||||
// syscalls/timer.cpp:
|
||||
NTSTATUS handle_NtQueryTimerResolution(const syscall_context&, emulator_object<ULONG> maximum_time,
|
||||
emulator_object<ULONG> minimum_time, emulator_object<ULONG> current_time);
|
||||
NTSTATUS handle_NtQueryTimerResolution(const syscall_context&, emulator_object<ULONG> maximum_time, emulator_object<ULONG> minimum_time,
|
||||
emulator_object<ULONG> current_time);
|
||||
NTSTATUS handle_NtSetTimerResolution(const syscall_context&, ULONG /*desired_resolution*/, BOOLEAN set_resolution,
|
||||
emulator_object<ULONG> current_resolution);
|
||||
NTSTATUS handle_NtCreateTimer2(const syscall_context& c, emulator_object<handle> timer_handle, uint64_t reserved,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG attributes, ACCESS_MASK desired_access);
|
||||
NTSTATUS handle_NtCreateTimer(const syscall_context& c, emulator_object<handle> timer_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG timer_type);
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG attributes,
|
||||
ACCESS_MASK desired_access);
|
||||
NTSTATUS handle_NtCreateTimer(const syscall_context& c, emulator_object<handle> timer_handle, ACCESS_MASK desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG timer_type);
|
||||
NTSTATUS handle_NtSetTimer();
|
||||
NTSTATUS handle_NtSetTimer2();
|
||||
NTSTATUS handle_NtSetTimerEx(const syscall_context& c, handle timer_handle, uint32_t timer_set_info_class,
|
||||
@@ -383,22 +319,20 @@ namespace syscalls
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
|
||||
/*object_attributes*/,
|
||||
BOOLEAN /*effective_only*/, TOKEN_TYPE type, emulator_object<handle> new_token_handle);
|
||||
NTSTATUS handle_NtQueryInformationToken(const syscall_context& c, handle token_handle,
|
||||
TOKEN_INFORMATION_CLASS token_information_class, uint64_t token_information,
|
||||
ULONG token_information_length, emulator_object<ULONG> return_length);
|
||||
NTSTATUS handle_NtQueryInformationToken(const syscall_context& c, handle token_handle, TOKEN_INFORMATION_CLASS token_information_class,
|
||||
uint64_t token_information, ULONG token_information_length,
|
||||
emulator_object<ULONG> return_length);
|
||||
NTSTATUS handle_NtQuerySecurityAttributesToken();
|
||||
|
||||
NTSTATUS handle_NtQueryPerformanceCounter(const syscall_context& c,
|
||||
const emulator_object<LARGE_INTEGER> performance_counter,
|
||||
NTSTATUS handle_NtQueryPerformanceCounter(const syscall_context& c, const emulator_object<LARGE_INTEGER> performance_counter,
|
||||
const emulator_object<LARGE_INTEGER> performance_frequency)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (performance_counter)
|
||||
{
|
||||
performance_counter.access([&](LARGE_INTEGER& value) {
|
||||
value.QuadPart = c.win_emu.clock().steady_now().time_since_epoch().count();
|
||||
});
|
||||
performance_counter.access(
|
||||
[&](LARGE_INTEGER& value) { value.QuadPart = c.win_emu.clock().steady_now().time_since_epoch().count(); });
|
||||
}
|
||||
|
||||
if (performance_frequency)
|
||||
@@ -436,10 +370,15 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateIoCompletion(
|
||||
const syscall_context& c, const emulator_object<handle> event_handle, const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const uint32_t /*number_of_concurrent_threads*/)
|
||||
NTSTATUS handle_NtReleaseWorkerFactoryWorker()
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateIoCompletion(const syscall_context& c, const emulator_object<handle> event_handle,
|
||||
const ACCESS_MASK desired_access,
|
||||
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);
|
||||
}
|
||||
@@ -449,11 +388,10 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtRemoveIoCompletion(
|
||||
const syscall_context&, const emulator_object<handle> /*io_completion__handle*/,
|
||||
const emulator_object<int64_t> key_context, const emulator_pointer /*apc_context*/,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/,
|
||||
const emulator_object<LARGE_INTEGER> timeout)
|
||||
NTSTATUS handle_NtRemoveIoCompletion(const syscall_context&, const emulator_object<handle> /*io_completion__handle*/,
|
||||
const emulator_object<int64_t> key_context, const emulator_pointer /*apc_context*/,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/,
|
||||
const emulator_object<LARGE_INTEGER> timeout)
|
||||
{
|
||||
if (timeout && timeout.read().QuadPart == 0)
|
||||
{
|
||||
@@ -469,9 +407,9 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateWaitCompletionPacket(
|
||||
const syscall_context& c, const emulator_object<handle> event_handle, const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
NTSTATUS handle_NtCreateWaitCompletionPacket(const syscall_context& c, const emulator_object<handle> event_handle,
|
||||
const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
{
|
||||
return handle_NtCreateEvent(c, event_handle, desired_access, object_attributes, NotificationEvent, FALSE);
|
||||
}
|
||||
@@ -482,12 +420,10 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtDeviceIoControlFile(const syscall_context& c, const handle file_handle, const handle event,
|
||||
const emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine,
|
||||
const emulator_pointer apc_context,
|
||||
const emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine, const emulator_pointer apc_context,
|
||||
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,
|
||||
const ULONG output_buffer_length)
|
||||
const ULONG io_control_code, const emulator_pointer input_buffer, const ULONG input_buffer_length,
|
||||
const emulator_pointer output_buffer, const ULONG output_buffer_length)
|
||||
{
|
||||
auto* device = c.proc.devices.get(file_handle);
|
||||
if (!device)
|
||||
@@ -630,8 +566,7 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAddAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length,
|
||||
const emulator_object<RTL_ATOM> atom)
|
||||
NTSTATUS handle_NtAddAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length, const emulator_object<RTL_ATOM> atom)
|
||||
{
|
||||
return handle_NtAddAtomEx(c, atom_name, length, atom, 0);
|
||||
}
|
||||
@@ -642,8 +577,7 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFindAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length,
|
||||
const emulator_object<uint16_t> atom)
|
||||
NTSTATUS handle_NtFindAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length, const emulator_object<uint16_t> atom)
|
||||
{
|
||||
const auto name = read_string<char16_t>(c.emu, atom_name, length / 2);
|
||||
const auto index = c.proc.find_atom(name);
|
||||
@@ -697,8 +631,7 @@ namespace syscalls
|
||||
return 96;
|
||||
}
|
||||
|
||||
hdc handle_NtUserGetDCEx(const syscall_context& /*c*/, const hwnd window, const uint64_t /*clip_region*/,
|
||||
const ULONG /*flags*/)
|
||||
hdc handle_NtUserGetDCEx(const syscall_context& /*c*/, const hwnd window, const uint64_t /*clip_region*/, const ULONG /*flags*/)
|
||||
{
|
||||
return window;
|
||||
}
|
||||
@@ -781,19 +714,17 @@ namespace syscalls
|
||||
EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) pusMenuName;
|
||||
};
|
||||
|
||||
NTSTATUS handle_NtUserRegisterClassExWOW(
|
||||
const syscall_context& c, const emulator_pointer /*wnd_class_ex*/,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> class_name,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class_version*/,
|
||||
const emulator_object<CLSMENUNAME<EmulatorTraits<Emu64>>> /*class_menu_name*/, const DWORD /*function_id*/,
|
||||
const DWORD /*flags*/, const emulator_pointer /*wow*/)
|
||||
NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_pointer /*wnd_class_ex*/,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> class_name,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class_version*/,
|
||||
const emulator_object<CLSMENUNAME<EmulatorTraits<Emu64>>> /*class_menu_name*/,
|
||||
const DWORD /*function_id*/, const DWORD /*flags*/, const emulator_pointer /*wow*/)
|
||||
{
|
||||
uint16_t index = c.proc.add_or_find_atom(read_unicode_string(c.emu, class_name));
|
||||
return index;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserUnregisterClass(const syscall_context& c,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> class_name,
|
||||
NTSTATUS handle_NtUserUnregisterClass(const syscall_context& c, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> class_name,
|
||||
const emulator_pointer /*instance*/,
|
||||
const emulator_object<CLSMENUNAME<EmulatorTraits<Emu64>>> /*class_menu_name*/)
|
||||
{
|
||||
@@ -842,12 +773,10 @@ namespace syscalls
|
||||
return u8_to_u16(ansi_string);
|
||||
}
|
||||
|
||||
hwnd handle_NtUserCreateWindowEx(const syscall_context& c, const DWORD /*ex_style*/,
|
||||
const emulator_object<LARGE_STRING> class_name,
|
||||
const emulator_object<LARGE_STRING> /*cls_version*/,
|
||||
const emulator_object<LARGE_STRING> window_name, const DWORD /*style*/,
|
||||
const int x, const int y, const int width, const int height, const hwnd /*parent*/,
|
||||
const hmenu /*menu*/, const hinstance /*instance*/, const pointer /*l_param*/,
|
||||
hwnd handle_NtUserCreateWindowEx(const syscall_context& c, const DWORD /*ex_style*/, const emulator_object<LARGE_STRING> class_name,
|
||||
const emulator_object<LARGE_STRING> /*cls_version*/, const emulator_object<LARGE_STRING> window_name,
|
||||
const DWORD /*style*/, const int x, const int y, const int width, const int height,
|
||||
const hwnd /*parent*/, const hmenu /*menu*/, const hinstance /*instance*/, const pointer /*l_param*/,
|
||||
const DWORD /*flags*/, const pointer /*acbi_buffer*/)
|
||||
{
|
||||
window win{};
|
||||
@@ -920,8 +849,8 @@ namespace syscalls
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL handle_NtUserGetMessage(const syscall_context& c, const emulator_object<msg> message, const hwnd hwnd,
|
||||
const UINT msg_filter_min, const UINT msg_filter_max)
|
||||
BOOL handle_NtUserGetMessage(const syscall_context& c, const emulator_object<msg> message, const hwnd hwnd, const UINT msg_filter_min,
|
||||
const UINT msg_filter_max)
|
||||
{
|
||||
(void)c;
|
||||
(void)message;
|
||||
@@ -932,8 +861,8 @@ namespace syscalls
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL handle_NtUserPeekMessage(const syscall_context& c, const emulator_object<msg> message, const hwnd hwnd,
|
||||
const UINT msg_filter_min, const UINT msg_filter_max, const UINT remove_message)
|
||||
BOOL handle_NtUserPeekMessage(const syscall_context& c, const emulator_object<msg> message, const hwnd hwnd, const UINT msg_filter_min,
|
||||
const UINT msg_filter_max, const UINT remove_message)
|
||||
{
|
||||
(void)c;
|
||||
(void)message;
|
||||
@@ -946,10 +875,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserEnumDisplayDevices(const syscall_context& /*c*/,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> str_device,
|
||||
const DWORD dev_num,
|
||||
const emulator_object<EMU_DISPLAY_DEVICEW> display_device,
|
||||
const DWORD /*flags*/)
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> str_device, const DWORD dev_num,
|
||||
const emulator_object<EMU_DISPLAY_DEVICEW> display_device, const DWORD /*flags*/)
|
||||
{
|
||||
if (str_device && dev_num != 0)
|
||||
{
|
||||
@@ -966,9 +893,8 @@ namespace syscalls
|
||||
utils::string::copy(dev.DeviceName, u"\\\\.\\DISPLAY1");
|
||||
utils::string::copy(dev.DeviceID, u"PCI\\VEN_10DE&DEV_0000&SUBSYS_00000000&REV_A1");
|
||||
utils::string::copy(dev.DeviceString, u"Emulator Display");
|
||||
utils::string::copy(dev.DeviceKey,
|
||||
u"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{00000001-"
|
||||
u"0002-0003-0004-000000000005}\\0001");
|
||||
utils::string::copy(dev.DeviceKey, u"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{00000001-"
|
||||
u"0002-0003-0004-000000000005}\\0001");
|
||||
});
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -1125,6 +1051,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtEnumerateKey);
|
||||
add_handler(NtEnumerateValueKey);
|
||||
add_handler(NtAlpcConnectPort);
|
||||
add_handler(NtAlpcConnectPortEx);
|
||||
add_handler(NtGetNextThread);
|
||||
add_handler(NtSetInformationObject);
|
||||
add_handler(NtUserGetCursorPos);
|
||||
@@ -1185,6 +1112,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtQueryEvent);
|
||||
add_handler(NtRemoveIoCompletionEx);
|
||||
add_handler(NtCreateDebugObject);
|
||||
add_handler(NtReleaseWorkerFactoryWorker);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
@@ -4,16 +4,15 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtSetEvent(const syscall_context& c, const uint64_t handle,
|
||||
const emulator_object<LONG> previous_state)
|
||||
NTSTATUS handle_NtSetEvent(const syscall_context& c, const uint64_t handle, const emulator_object<LONG> previous_state)
|
||||
{
|
||||
if (handle == DBWIN_DATA_READY)
|
||||
{
|
||||
if (c.proc.dbwin_buffer)
|
||||
if (c.proc.dbwin_buffer && c.win_emu.callbacks.on_debug_string)
|
||||
{
|
||||
constexpr auto pid_length = 4;
|
||||
const auto debug_data = read_string<char>(c.win_emu.memory, c.proc.dbwin_buffer + pid_length);
|
||||
c.win_emu.log.info("--> Debug string: %s\n", debug_data.c_str());
|
||||
c.win_emu.callbacks.on_debug_string(debug_data);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status,
|
||||
const ULONG /*number_of_parameters*/,
|
||||
NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status, const ULONG /*number_of_parameters*/,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>
|
||||
/*unicode_string_parameter_mask*/,
|
||||
const emulator_object<DWORD> /*parameters*/,
|
||||
const HARDERROR_RESPONSE_OPTION /*valid_response_option*/,
|
||||
const emulator_object<DWORD> /*parameters*/, const HARDERROR_RESPONSE_OPTION /*valid_response_option*/,
|
||||
const emulator_object<HARDERROR_RESPONSE> response)
|
||||
{
|
||||
if (response)
|
||||
@@ -24,10 +22,9 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtRaiseException(
|
||||
const syscall_context& c,
|
||||
const emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> /*exception_record*/,
|
||||
const emulator_object<CONTEXT64> /*thread_context*/, const BOOLEAN handle_exception)
|
||||
NTSTATUS handle_NtRaiseException(const syscall_context& c,
|
||||
const emulator_object<EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>>> /*exception_record*/,
|
||||
const emulator_object<CONTEXT64> /*thread_context*/, const BOOLEAN handle_exception)
|
||||
{
|
||||
if (handle_exception)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../devices/named_pipe.hpp"
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#define fstat64 _fstat64
|
||||
#elif defined(OS_MAC)
|
||||
@@ -19,8 +21,7 @@ namespace syscalls
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::pair<utils::file_handle, NTSTATUS> open_file(const file_system& file_sys, const windows_path& path,
|
||||
const std::u16string& mode)
|
||||
std::pair<utils::file_handle, NTSTATUS> open_file(const file_system& file_sys, const windows_path& path, const std::u16string& mode)
|
||||
{
|
||||
FILE* file{};
|
||||
const auto error = open_unicode(&file, file_sys.translate(path), mode);
|
||||
@@ -48,8 +49,7 @@ namespace syscalls
|
||||
|
||||
NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle,
|
||||
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)
|
||||
const uint64_t file_information, const ULONG length, const FILE_INFORMATION_CLASS info_class)
|
||||
{
|
||||
const auto* f = c.proc.files.get(file_handle);
|
||||
if (!f)
|
||||
@@ -71,8 +71,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
const auto info = c.emu.read_memory<FILE_RENAME_INFORMATION>(file_information);
|
||||
auto new_name = read_string<char16_t>(c.emu, file_information + offsetof(FILE_RENAME_INFORMATION, FileName),
|
||||
info.FileNameLength / 2);
|
||||
auto new_name =
|
||||
read_string<char16_t>(c.emu, file_information + offsetof(FILE_RENAME_INFORMATION, FileName), info.FileNameLength / 2);
|
||||
|
||||
if (info.RootDirectory)
|
||||
{
|
||||
@@ -86,8 +86,7 @@ namespace syscalls
|
||||
new_name = root->name + (has_separator ? u"" : u"\\") + new_name;
|
||||
}
|
||||
|
||||
c.win_emu.log.warn("--> File rename requested: %s --> %s\n", u16_to_u8(f->name).c_str(),
|
||||
u16_to_u8(new_name).c_str());
|
||||
c.win_emu.log.warn("--> File rename requested: %s --> %s\n", u16_to_u8(f->name).c_str(), u16_to_u8(new_name).c_str());
|
||||
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
@@ -133,10 +132,10 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryVolumeInformationFile(
|
||||
const syscall_context& c, const handle file_handle,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const uint64_t fs_information,
|
||||
const ULONG length, const FS_INFORMATION_CLASS fs_information_class)
|
||||
NTSTATUS handle_NtQueryVolumeInformationFile(const syscall_context& c, const handle file_handle,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t fs_information, const ULONG length,
|
||||
const FS_INFORMATION_CLASS fs_information_class)
|
||||
{
|
||||
switch (fs_information_class)
|
||||
{
|
||||
@@ -175,8 +174,7 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<file_entry> scan_directory(const file_system& file_sys, const windows_path& win_path,
|
||||
const std::u16string_view file_mask)
|
||||
std::vector<file_entry> scan_directory(const file_system& file_sys, const windows_path& win_path, const std::u16string_view file_mask)
|
||||
{
|
||||
std::vector<file_entry> files{};
|
||||
|
||||
@@ -317,12 +315,12 @@ namespace syscalls
|
||||
return current_index <= enum_state.files.size() ? STATUS_SUCCESS : STATUS_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryDirectoryFileEx(
|
||||
const syscall_context& c, const handle file_handle, const handle /*event_handle*/,
|
||||
const EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) /*apc_routine*/, const emulator_pointer /*apc_context*/,
|
||||
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, const ULONG query_flags,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name)
|
||||
NTSTATUS handle_NtQueryDirectoryFileEx(const syscall_context& c, const handle file_handle, const handle /*event_handle*/,
|
||||
const EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) /*apc_routine*/,
|
||||
const emulator_pointer /*apc_context*/,
|
||||
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,
|
||||
const ULONG query_flags, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name)
|
||||
{
|
||||
auto* f = c.proc.files.get(file_handle);
|
||||
if (!f || !f->is_directory())
|
||||
@@ -332,20 +330,20 @@ namespace syscalls
|
||||
|
||||
if (info_class == FileDirectoryInformation)
|
||||
{
|
||||
return handle_file_enumeration<FILE_DIRECTORY_INFORMATION>(c, io_status_block, file_information, length,
|
||||
query_flags, file_name, f);
|
||||
return handle_file_enumeration<FILE_DIRECTORY_INFORMATION>(c, io_status_block, file_information, length, query_flags, file_name,
|
||||
f);
|
||||
}
|
||||
|
||||
if (info_class == FileFullDirectoryInformation)
|
||||
{
|
||||
return handle_file_enumeration<FILE_FULL_DIR_INFORMATION>(c, io_status_block, file_information, length,
|
||||
query_flags, file_name, f);
|
||||
return handle_file_enumeration<FILE_FULL_DIR_INFORMATION>(c, io_status_block, file_information, length, query_flags, file_name,
|
||||
f);
|
||||
}
|
||||
|
||||
if (info_class == FileBothDirectoryInformation)
|
||||
{
|
||||
return handle_file_enumeration<FILE_BOTH_DIR_INFORMATION>(c, io_status_block, file_information, length,
|
||||
query_flags, file_name, f);
|
||||
return handle_file_enumeration<FILE_BOTH_DIR_INFORMATION>(c, io_status_block, file_information, length, query_flags, file_name,
|
||||
f);
|
||||
}
|
||||
|
||||
c.win_emu.log.error("Unsupported query directory file info class: %X\n", info_class);
|
||||
@@ -358,10 +356,9 @@ namespace syscalls
|
||||
const EMULATOR_CAST(emulator_pointer, PIO_APC_ROUTINE) apc_routine,
|
||||
const emulator_pointer apc_context,
|
||||
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, const BOOLEAN return_single_entry,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name,
|
||||
const BOOLEAN restart_scan)
|
||||
const uint64_t file_information, const uint32_t length, const uint32_t info_class,
|
||||
const BOOLEAN return_single_entry,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> file_name, const BOOLEAN restart_scan)
|
||||
{
|
||||
ULONG query_flags = 0;
|
||||
if (return_single_entry)
|
||||
@@ -372,14 +369,13 @@ namespace syscalls
|
||||
{
|
||||
query_flags |= SL_RESTART_SCAN;
|
||||
}
|
||||
return handle_NtQueryDirectoryFileEx(c, file_handle, event_handle, apc_routine, apc_context, io_status_block,
|
||||
file_information, length, info_class, query_flags, file_name);
|
||||
return handle_NtQueryDirectoryFileEx(c, file_handle, event_handle, apc_routine, apc_context, io_status_block, file_information,
|
||||
length, info_class, query_flags, file_name);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInformationFile(
|
||||
const syscall_context& c, const handle file_handle,
|
||||
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)
|
||||
NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, const handle file_handle,
|
||||
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)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Status = STATUS_SUCCESS;
|
||||
@@ -537,10 +533,10 @@ namespace syscalls
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInformationByName(
|
||||
const syscall_context& c, const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
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)
|
||||
NTSTATUS handle_NtQueryInformationByName(const syscall_context& c,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
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)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Status = STATUS_SUCCESS;
|
||||
@@ -604,8 +600,7 @@ namespace syscalls
|
||||
}
|
||||
|
||||
void commit_file_data(const std::string_view data, emulator& emu,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t buffer)
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const uint64_t buffer)
|
||||
{
|
||||
if (io_status_block)
|
||||
{
|
||||
@@ -617,11 +612,10 @@ namespace syscalls
|
||||
emu.write_memory(buffer, data.data(), data.size());
|
||||
}
|
||||
|
||||
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<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t buffer, const ULONG length,
|
||||
const emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
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<EmulatorTraits<Emu64>>> io_status_block, const uint64_t buffer,
|
||||
const ULONG length, const emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
const emulator_object<ULONG> /*key*/)
|
||||
{
|
||||
std::string temp_buffer{};
|
||||
@@ -637,15 +631,41 @@ namespace syscalls
|
||||
|
||||
std::cin.putback(chr);
|
||||
|
||||
const auto read_count =
|
||||
std::cin.readsome(temp_buffer.data(), static_cast<std::streamsize>(temp_buffer.size()));
|
||||
const auto read_count = std::cin.readsome(temp_buffer.data(), static_cast<std::streamsize>(temp_buffer.size()));
|
||||
const auto count = std::max(read_count, static_cast<std::streamsize>(0));
|
||||
|
||||
commit_file_data(std::string_view(temp_buffer.data(), static_cast<size_t>(count)), c.emu, io_status_block,
|
||||
buffer);
|
||||
commit_file_data(std::string_view(temp_buffer.data(), static_cast<size_t>(count)), c.emu, io_status_block, buffer);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const auto* container = c.proc.devices.get(file_handle);
|
||||
if (container)
|
||||
{
|
||||
if (auto* pipe = container->get_internal_device<named_pipe>())
|
||||
{
|
||||
if (!pipe->write_queue.empty())
|
||||
{
|
||||
std::string_view data = pipe->write_queue.front();
|
||||
const size_t to_copy = std::min<size_t>(data.size(), length);
|
||||
|
||||
commit_file_data(data.substr(0, to_copy), c.emu, io_status_block, buffer);
|
||||
|
||||
if (to_copy == data.size())
|
||||
{
|
||||
pipe->write_queue.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
pipe->write_queue.front().erase(0, to_copy);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_PIPE_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* f = c.proc.files.get(file_handle);
|
||||
if (!f)
|
||||
{
|
||||
@@ -660,9 +680,8 @@ namespace syscalls
|
||||
|
||||
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<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t buffer, const ULONG length,
|
||||
const emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const uint64_t buffer,
|
||||
const ULONG length, const emulator_object<LARGE_INTEGER> /*byte_offset*/,
|
||||
const emulator_object<ULONG> /*key*/)
|
||||
{
|
||||
std::string temp_buffer{};
|
||||
@@ -683,6 +702,27 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const auto* container = c.proc.devices.get(file_handle);
|
||||
if (container)
|
||||
{
|
||||
if (auto* pipe = container->get_internal_device<named_pipe>())
|
||||
{
|
||||
(void)pipe; // For future use: suppressing compiler issues
|
||||
// TODO c.win_emu.callbacks.on_named_pipe_write(pipe->name, temp_buffer);
|
||||
|
||||
// TODO pipe->write_queue.push_back(temp_buffer);
|
||||
|
||||
if (io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = static_cast<ULONG>(temp_buffer.size());
|
||||
io_status_block.write(block);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* f = c.proc.files.get(file_handle);
|
||||
if (!f)
|
||||
{
|
||||
@@ -777,17 +817,47 @@ namespace syscalls
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object<handle> file_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_named_pipe_create(const syscall_context& c, const emulator_object<handle>& out_handle,
|
||||
const std::u16string_view filename, const OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>& attributes,
|
||||
ACCESS_MASK desired_access)
|
||||
{
|
||||
(void)attributes; // This isn't being consumed atm, suppressing errors
|
||||
|
||||
c.win_emu.callbacks.on_generic_access("Creating/opening named pipe", filename);
|
||||
|
||||
io_device_creation_data data{};
|
||||
|
||||
std::u16string device_name = u"NamedPipe";
|
||||
|
||||
io_device_container container{device_name, c.win_emu, data};
|
||||
|
||||
if (auto* pipe_device = container.get_internal_device<named_pipe>())
|
||||
{
|
||||
pipe_device->name = std::u16string(filename);
|
||||
pipe_device->access = desired_access;
|
||||
}
|
||||
|
||||
const auto handle = c.proc.devices.store(std::move(container));
|
||||
out_handle.write(handle);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object<handle> file_handle, ACCESS_MASK desired_access,
|
||||
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, ULONG ea_length)
|
||||
ULONG /*share_access*/, ULONG create_disposition, ULONG create_options, uint64_t ea_buffer,
|
||||
ULONG ea_length)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
|
||||
if (is_named_pipe_path(filename))
|
||||
{
|
||||
return handle_named_pipe_create(c, file_handle, filename, attributes, desired_access);
|
||||
}
|
||||
|
||||
auto printer = utils::finally([&] {
|
||||
c.win_emu.callbacks.on_generic_access("Opening file", filename); //
|
||||
});
|
||||
@@ -885,9 +955,9 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryFullAttributesFile(
|
||||
const syscall_context& c, const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const emulator_object<FILE_NETWORK_OPEN_INFORMATION> file_information)
|
||||
NTSTATUS handle_NtQueryFullAttributesFile(const syscall_context& c,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const emulator_object<FILE_NETWORK_OPEN_INFORMATION> file_information)
|
||||
{
|
||||
if (!object_attributes)
|
||||
{
|
||||
@@ -900,8 +970,7 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto filename = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
auto filename = read_unicode_string(c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
|
||||
if (attributes.RootDirectory)
|
||||
{
|
||||
@@ -938,9 +1007,9 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryAttributesFile(
|
||||
const syscall_context& c, const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const emulator_object<FILE_BASIC_INFORMATION> file_information)
|
||||
NTSTATUS handle_NtQueryAttributesFile(const syscall_context& c,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const emulator_object<FILE_BASIC_INFORMATION> file_information)
|
||||
{
|
||||
if (!object_attributes)
|
||||
{
|
||||
@@ -953,8 +1022,8 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto filename = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
const auto filename =
|
||||
read_unicode_string(c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
|
||||
c.win_emu.callbacks.on_generic_access("Querying file attributes", filename);
|
||||
|
||||
@@ -983,19 +1052,18 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenFile(const syscall_context& c, const emulator_object<handle> file_handle,
|
||||
const ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtOpenFile(const syscall_context& c, const emulator_object<handle> file_handle, const ACCESS_MASK desired_access,
|
||||
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)
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const ULONG share_access,
|
||||
const ULONG open_options)
|
||||
{
|
||||
return handle_NtCreateFile(c, file_handle, desired_access, object_attributes, io_status_block, {c.emu}, 0,
|
||||
share_access, FILE_OPEN, open_options, 0, 0);
|
||||
return handle_NtCreateFile(c, file_handle, desired_access, object_attributes, io_status_block, {c.emu}, 0, share_access, FILE_OPEN,
|
||||
open_options, 0, 0);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenDirectoryObject(
|
||||
const syscall_context& c, const emulator_object<handle> directory_handle, const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
NTSTATUS handle_NtOpenDirectoryObject(const syscall_context& c, const emulator_object<handle> directory_handle,
|
||||
const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
const auto object_name = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
@@ -1021,9 +1089,9 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenSymbolicLinkObject(
|
||||
const syscall_context& c, const emulator_object<handle> link_handle, ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
NTSTATUS handle_NtOpenSymbolicLinkObject(const syscall_context& c, const emulator_object<handle> link_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
const auto object_name = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
@@ -1067,27 +1135,63 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(
|
||||
const syscall_context& c, const emulator_object<handle> /*file_handle*/, const ULONG /*desired_access*/,
|
||||
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 /*create_disposition*/, const ULONG /*create_options*/, const ULONG /*named_pipe_type*/,
|
||||
const ULONG /*read_mode*/, const ULONG /*completion_mode*/, const ULONG /*maximum_instances*/,
|
||||
const ULONG /*inbound_quota*/, const ULONG /*outbound_quota*/,
|
||||
const emulator_object<LARGE_INTEGER> /*default_timeout*/)
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(const syscall_context& c, emulator_object<handle> file_handle, ULONG desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, ULONG share_access,
|
||||
ULONG create_disposition, ULONG create_options, ULONG named_pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG maximum_instances, ULONG inbound_quota, ULONG outbound_quota,
|
||||
emulator_object<LARGE_INTEGER> default_timeout)
|
||||
{
|
||||
c.win_emu.log.error("Unimplemented syscall NtCreateNamedPipeFile!");
|
||||
c.emu.stop();
|
||||
(void)desired_access;
|
||||
(void)share_access;
|
||||
(void)create_disposition;
|
||||
(void)create_options;
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
const auto attributes = object_attributes.read();
|
||||
const auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
|
||||
if (!filename.starts_with(u"\\Device\\NamedPipe"))
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
c.win_emu.callbacks.on_generic_access("Creating named pipe", filename);
|
||||
|
||||
io_device_creation_data data{};
|
||||
io_device_container container{u"NamedPipe", c.win_emu, data};
|
||||
|
||||
if (auto* pipe_device = container.get_internal_device<named_pipe>())
|
||||
{
|
||||
pipe_device->name = filename;
|
||||
pipe_device->pipe_type = named_pipe_type;
|
||||
pipe_device->read_mode = read_mode;
|
||||
pipe_device->completion_mode = completion_mode;
|
||||
pipe_device->max_instances = maximum_instances;
|
||||
pipe_device->inbound_quota = inbound_quota;
|
||||
pipe_device->outbound_quota = outbound_quota;
|
||||
pipe_device->default_timeout = default_timeout.read();
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
handle pipe_handle = c.proc.devices.store(std::move(container));
|
||||
file_handle.write(pipe_handle);
|
||||
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> iosb{};
|
||||
iosb.Status = STATUS_SUCCESS;
|
||||
iosb.Information = 0;
|
||||
io_status_block.write(iosb);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFsControlFile(const syscall_context& c, const handle /*event_handle*/,
|
||||
const uint64_t /*apc_routine*/, const uint64_t /*app_context*/,
|
||||
NTSTATUS handle_NtFsControlFile(const syscall_context& c, const handle /*event_handle*/, const uint64_t /*apc_routine*/,
|
||||
const uint64_t /*app_context*/,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/,
|
||||
const ULONG /*fs_control_code*/, const uint64_t /*input_buffer*/,
|
||||
const ULONG /*input_buffer_length*/, const uint64_t /*output_buffer*/,
|
||||
const ULONG /*output_buffer_length*/)
|
||||
const ULONG /*fs_control_code*/, const uint64_t /*input_buffer*/, const ULONG /*input_buffer_length*/,
|
||||
const uint64_t /*output_buffer*/, const ULONG /*output_buffer_length*/)
|
||||
{
|
||||
c.win_emu.log.error("Unimplemented syscall NtFsControlFile!");
|
||||
c.emu.stop();
|
||||
@@ -1095,9 +1199,8 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFlushBuffersFile(
|
||||
const syscall_context& c, const handle file_handle,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/)
|
||||
NTSTATUS handle_NtFlushBuffersFile(const syscall_context& c, const handle file_handle,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/)
|
||||
{
|
||||
if (file_handle == STDOUT_HANDLE)
|
||||
{
|
||||
|
||||
@@ -10,8 +10,7 @@ namespace syscalls
|
||||
const emulator_object<LCID> default_locale_id,
|
||||
const emulator_object<LARGE_INTEGER> /*default_casing_table_size*/)
|
||||
{
|
||||
const auto locale_file =
|
||||
utils::io::read_file(c.win_emu.file_sys.translate(R"(C:\Windows\System32\locale.nls)"));
|
||||
const auto locale_file = utils::io::read_file(c.win_emu.file_sys.translate(R"(C:\Windows\System32\locale.nls)"));
|
||||
if (locale_file.empty())
|
||||
{
|
||||
return STATUS_FILE_INVALID;
|
||||
@@ -27,16 +26,14 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/,
|
||||
const emulator_object<LCID> default_locale_id)
|
||||
NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/, const emulator_object<LCID> default_locale_id)
|
||||
{
|
||||
default_locale_id.write(0x407);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtGetNlsSectionPtr(const syscall_context& c, const ULONG section_type, const ULONG section_data,
|
||||
emulator_pointer /*context_data*/,
|
||||
const emulator_object<uint64_t> section_pointer,
|
||||
emulator_pointer /*context_data*/, const emulator_object<uint64_t> section_pointer,
|
||||
const emulator_object<ULONG> section_size)
|
||||
{
|
||||
if (section_type == 11)
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtQueryVirtualMemory(const syscall_context& c, const handle process_handle,
|
||||
const uint64_t base_address, const uint32_t info_class,
|
||||
const uint64_t memory_information, const uint64_t memory_information_length,
|
||||
const emulator_object<uint64_t> return_length)
|
||||
NTSTATUS handle_NtQueryVirtualMemory(const syscall_context& c, const handle process_handle, const uint64_t base_address,
|
||||
const uint32_t info_class, const uint64_t memory_information,
|
||||
const uint64_t memory_information_length, const emulator_object<uint64_t> return_length)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -126,9 +125,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtProtectVirtualMemory(const syscall_context& c, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address,
|
||||
const emulator_object<uint32_t> bytes_to_protect, const uint32_t protection,
|
||||
const emulator_object<uint32_t> old_protection)
|
||||
const emulator_object<uint64_t> base_address, const emulator_object<uint32_t> bytes_to_protect,
|
||||
const uint32_t protection, const emulator_object<uint32_t> old_protection)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -144,15 +142,19 @@ namespace syscalls
|
||||
base_address.write(aligned_start);
|
||||
bytes_to_protect.write(static_cast<uint32_t>(aligned_length));
|
||||
|
||||
const auto requested_protection = map_nt_to_emulator_protection(protection);
|
||||
const auto requested_protection = try_map_nt_to_emulator_protection(protection);
|
||||
if (!requested_protection.has_value())
|
||||
{
|
||||
return STATUS_INVALID_PAGE_PROTECTION;
|
||||
}
|
||||
|
||||
c.win_emu.callbacks.on_memory_protect(aligned_start, aligned_length, requested_protection);
|
||||
c.win_emu.callbacks.on_memory_protect(aligned_start, aligned_length, *requested_protection);
|
||||
|
||||
memory_permission old_protection_value{};
|
||||
nt_memory_permission old_protection_value{};
|
||||
|
||||
try
|
||||
{
|
||||
c.win_emu.memory.protect_memory(aligned_start, static_cast<size_t>(aligned_length), requested_protection,
|
||||
c.win_emu.memory.protect_memory(aligned_start, static_cast<size_t>(aligned_length), *requested_protection,
|
||||
&old_protection_value);
|
||||
}
|
||||
catch (...)
|
||||
@@ -168,8 +170,8 @@ namespace syscalls
|
||||
|
||||
NTSTATUS handle_NtAllocateVirtualMemoryEx(const syscall_context& c, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address,
|
||||
const emulator_object<uint64_t> bytes_to_allocate,
|
||||
const uint32_t allocation_type, const uint32_t page_protection)
|
||||
const emulator_object<uint64_t> bytes_to_allocate, const uint32_t allocation_type,
|
||||
const uint32_t page_protection)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -177,10 +179,20 @@ namespace syscalls
|
||||
}
|
||||
|
||||
auto allocation_bytes = bytes_to_allocate.read();
|
||||
|
||||
if (allocation_bytes == 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
allocation_bytes = page_align_up(allocation_bytes);
|
||||
bytes_to_allocate.write(allocation_bytes);
|
||||
|
||||
const auto protection = map_nt_to_emulator_protection(page_protection);
|
||||
const auto protection = try_map_nt_to_emulator_protection(page_protection);
|
||||
if (!protection.has_value())
|
||||
{
|
||||
return STATUS_INVALID_PAGE_PROTECTION;
|
||||
}
|
||||
|
||||
auto potential_base = base_address.read();
|
||||
if (!potential_base)
|
||||
@@ -203,32 +215,28 @@ namespace syscalls
|
||||
throw std::runtime_error("Unsupported allocation type!");
|
||||
}
|
||||
|
||||
if (commit && !reserve &&
|
||||
c.win_emu.memory.commit_memory(potential_base, static_cast<size_t>(allocation_bytes), protection))
|
||||
if (commit && !reserve && c.win_emu.memory.commit_memory(potential_base, static_cast<size_t>(allocation_bytes), *protection))
|
||||
{
|
||||
c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, protection, true);
|
||||
c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, *protection, true);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, protection, false);
|
||||
c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, *protection, false);
|
||||
|
||||
return c.win_emu.memory.allocate_memory(potential_base, static_cast<size_t>(allocation_bytes), protection,
|
||||
!commit)
|
||||
return c.win_emu.memory.allocate_memory(potential_base, static_cast<size_t>(allocation_bytes), *protection, !commit)
|
||||
? STATUS_SUCCESS
|
||||
: STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAllocateVirtualMemory(const syscall_context& c, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address, const uint64_t /*zero_bits*/,
|
||||
const emulator_object<uint64_t> bytes_to_allocate,
|
||||
const uint32_t allocation_type, const uint32_t page_protection)
|
||||
const emulator_object<uint64_t> bytes_to_allocate, const uint32_t allocation_type,
|
||||
const uint32_t page_protection)
|
||||
{
|
||||
return handle_NtAllocateVirtualMemoryEx(c, process_handle, base_address, bytes_to_allocate, allocation_type,
|
||||
page_protection);
|
||||
return handle_NtAllocateVirtualMemoryEx(c, process_handle, base_address, bytes_to_allocate, allocation_type, page_protection);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFreeVirtualMemory(const syscall_context& c, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address,
|
||||
NTSTATUS handle_NtFreeVirtualMemory(const syscall_context& c, const handle process_handle, const emulator_object<uint64_t> base_address,
|
||||
const emulator_object<uint64_t> bytes_to_allocate, const uint32_t free_type)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
@@ -236,29 +244,31 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (free_type == 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto allocation_base = base_address.read();
|
||||
const auto allocation_size = bytes_to_allocate.read();
|
||||
|
||||
if (free_type & MEM_RELEASE)
|
||||
{
|
||||
return c.win_emu.memory.release_memory(allocation_base, static_cast<size_t>(allocation_size))
|
||||
? STATUS_SUCCESS
|
||||
: STATUS_MEMORY_NOT_ALLOCATED;
|
||||
return c.win_emu.memory.release_memory(allocation_base, static_cast<size_t>(allocation_size)) ? STATUS_SUCCESS
|
||||
: STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
if (free_type & MEM_DECOMMIT)
|
||||
{
|
||||
return c.win_emu.memory.decommit_memory(allocation_base, static_cast<size_t>(allocation_size))
|
||||
? STATUS_SUCCESS
|
||||
: STATUS_MEMORY_NOT_ALLOCATED;
|
||||
return c.win_emu.memory.decommit_memory(allocation_base, static_cast<size_t>(allocation_size)) ? STATUS_SUCCESS
|
||||
: STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Bad free type");
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtReadVirtualMemory(const syscall_context& c, const handle process_handle,
|
||||
const emulator_pointer base_address, const emulator_pointer buffer,
|
||||
const ULONG number_of_bytes_to_read,
|
||||
NTSTATUS handle_NtReadVirtualMemory(const syscall_context& c, const handle process_handle, const emulator_pointer base_address,
|
||||
const emulator_pointer buffer, const ULONG number_of_bytes_to_read,
|
||||
const emulator_object<ULONG> number_of_bytes_read)
|
||||
{
|
||||
number_of_bytes_read.write(0);
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtReleaseMutant(const syscall_context& c, const handle mutant_handle,
|
||||
const emulator_object<LONG> previous_count)
|
||||
NTSTATUS handle_NtReleaseMutant(const syscall_context& c, const handle mutant_handle, const emulator_object<LONG> previous_count)
|
||||
{
|
||||
if (mutant_handle.value.type != handle_types::mutant)
|
||||
{
|
||||
@@ -42,8 +41,7 @@ namespace syscalls
|
||||
const auto attributes = object_attributes.read();
|
||||
if (attributes.ObjectName)
|
||||
{
|
||||
name = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
name = read_unicode_string(c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
c.win_emu.callbacks.on_generic_access("Opening mutant", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,9 @@ namespace syscalls
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtDuplicateObject(const syscall_context& c, const handle source_process_handle,
|
||||
const handle source_handle, const handle target_process_handle,
|
||||
const emulator_object<handle> target_handle, const ACCESS_MASK /*desired_access*/,
|
||||
const ULONG /*handle_attributes*/, const ULONG /*options*/)
|
||||
NTSTATUS handle_NtDuplicateObject(const syscall_context& c, const handle source_process_handle, const handle source_handle,
|
||||
const handle target_process_handle, const emulator_object<handle> target_handle,
|
||||
const ACCESS_MASK /*desired_access*/, const ULONG /*handle_attributes*/, const ULONG /*options*/)
|
||||
{
|
||||
if (source_process_handle != CURRENT_PROCESS || target_process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -90,8 +89,7 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryObject(const syscall_context& c, const handle handle,
|
||||
const OBJECT_INFORMATION_CLASS object_information_class,
|
||||
NTSTATUS handle_NtQueryObject(const syscall_context& c, const handle handle, const OBJECT_INFORMATION_CLASS object_information_class,
|
||||
const emulator_pointer object_information, const ULONG object_information_length,
|
||||
const emulator_object<ULONG> return_length)
|
||||
{
|
||||
@@ -163,8 +161,7 @@ namespace syscalls
|
||||
|
||||
if (object_information_class == ObjectHandleFlagInformation)
|
||||
{
|
||||
return handle_query<OBJECT_HANDLE_FLAG_INFORMATION>(c.emu, object_information, object_information_length,
|
||||
return_length,
|
||||
return handle_query<OBJECT_HANDLE_FLAG_INFORMATION>(c.emu, object_information, object_information_length, return_length,
|
||||
[&](OBJECT_HANDLE_FLAG_INFORMATION& info) {
|
||||
info.Inherit = 0;
|
||||
info.ProtectFromClose = 0;
|
||||
@@ -185,9 +182,9 @@ namespace syscalls
|
||||
|| h.value.type == handle_types::event;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, const ULONG count,
|
||||
const emulator_object<handle> handles, const WAIT_TYPE wait_type,
|
||||
const BOOLEAN alertable, const emulator_object<LARGE_INTEGER> timeout)
|
||||
NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, const ULONG count, const emulator_object<handle> handles,
|
||||
const WAIT_TYPE wait_type, const BOOLEAN alertable,
|
||||
const emulator_object<LARGE_INTEGER> timeout)
|
||||
{
|
||||
if (wait_type != WaitAny && wait_type != WaitAll)
|
||||
{
|
||||
@@ -249,21 +246,19 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQuerySecurityObject(const syscall_context& c, const handle /*h*/,
|
||||
const SECURITY_INFORMATION security_information,
|
||||
NTSTATUS handle_NtQuerySecurityObject(const syscall_context& c, const handle /*h*/, const SECURITY_INFORMATION security_information,
|
||||
const emulator_pointer security_descriptor, const ULONG length,
|
||||
const emulator_object<ULONG> length_needed)
|
||||
{
|
||||
if ((security_information & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION)) == 0)
|
||||
if ((security_information &
|
||||
(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION)) == 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Owner SID: S-1-5-32-544 (Administrators)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
const uint8_t owner_sid[] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00};
|
||||
const uint8_t owner_sid[] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00};
|
||||
|
||||
// Group SID: S-1-5-18 (Local System)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
@@ -272,21 +267,19 @@ namespace syscalls
|
||||
// DACL structure
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
const uint8_t dacl_data[] = {
|
||||
0x02, 0x00, 0x9C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x01, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0F, 0x00, 0x02, 0x00,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0F, 0x00,
|
||||
0x0F, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
|
||||
0x00, 0x0B, 0x14, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0B, 0x14, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x0C, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x0B, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00};
|
||||
0x02, 0x00, 0x9C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x01, 0x02, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x0B, 0x14, 0x00, 0x00, 0x00, 0x00, 0xE0,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x14, 0x00, 0x00, 0x00, 0x00, 0xE0,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10,
|
||||
0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x0B, 0x14, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// SACL structure
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
const uint8_t sacl_data[] = {0x02, 0x00, 0x1C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00,
|
||||
0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00};
|
||||
const uint8_t sacl_data[] = {0x02, 0x00, 0x1C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x14, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00};
|
||||
|
||||
ULONG total_size = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace syscalls
|
||||
const emulator_object<SECURITY_QUALITY_OF_SERVICE> /*security_qos*/,
|
||||
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> /*maximum_message_length*/, const emulator_pointer connection_info,
|
||||
const emulator_object<ULONG> connection_info_length)
|
||||
{
|
||||
auto port_name = read_unicode_string(c.emu, server_port_name);
|
||||
@@ -27,8 +26,7 @@ namespace syscalls
|
||||
}
|
||||
|
||||
client_shared_memory.access([&](PORT_VIEW64& view) {
|
||||
p.view_base =
|
||||
c.win_emu.memory.allocate_memory(static_cast<size_t>(view.ViewSize), memory_permission::read_write);
|
||||
p.view_base = c.win_emu.memory.allocate_memory(static_cast<size_t>(view.ViewSize), memory_permission::read_write);
|
||||
view.ViewBase = p.view_base;
|
||||
view.ViewRemoteBase = view.ViewBase;
|
||||
});
|
||||
@@ -42,15 +40,13 @@ namespace syscalls
|
||||
NTSTATUS handle_NtSecureConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
|
||||
emulator_object<SECURITY_QUALITY_OF_SERVICE> security_qos,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory,
|
||||
emulator_pointer /*server_sid*/,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory, emulator_pointer /*server_sid*/,
|
||||
emulator_object<REMOTE_PORT_VIEW64> server_shared_memory,
|
||||
emulator_object<ULONG> maximum_message_length, emulator_pointer connection_info,
|
||||
emulator_object<ULONG> connection_info_length)
|
||||
{
|
||||
return handle_NtConnectPort(c, client_port_handle, server_port_name, security_qos, client_shared_memory,
|
||||
server_shared_memory, maximum_message_length, connection_info,
|
||||
connection_info_length);
|
||||
return handle_NtConnectPort(c, client_port_handle, server_port_name, security_qos, client_shared_memory, server_shared_memory,
|
||||
maximum_message_length, connection_info, connection_info_length);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, const handle port_handle, const ULONG /*flags*/,
|
||||
@@ -98,4 +94,9 @@ namespace syscalls
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAlpcConnectPortEx()
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtQueryInformationProcess(const syscall_context& c, const handle process_handle,
|
||||
const uint32_t info_class, const uint64_t process_information,
|
||||
const uint32_t process_information_length,
|
||||
NTSTATUS handle_NtQueryInformationProcess(const syscall_context& c, const handle process_handle, const uint32_t info_class,
|
||||
const uint64_t process_information, const uint32_t process_information_length,
|
||||
const emulator_object<uint32_t> return_length)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
@@ -24,48 +23,43 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
case ProcessTimes:
|
||||
return handle_query<KERNEL_USER_TIMES>(c.emu, process_information, process_information_length,
|
||||
return_length, [](KERNEL_USER_TIMES& t) {
|
||||
return handle_query<KERNEL_USER_TIMES>(c.emu, process_information, process_information_length, return_length,
|
||||
[](KERNEL_USER_TIMES& t) {
|
||||
t = {}; //
|
||||
});
|
||||
|
||||
case ProcessCookie:
|
||||
return handle_query<uint32_t>(c.emu, process_information, process_information_length, return_length,
|
||||
[](uint32_t& cookie) {
|
||||
cookie = 0x01234567; //
|
||||
});
|
||||
return handle_query<uint32_t>(c.emu, process_information, process_information_length, return_length, [](uint32_t& cookie) {
|
||||
cookie = 0x01234567; //
|
||||
});
|
||||
|
||||
case ProcessDebugObjectHandle:
|
||||
return handle_query<handle>(c.emu, process_information, process_information_length, return_length,
|
||||
[](handle& h) {
|
||||
h = NULL_HANDLE;
|
||||
return STATUS_PORT_NOT_SET;
|
||||
});
|
||||
return handle_query<handle>(c.emu, process_information, process_information_length, return_length, [](handle& h) {
|
||||
h = NULL_HANDLE;
|
||||
return STATUS_PORT_NOT_SET;
|
||||
});
|
||||
|
||||
case ProcessDebugFlags:
|
||||
case ProcessWx86Information:
|
||||
case ProcessDefaultHardErrorMode:
|
||||
return handle_query<ULONG>(c.emu, process_information, process_information_length, return_length,
|
||||
[&](ULONG& res) {
|
||||
res = (info_class == ProcessDebugFlags ? 1 : 0); //
|
||||
});
|
||||
return handle_query<ULONG>(c.emu, process_information, process_information_length, return_length, [&](ULONG& res) {
|
||||
res = (info_class == ProcessDebugFlags ? 1 : 0); //
|
||||
});
|
||||
|
||||
case ProcessDebugPort:
|
||||
case ProcessDeviceMap:
|
||||
return handle_query<EmulatorTraits<Emu64>::PVOID>(c.emu, process_information, process_information_length,
|
||||
return_length, [](EmulatorTraits<Emu64>::PVOID& ptr) {
|
||||
return handle_query<EmulatorTraits<Emu64>::PVOID>(c.emu, process_information, process_information_length, return_length,
|
||||
[](EmulatorTraits<Emu64>::PVOID& ptr) {
|
||||
ptr = 0; //
|
||||
});
|
||||
|
||||
case ProcessEnableAlignmentFaultFixup:
|
||||
return handle_query<BOOLEAN>(c.emu, process_information, process_information_length, return_length,
|
||||
[](BOOLEAN& b) {
|
||||
b = FALSE; //
|
||||
});
|
||||
return handle_query<BOOLEAN>(c.emu, process_information, process_information_length, return_length, [](BOOLEAN& b) {
|
||||
b = FALSE; //
|
||||
});
|
||||
|
||||
case ProcessBasicInformation:
|
||||
return handle_query<PROCESS_BASIC_INFORMATION64>(c.emu, process_information, process_information_length,
|
||||
return_length,
|
||||
return handle_query<PROCESS_BASIC_INFORMATION64>(c.emu, process_information, process_information_length, return_length,
|
||||
[&](PROCESS_BASIC_INFORMATION64& basic_info) {
|
||||
basic_info.PebBaseAddress = c.proc.peb.value();
|
||||
basic_info.UniqueProcessId = 1;
|
||||
@@ -80,8 +74,7 @@ namespace syscalls
|
||||
const emulator_object<PEDosHeader_t> dos_header_obj{c.emu, mod.image_base};
|
||||
const auto dos_header = dos_header_obj.read();
|
||||
|
||||
const emulator_object<PENTHeaders_t<uint64_t>> 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;
|
||||
@@ -123,8 +116,7 @@ namespace syscalls
|
||||
|
||||
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<EmulatorTraits<Emu64>>);
|
||||
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;
|
||||
@@ -143,9 +135,8 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, const handle process_handle,
|
||||
const uint32_t info_class, const uint64_t process_information,
|
||||
const uint32_t process_information_length)
|
||||
NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, const handle process_handle, const uint32_t info_class,
|
||||
const uint64_t process_information, const uint32_t process_information_length)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -243,8 +234,8 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenProcessToken(const syscall_context&, const handle process_handle,
|
||||
const ACCESS_MASK /*desired_access*/, const emulator_object<handle> token_handle)
|
||||
NTSTATUS handle_NtOpenProcessToken(const syscall_context&, const handle process_handle, const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<handle> token_handle)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -256,9 +247,8 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenProcessTokenEx(const syscall_context& c, const handle process_handle,
|
||||
const ACCESS_MASK desired_access, const ULONG /*handle_attributes*/,
|
||||
const emulator_object<handle> token_handle)
|
||||
NTSTATUS handle_NtOpenProcessTokenEx(const syscall_context& c, const handle process_handle, const ACCESS_MASK desired_access,
|
||||
const ULONG /*handle_attributes*/, const emulator_object<handle> token_handle)
|
||||
{
|
||||
return handle_NtOpenProcessToken(c, process_handle, desired_access, token_handle);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object<handle> key_handle,
|
||||
const ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object<handle> key_handle, const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
@@ -39,17 +38,14 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, const emulator_object<handle> key_handle,
|
||||
const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG /*open_options*/)
|
||||
NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, const emulator_object<handle> key_handle, const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*open_options*/)
|
||||
{
|
||||
return handle_NtOpenKey(c, key_handle, desired_access, object_attributes);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryKey(const syscall_context& c, const handle key_handle,
|
||||
const KEY_INFORMATION_CLASS key_information_class, const uint64_t key_information,
|
||||
const ULONG length, const emulator_object<ULONG> result_length)
|
||||
NTSTATUS handle_NtQueryKey(const syscall_context& c, const handle key_handle, const KEY_INFORMATION_CLASS key_information_class,
|
||||
const uint64_t key_information, const ULONG length, const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
@@ -81,8 +77,7 @@ namespace syscalls
|
||||
const emulator_object<KEY_NAME_INFORMATION> info_obj{c.emu, key_information};
|
||||
info_obj.write(info);
|
||||
|
||||
c.emu.write_memory(key_information + offsetof(KEY_NAME_INFORMATION, Name), key_name.data(),
|
||||
info.NameLength);
|
||||
c.emu.write_memory(key_information + offsetof(KEY_NAME_INFORMATION, Name), key_name.data(), info.NameLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -118,9 +113,8 @@ namespace syscalls
|
||||
|
||||
NTSTATUS handle_NtQueryValueKey(const syscall_context& c, const handle key_handle,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> value_name,
|
||||
const KEY_VALUE_INFORMATION_CLASS key_value_information_class,
|
||||
const uint64_t key_value_information, const ULONG length,
|
||||
const emulator_object<ULONG> result_length)
|
||||
const KEY_VALUE_INFORMATION_CLASS key_value_information_class, const uint64_t key_value_information,
|
||||
const ULONG length, const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
@@ -222,8 +216,7 @@ namespace syscalls
|
||||
|
||||
c.emu.write_memory(key_value_information + base_size, original_name.data(), info.NameLength);
|
||||
|
||||
c.emu.write_memory(key_value_information + base_size + info.NameLength, value->data.data(),
|
||||
value->data.size());
|
||||
c.emu.write_memory(key_value_information + base_size + info.NameLength, value->data.data(), value->data.size());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -233,11 +226,9 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, const emulator_object<handle> key_handle,
|
||||
const ACCESS_MASK desired_access,
|
||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, const emulator_object<handle> key_handle, const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const ULONG /*title_index*/,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
|
||||
const ULONG /*title_index*/, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
|
||||
const ULONG /*create_options*/, const emulator_object<ULONG> /*disposition*/)
|
||||
{
|
||||
const auto result = handle_NtOpenKey(c, key_handle, desired_access, object_attributes);
|
||||
@@ -261,8 +252,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtEnumerateKey(const syscall_context& c, const handle key_handle, const ULONG index,
|
||||
const KEY_INFORMATION_CLASS key_information_class, const uint64_t key_information,
|
||||
const ULONG length, const emulator_object<ULONG> result_length)
|
||||
const KEY_INFORMATION_CLASS key_information_class, const uint64_t key_information, const ULONG length,
|
||||
const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
@@ -341,9 +332,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtEnumerateValueKey(const syscall_context& c, const handle key_handle, const ULONG index,
|
||||
const KEY_VALUE_INFORMATION_CLASS key_value_information_class,
|
||||
const uint64_t key_value_information, const ULONG length,
|
||||
const emulator_object<ULONG> result_length)
|
||||
const KEY_VALUE_INFORMATION_CLASS key_value_information_class, const uint64_t key_value_information,
|
||||
const ULONG length, const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
|
||||
@@ -9,9 +9,8 @@ namespace syscalls
|
||||
NTSTATUS handle_NtCreateSection(const syscall_context& c, const emulator_object<handle> section_handle,
|
||||
const ACCESS_MASK /*desired_access*/,
|
||||
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)
|
||||
const emulator_object<ULARGE_INTEGER> maximum_size, const ULONG section_page_protection,
|
||||
const ULONG allocation_attributes, const handle file_handle)
|
||||
{
|
||||
section s{};
|
||||
s.section_page_protection = section_page_protection;
|
||||
@@ -96,8 +95,7 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (attributes.RootDirectory != KNOWN_DLLS_DIRECTORY &&
|
||||
attributes.RootDirectory != BASE_NAMED_OBJECTS_DIRECTORY)
|
||||
if (attributes.RootDirectory != KNOWN_DLLS_DIRECTORY && attributes.RootDirectory != BASE_NAMED_OBJECTS_DIRECTORY)
|
||||
{
|
||||
c.win_emu.log.error("Unsupported section\n");
|
||||
c.emu.stop();
|
||||
@@ -118,14 +116,14 @@ namespace syscalls
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtMapViewOfSection(
|
||||
const syscall_context& c, const handle section_handle, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address,
|
||||
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<EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T)> view_size,
|
||||
const SECTION_INHERIT /*inherit_disposition*/, const ULONG /*allocation_type*/, const ULONG /*win32_protect*/)
|
||||
NTSTATUS handle_NtMapViewOfSection(const syscall_context& c, const handle section_handle, const handle process_handle,
|
||||
const emulator_object<uint64_t> base_address,
|
||||
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<EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T)> view_size,
|
||||
const SECTION_INHERIT /*inherit_disposition*/, const ULONG /*allocation_type*/,
|
||||
const ULONG /*win32_protect*/)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -155,15 +153,13 @@ namespace syscalls
|
||||
ucs.MaximumLength = ucs.Length;
|
||||
});
|
||||
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> sysdir_obj{c.emu, windir_obj.value() +
|
||||
windir_obj.size()};
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> sysdir_obj{c.emu, windir_obj.value() + windir_obj.size()};
|
||||
sysdir_obj.access([&](UNICODE_STRING<EmulatorTraits<Emu64>>& ucs) {
|
||||
c.proc.base_allocator.make_unicode_string(ucs, u"C:\\WINDOWS\\System32");
|
||||
ucs.Buffer = ucs.Buffer - obj_address;
|
||||
});
|
||||
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> base_dir_obj{c.emu, sysdir_obj.value() +
|
||||
sysdir_obj.size()};
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> base_dir_obj{c.emu, sysdir_obj.value() + sysdir_obj.size()};
|
||||
base_dir_obj.access([&](UNICODE_STRING<EmulatorTraits<Emu64>>& ucs) {
|
||||
c.proc.base_allocator.make_unicode_string(ucs, u"\\Sessions\\1\\BaseNamedObjects");
|
||||
ucs.Buffer = ucs.Buffer - obj_address;
|
||||
@@ -257,8 +253,7 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUnmapViewOfSection(const syscall_context& c, const handle process_handle,
|
||||
const uint64_t base_address)
|
||||
NTSTATUS handle_NtUnmapViewOfSection(const syscall_context& c, const handle process_handle, const uint64_t base_address)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS)
|
||||
{
|
||||
@@ -305,8 +300,8 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, const handle process_handle,
|
||||
const uint64_t base_address, const ULONG /*flags*/)
|
||||
NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, const handle process_handle, const uint64_t base_address,
|
||||
const ULONG /*flags*/)
|
||||
{
|
||||
return handle_NtUnmapViewOfSection(c, process_handle, base_address);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto name = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
const auto name = read_unicode_string(c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
if (name.empty())
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
@@ -38,8 +37,8 @@ namespace syscalls
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtReleaseSemaphore(const syscall_context& c, const handle semaphore_handle,
|
||||
const ULONG release_count, const emulator_object<LONG> previous_count)
|
||||
NTSTATUS handle_NtReleaseSemaphore(const syscall_context& c, const handle semaphore_handle, const ULONG release_count,
|
||||
const emulator_object<LONG> previous_count)
|
||||
{
|
||||
if (semaphore_handle.value.type != handle_types::semaphore)
|
||||
{
|
||||
|
||||
@@ -7,8 +7,7 @@ namespace syscalls
|
||||
namespace
|
||||
{
|
||||
NTSTATUS handle_logical_processor_and_group_information(const syscall_context& c, const uint64_t input_buffer,
|
||||
const uint32_t input_buffer_length,
|
||||
const uint64_t system_information,
|
||||
const uint32_t input_buffer_length, const uint64_t system_information,
|
||||
const uint32_t system_information_length,
|
||||
const emulator_object<uint32_t> return_length)
|
||||
{
|
||||
@@ -87,11 +86,9 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQuerySystemInformationEx(const syscall_context& c, const uint32_t info_class,
|
||||
const uint64_t input_buffer, const uint32_t input_buffer_length,
|
||||
const uint64_t system_information,
|
||||
const uint32_t system_information_length,
|
||||
const emulator_object<uint32_t> return_length)
|
||||
NTSTATUS handle_NtQuerySystemInformationEx(const syscall_context& c, const uint32_t info_class, const uint64_t input_buffer,
|
||||
const uint32_t input_buffer_length, const uint64_t system_information,
|
||||
const uint32_t system_information_length, const emulator_object<uint32_t> return_length)
|
||||
{
|
||||
switch (info_class)
|
||||
{
|
||||
@@ -113,8 +110,7 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
case SystemTimeOfDayInformation:
|
||||
return handle_query<SYSTEM_TIMEOFDAY_INFORMATION64>(c.emu, system_information, system_information_length,
|
||||
return_length,
|
||||
return handle_query<SYSTEM_TIMEOFDAY_INFORMATION64>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_TIMEOFDAY_INFORMATION64& info) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.BootTime.QuadPart = 0;
|
||||
@@ -125,8 +121,7 @@ namespace syscalls
|
||||
case SystemTimeZoneInformation:
|
||||
case SystemCurrentTimeZoneInformation:
|
||||
return handle_query<SYSTEM_TIMEZONE_INFORMATION>(
|
||||
c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_TIMEZONE_INFORMATION& tzi) {
|
||||
c.emu, system_information, system_information_length, return_length, [&](SYSTEM_TIMEZONE_INFORMATION& tzi) {
|
||||
memset(&tzi, 0, sizeof(tzi));
|
||||
|
||||
tzi.Bias = -60;
|
||||
@@ -160,8 +155,7 @@ namespace syscalls
|
||||
|
||||
case SystemDynamicTimeZoneInformation:
|
||||
return handle_query<SYSTEM_DYNAMIC_TIMEZONE_INFORMATION>(
|
||||
c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_DYNAMIC_TIMEZONE_INFORMATION& dtzi) {
|
||||
c.emu, system_information, system_information_length, return_length, [&](SYSTEM_DYNAMIC_TIMEZONE_INFORMATION& dtzi) {
|
||||
memset(&dtzi, 0, sizeof(dtzi));
|
||||
|
||||
dtzi.Bias = -60;
|
||||
@@ -199,24 +193,22 @@ namespace syscalls
|
||||
});
|
||||
|
||||
case SystemRangeStartInformation:
|
||||
return handle_query<SYSTEM_RANGE_START_INFORMATION64>(c.emu, system_information, system_information_length,
|
||||
return_length,
|
||||
return handle_query<SYSTEM_RANGE_START_INFORMATION64>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_RANGE_START_INFORMATION64& info) {
|
||||
info.SystemRangeStart = 0xFFFF800000000000; //
|
||||
});
|
||||
|
||||
case SystemProcessorInformation:
|
||||
return handle_query<SYSTEM_PROCESSOR_INFORMATION64>(
|
||||
c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_PROCESSOR_INFORMATION64& info) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.MaximumProcessors = 2;
|
||||
info.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
|
||||
});
|
||||
return handle_query<SYSTEM_PROCESSOR_INFORMATION64>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_PROCESSOR_INFORMATION64& info) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.MaximumProcessors = 2;
|
||||
info.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
|
||||
});
|
||||
|
||||
case SystemNumaProcessorMap:
|
||||
return handle_query<SYSTEM_NUMA_INFORMATION64>(c.emu, system_information, system_information_length,
|
||||
return_length, [&](SYSTEM_NUMA_INFORMATION64& info) {
|
||||
return handle_query<SYSTEM_NUMA_INFORMATION64>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_NUMA_INFORMATION64& info) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.ActiveProcessorsGroupAffinity->Mask = 0xFFF;
|
||||
info.AvailableMemory[0] = 0xFFF;
|
||||
@@ -224,23 +216,22 @@ namespace syscalls
|
||||
});
|
||||
|
||||
case SystemErrorPortTimeouts:
|
||||
return handle_query<SYSTEM_ERROR_PORT_TIMEOUTS>(c.emu, system_information, system_information_length,
|
||||
return_length, [&](SYSTEM_ERROR_PORT_TIMEOUTS& info) {
|
||||
return handle_query<SYSTEM_ERROR_PORT_TIMEOUTS>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_ERROR_PORT_TIMEOUTS& info) {
|
||||
info.StartTimeout = 0;
|
||||
info.CommTimeout = 0;
|
||||
});
|
||||
|
||||
case SystemKernelDebuggerInformation:
|
||||
return handle_query<SYSTEM_KERNEL_DEBUGGER_INFORMATION>(c.emu, system_information,
|
||||
system_information_length, return_length,
|
||||
return handle_query<SYSTEM_KERNEL_DEBUGGER_INFORMATION>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_KERNEL_DEBUGGER_INFORMATION& info) {
|
||||
info.KernelDebuggerEnabled = FALSE;
|
||||
info.KernelDebuggerNotPresent = TRUE;
|
||||
});
|
||||
|
||||
case SystemLogicalProcessorAndGroupInformation:
|
||||
return handle_logical_processor_and_group_information(
|
||||
c, input_buffer, input_buffer_length, system_information, system_information_length, return_length);
|
||||
return handle_logical_processor_and_group_information(c, input_buffer, input_buffer_length, system_information,
|
||||
system_information_length, return_length);
|
||||
|
||||
case SystemLogicalProcessorInformation: {
|
||||
if (!input_buffer || input_buffer_length != sizeof(USHORT))
|
||||
@@ -252,35 +243,33 @@ namespace syscalls
|
||||
|
||||
const auto processor_group = c.emu.read_memory<USHORT>(input_buffer);
|
||||
|
||||
return handle_query<info_type>(
|
||||
c.emu, system_information, system_information_length, return_length, [&](info_type& info) {
|
||||
info.Relationship = RelationProcessorCore;
|
||||
return handle_query<info_type>(c.emu, system_information, system_information_length, return_length, [&](info_type& info) {
|
||||
info.Relationship = RelationProcessorCore;
|
||||
|
||||
if (processor_group == 0)
|
||||
{
|
||||
using mask_type = decltype(info.ProcessorMask);
|
||||
const auto active_processor_count = c.proc.kusd.get().ActiveProcessorCount;
|
||||
info.ProcessorMask = (static_cast<mask_type>(1) << active_processor_count) - 1;
|
||||
}
|
||||
});
|
||||
if (processor_group == 0)
|
||||
{
|
||||
using mask_type = decltype(info.ProcessorMask);
|
||||
const auto active_processor_count = c.proc.kusd.get().ActiveProcessorCount;
|
||||
info.ProcessorMask = (static_cast<mask_type>(1) << active_processor_count) - 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SystemBasicInformation:
|
||||
case SystemEmulationBasicInformation:
|
||||
return handle_query<SYSTEM_BASIC_INFORMATION64>(
|
||||
c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_BASIC_INFORMATION64& basic_info) {
|
||||
basic_info.Reserved = 0;
|
||||
basic_info.TimerResolution = 0x0002625a;
|
||||
basic_info.PageSize = 0x1000;
|
||||
basic_info.LowestPhysicalPageNumber = 0x00000001;
|
||||
basic_info.HighestPhysicalPageNumber = 0x00c9c7ff;
|
||||
basic_info.AllocationGranularity = ALLOCATION_GRANULARITY;
|
||||
basic_info.MinimumUserModeAddress = MIN_ALLOCATION_ADDRESS;
|
||||
basic_info.MaximumUserModeAddress = MAX_ALLOCATION_ADDRESS;
|
||||
basic_info.ActiveProcessorsAffinityMask = 0x0000000000000fff;
|
||||
basic_info.NumberOfProcessors = 1;
|
||||
});
|
||||
return handle_query<SYSTEM_BASIC_INFORMATION64>(c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_BASIC_INFORMATION64& basic_info) {
|
||||
basic_info.Reserved = 0;
|
||||
basic_info.TimerResolution = 0x0002625a;
|
||||
basic_info.PageSize = 0x1000;
|
||||
basic_info.LowestPhysicalPageNumber = 0x00000001;
|
||||
basic_info.HighestPhysicalPageNumber = 0x00c9c7ff;
|
||||
basic_info.AllocationGranularity = ALLOCATION_GRANULARITY;
|
||||
basic_info.MinimumUserModeAddress = MIN_ALLOCATION_ADDRESS;
|
||||
basic_info.MaximumUserModeAddress = MAX_ALLOCATION_ADDRESS;
|
||||
basic_info.ActiveProcessorsAffinityMask = 0x0000000000000f;
|
||||
basic_info.NumberOfProcessors = 4;
|
||||
});
|
||||
|
||||
default:
|
||||
c.win_emu.log.error("Unsupported system info class: %X\n", info_class);
|
||||
@@ -289,13 +278,10 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQuerySystemInformation(const syscall_context& c, const uint32_t info_class,
|
||||
const uint64_t system_information,
|
||||
const uint32_t system_information_length,
|
||||
const emulator_object<uint32_t> return_length)
|
||||
NTSTATUS handle_NtQuerySystemInformation(const syscall_context& c, const uint32_t info_class, const uint64_t system_information,
|
||||
const uint32_t system_information_length, const emulator_object<uint32_t> return_length)
|
||||
{
|
||||
return handle_NtQuerySystemInformationEx(c, info_class, 0, 0, system_information, system_information_length,
|
||||
return_length);
|
||||
return handle_NtQuerySystemInformationEx(c, info_class, 0, 0, system_information, system_information_length, return_length);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetSystemInformation()
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtSetInformationThread(const syscall_context& c, const handle thread_handle,
|
||||
const THREADINFOCLASS info_class, const uint64_t thread_information,
|
||||
const uint32_t thread_information_length)
|
||||
NTSTATUS handle_NtSetInformationThread(const syscall_context& c, const handle thread_handle, const THREADINFOCLASS info_class,
|
||||
const uint64_t thread_information, const uint32_t thread_information_length)
|
||||
{
|
||||
auto* thread = thread_handle == CURRENT_THREAD ? c.proc.active_thread : c.proc.threads.get(thread_handle);
|
||||
|
||||
@@ -18,8 +17,7 @@ namespace syscalls
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (info_class == ThreadSchedulerSharedDataSlot || info_class == ThreadBasePriority ||
|
||||
info_class == ThreadAffinityMask)
|
||||
if (info_class == ThreadSchedulerSharedDataSlot || info_class == ThreadBasePriority || info_class == ThreadAffinityMask)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -91,9 +89,8 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInformationThread(const syscall_context& c, const handle thread_handle,
|
||||
const uint32_t info_class, const uint64_t thread_information,
|
||||
const uint32_t thread_information_length,
|
||||
NTSTATUS handle_NtQueryInformationThread(const syscall_context& c, const handle thread_handle, const uint32_t info_class,
|
||||
const uint64_t thread_information, const uint32_t thread_information_length,
|
||||
const emulator_object<uint32_t> return_length)
|
||||
{
|
||||
const auto* thread = thread_handle == CURRENT_THREAD ? c.proc.active_thread : c.proc.threads.get(thread_handle);
|
||||
@@ -246,9 +243,8 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenThreadToken(const syscall_context&, const handle thread_handle,
|
||||
const ACCESS_MASK /*desired_access*/, const BOOLEAN /*open_as_self*/,
|
||||
const emulator_object<handle> token_handle)
|
||||
NTSTATUS handle_NtOpenThreadToken(const syscall_context&, const handle thread_handle, const ACCESS_MASK /*desired_access*/,
|
||||
const BOOLEAN /*open_as_self*/, const emulator_object<handle> token_handle)
|
||||
{
|
||||
if (thread_handle != CURRENT_THREAD)
|
||||
{
|
||||
@@ -260,9 +256,9 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenThreadTokenEx(const syscall_context& c, const handle thread_handle,
|
||||
const ACCESS_MASK desired_access, const BOOLEAN open_as_self,
|
||||
const ULONG /*handle_attributes*/, const emulator_object<handle> token_handle)
|
||||
NTSTATUS handle_NtOpenThreadTokenEx(const syscall_context& c, const handle thread_handle, const ACCESS_MASK desired_access,
|
||||
const BOOLEAN open_as_self, const ULONG /*handle_attributes*/,
|
||||
const emulator_object<handle> token_handle)
|
||||
{
|
||||
return handle_NtOpenThreadToken(c, thread_handle, desired_access, open_as_self, token_handle);
|
||||
}
|
||||
@@ -304,8 +300,7 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtDelayExecution(const syscall_context& c, const BOOLEAN alertable,
|
||||
const emulator_object<LARGE_INTEGER> delay_interval)
|
||||
NTSTATUS handle_NtDelayExecution(const syscall_context& c, const BOOLEAN alertable, const emulator_object<LARGE_INTEGER> delay_interval)
|
||||
{
|
||||
auto& t = c.win_emu.current_thread();
|
||||
t.await_time = utils::convert_delay_interval_to_time_point(c.win_emu.clock(), delay_interval.read());
|
||||
@@ -342,8 +337,7 @@ namespace syscalls
|
||||
return handle_NtAlertThreadByThreadId(c, thread_id);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, const uint64_t,
|
||||
const emulator_object<LARGE_INTEGER> timeout)
|
||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, const uint64_t, const emulator_object<LARGE_INTEGER> timeout)
|
||||
{
|
||||
auto& t = c.win_emu.current_thread();
|
||||
t.waiting_for_alert = true;
|
||||
@@ -413,15 +407,14 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object<CONTEXT64> thread_context,
|
||||
const BOOLEAN raise_alert)
|
||||
NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object<CONTEXT64> thread_context, const BOOLEAN raise_alert)
|
||||
{
|
||||
return handle_NtContinueEx(c, thread_context, raise_alert ? 1 : 0);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtGetNextThread(const syscall_context& c, const handle process_handle, const handle thread_handle,
|
||||
const ACCESS_MASK /*desired_access*/, const ULONG /*handle_attributes*/,
|
||||
const ULONG flags, const emulator_object<handle> new_thread_handle)
|
||||
const ACCESS_MASK /*desired_access*/, const ULONG /*handle_attributes*/, const ULONG flags,
|
||||
const emulator_object<handle> new_thread_handle)
|
||||
{
|
||||
if (process_handle != CURRENT_PROCESS || thread_handle.value.type != handle_types::thread)
|
||||
{
|
||||
@@ -535,8 +528,7 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size,
|
||||
create_flags & CREATE_SUSPENDED);
|
||||
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size, create_flags & CREATE_SUSPENDED);
|
||||
thread_handle.write(h);
|
||||
|
||||
if (!attribute_list)
|
||||
@@ -581,8 +573,7 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtGetCurrentProcessorNumberEx(const syscall_context&,
|
||||
const emulator_object<PROCESSOR_NUMBER> processor_number)
|
||||
NTSTATUS handle_NtGetCurrentProcessorNumberEx(const syscall_context&, const emulator_object<PROCESSOR_NUMBER> processor_number)
|
||||
{
|
||||
constexpr PROCESSOR_NUMBER number{};
|
||||
processor_number.write(number);
|
||||
@@ -594,9 +585,8 @@ namespace syscalls
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueueApcThreadEx2(const syscall_context& c, const handle thread_handle,
|
||||
const handle /*reserve_handle*/, const uint32_t apc_flags,
|
||||
const uint64_t apc_routine, const uint64_t apc_argument1,
|
||||
NTSTATUS handle_NtQueueApcThreadEx2(const syscall_context& c, const handle thread_handle, const handle /*reserve_handle*/,
|
||||
const uint32_t apc_flags, const uint64_t apc_routine, const uint64_t apc_argument1,
|
||||
const uint64_t apc_argument2, const uint64_t apc_argument3)
|
||||
{
|
||||
auto* thread = thread_handle == CURRENT_THREAD ? c.proc.active_thread : c.proc.threads.get(thread_handle);
|
||||
@@ -624,9 +614,8 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueueApcThreadEx(const syscall_context& c, const handle thread_handle,
|
||||
const handle reserve_handle, const uint64_t apc_routine,
|
||||
const uint64_t apc_argument1, const uint64_t apc_argument2,
|
||||
NTSTATUS handle_NtQueueApcThreadEx(const syscall_context& c, const handle thread_handle, const handle reserve_handle,
|
||||
const uint64_t apc_routine, const uint64_t apc_argument1, const uint64_t apc_argument2,
|
||||
const uint64_t apc_argument3)
|
||||
{
|
||||
uint32_t flags{0};
|
||||
@@ -638,15 +627,13 @@ namespace syscalls
|
||||
static_assert(QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC == 1);
|
||||
}
|
||||
|
||||
return handle_NtQueueApcThreadEx2(c, thread_handle, real_reserve_handle, flags, apc_routine, apc_argument1,
|
||||
apc_argument2, apc_argument3);
|
||||
return handle_NtQueueApcThreadEx2(c, thread_handle, real_reserve_handle, flags, apc_routine, apc_argument1, apc_argument2,
|
||||
apc_argument3);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueueApcThread(const syscall_context& c, const handle thread_handle, const uint64_t apc_routine,
|
||||
const uint64_t apc_argument1, const uint64_t apc_argument2,
|
||||
const uint64_t apc_argument3)
|
||||
const uint64_t apc_argument1, const uint64_t apc_argument2, const uint64_t apc_argument3)
|
||||
{
|
||||
return handle_NtQueueApcThreadEx(c, thread_handle, make_handle(0), apc_routine, apc_argument1, apc_argument2,
|
||||
apc_argument3);
|
||||
return handle_NtQueueApcThreadEx(c, thread_handle, make_handle(0), apc_routine, apc_argument1, apc_argument2, apc_argument3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
namespace syscalls
|
||||
{
|
||||
NTSTATUS handle_NtQueryTimerResolution(const syscall_context&, const emulator_object<ULONG> maximum_time,
|
||||
const emulator_object<ULONG> minimum_time,
|
||||
const emulator_object<ULONG> current_time)
|
||||
const emulator_object<ULONG> minimum_time, const emulator_object<ULONG> current_time)
|
||||
{
|
||||
maximum_time.write_if_valid(0x0002625a);
|
||||
minimum_time.write_if_valid(0x00001388);
|
||||
@@ -15,8 +14,8 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetTimerResolution(const syscall_context&, const ULONG /*desired_resolution*/,
|
||||
const BOOLEAN set_resolution, const emulator_object<ULONG> current_resolution)
|
||||
NTSTATUS handle_NtSetTimerResolution(const syscall_context&, const ULONG /*desired_resolution*/, const BOOLEAN set_resolution,
|
||||
const emulator_object<ULONG> current_resolution)
|
||||
{
|
||||
if (current_resolution)
|
||||
{
|
||||
@@ -31,10 +30,9 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateTimer2(const syscall_context& c, const emulator_object<handle> timer_handle,
|
||||
uint64_t /*reserved*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG /*attributes*/, ACCESS_MASK /*desired_access*/)
|
||||
NTSTATUS handle_NtCreateTimer2(const syscall_context& c, const emulator_object<handle> timer_handle, uint64_t /*reserved*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*attributes*/,
|
||||
ACCESS_MASK /*desired_access*/)
|
||||
{
|
||||
std::u16string name{};
|
||||
if (object_attributes)
|
||||
@@ -69,10 +67,8 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateTimer(const syscall_context& c, const emulator_object<handle> timer_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG timer_type)
|
||||
NTSTATUS handle_NtCreateTimer(const syscall_context& c, const emulator_object<handle> timer_handle, ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG timer_type)
|
||||
{
|
||||
return handle_NtCreateTimer2(c, timer_handle, 0, object_attributes, timer_type, desired_access);
|
||||
}
|
||||
@@ -87,9 +83,8 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetTimerEx(const syscall_context& /*c*/, handle /*timer_handle*/,
|
||||
uint32_t /*timer_set_info_class*/, uint64_t /*timer_set_information*/,
|
||||
ULONG /*timer_set_information_length*/)
|
||||
NTSTATUS handle_NtSetTimerEx(const syscall_context& /*c*/, handle /*timer_handle*/, uint32_t /*timer_set_info_class*/,
|
||||
uint64_t /*timer_set_information*/, ULONG /*timer_set_information_length*/)
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace syscalls
|
||||
: TokenPrimary;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtDuplicateToken(const syscall_context&, const handle existing_token_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
NTSTATUS handle_NtDuplicateToken(const syscall_context&, const handle existing_token_handle, ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
|
||||
/*object_attributes*/,
|
||||
const BOOLEAN /*effective_only*/, const TOKEN_TYPE type,
|
||||
@@ -35,9 +34,8 @@ namespace syscalls
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInformationToken(const syscall_context& c, const handle token_handle,
|
||||
const TOKEN_INFORMATION_CLASS token_information_class,
|
||||
const uint64_t token_information, const ULONG token_information_length,
|
||||
const emulator_object<ULONG> return_length)
|
||||
const TOKEN_INFORMATION_CLASS token_information_class, const uint64_t token_information,
|
||||
const ULONG token_information_length, const emulator_object<ULONG> return_length)
|
||||
{
|
||||
if (token_handle != CURRENT_PROCESS_TOKEN && token_handle != CURRENT_THREAD_TOKEN &&
|
||||
token_handle != CURRENT_THREAD_EFFECTIVE_TOKEN && token_handle != DUMMY_IMPERSONATION_TOKEN)
|
||||
@@ -270,8 +268,7 @@ namespace syscalls
|
||||
|
||||
TOKEN_STATISTICS stats{};
|
||||
stats.TokenType = get_token_type(token_handle);
|
||||
stats.ImpersonationLevel =
|
||||
stats.TokenType == TokenImpersonation ? SecurityImpersonation : SecurityAnonymous;
|
||||
stats.ImpersonationLevel = stats.TokenType == TokenImpersonation ? SecurityImpersonation : SecurityAnonymous;
|
||||
stats.GroupCount = 1;
|
||||
stats.PrivilegeCount = 0;
|
||||
|
||||
@@ -304,8 +301,7 @@ namespace syscalls
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
const uint8_t medium_integrity_sid[] = {
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
constexpr auto required_size = sizeof(medium_integrity_sid) + sizeof(TOKEN_MANDATORY_LABEL64);
|
||||
@@ -321,8 +317,7 @@ namespace syscalls
|
||||
label.Label.Sid = token_information + sizeof(TOKEN_MANDATORY_LABEL64);
|
||||
|
||||
emulator_object<TOKEN_MANDATORY_LABEL64>{c.emu, token_information}.write(label);
|
||||
c.emu.write_memory(token_information + sizeof(TOKEN_MANDATORY_LABEL64), medium_integrity_sid,
|
||||
sizeof(medium_integrity_sid));
|
||||
c.emu.write_memory(token_information + sizeof(TOKEN_MANDATORY_LABEL64), medium_integrity_sid, sizeof(medium_integrity_sid));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "apiset/apiset.hpp"
|
||||
|
||||
#include "network/static_socket_factory.hpp"
|
||||
#include "memory_permission_ext.hpp"
|
||||
|
||||
constexpr auto MAX_INSTRUCTIONS_PER_TIME_SLICE = 0x20000;
|
||||
|
||||
@@ -51,6 +52,7 @@ namespace
|
||||
void perform_context_switch_work(windows_emulator& win_emu)
|
||||
{
|
||||
auto& threads = win_emu.process.threads;
|
||||
auto*& active = win_emu.process.active_thread;
|
||||
|
||||
for (auto it = threads.begin(); it != threads.end();)
|
||||
{
|
||||
@@ -60,6 +62,11 @@ namespace
|
||||
continue;
|
||||
}
|
||||
|
||||
if (active == &it->second)
|
||||
{
|
||||
active = nullptr;
|
||||
}
|
||||
|
||||
const auto [new_it, deleted] = threads.erase(it);
|
||||
if (!deleted)
|
||||
{
|
||||
@@ -253,8 +260,7 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<utils::clock> get_clock(emulator_interfaces& interfaces, const uint64_t& instructions,
|
||||
const bool use_relative_time)
|
||||
std::unique_ptr<utils::clock> get_clock(emulator_interfaces& interfaces, const uint64_t& instructions, const bool use_relative_time)
|
||||
{
|
||||
if (interfaces.clock)
|
||||
{
|
||||
@@ -284,16 +290,15 @@ namespace
|
||||
}
|
||||
|
||||
windows_emulator::windows_emulator(std::unique_ptr<x86_64_emulator> emu, application_settings app_settings,
|
||||
const emulator_settings& settings, emulator_callbacks callbacks,
|
||||
emulator_interfaces interfaces)
|
||||
const emulator_settings& settings, emulator_callbacks callbacks, emulator_interfaces interfaces)
|
||||
: windows_emulator(std::move(emu), settings, std::move(callbacks), std::move(interfaces))
|
||||
{
|
||||
fixup_application_settings(app_settings);
|
||||
this->application_settings_ = std::move(app_settings);
|
||||
}
|
||||
|
||||
windows_emulator::windows_emulator(std::unique_ptr<x86_64_emulator> emu, const emulator_settings& settings,
|
||||
emulator_callbacks callbacks, emulator_interfaces interfaces)
|
||||
windows_emulator::windows_emulator(std::unique_ptr<x86_64_emulator> emu, const emulator_settings& settings, emulator_callbacks callbacks,
|
||||
emulator_interfaces interfaces)
|
||||
: emu_(std::move(emu)),
|
||||
clock_(get_clock(interfaces, this->executed_instructions_, settings.use_relative_time)),
|
||||
socket_factory_(get_socket_factory(interfaces)),
|
||||
@@ -346,8 +351,8 @@ void windows_emulator::setup_process(const application_settings& app_settings)
|
||||
const auto& emu = this->emu();
|
||||
auto& context = this->process;
|
||||
|
||||
this->mod_manager.map_main_modules(app_settings.application, R"(C:\Windows\System32\ntdll.dll)",
|
||||
R"(C:\Windows\System32\win32u.dll)", this->log);
|
||||
this->mod_manager.map_main_modules(app_settings.application, R"(C:\Windows\System32\ntdll.dll)", R"(C:\Windows\System32\win32u.dll)",
|
||||
this->log);
|
||||
|
||||
const auto* executable = this->mod_manager.executable;
|
||||
const auto* ntdll = this->mod_manager.ntdll;
|
||||
@@ -362,8 +367,7 @@ void windows_emulator::setup_process(const application_settings& app_settings)
|
||||
|
||||
this->dispatcher.setup(ntdll->exports, ntdll_data, win32u->exports, win32u_data);
|
||||
|
||||
const auto main_thread_id =
|
||||
context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, 0, false);
|
||||
const auto main_thread_id = context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, 0, false);
|
||||
switch_to_thread(*this, main_thread_id);
|
||||
}
|
||||
|
||||
@@ -422,8 +426,8 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
|
||||
this->yield_thread();
|
||||
}
|
||||
|
||||
this->process.previous_ip = this->process.current_ip;
|
||||
this->process.current_ip = this->emu().read_instruction_pointer();
|
||||
thread.previous_ip = thread.current_ip;
|
||||
thread.current_ip = this->emu().read_instruction_pointer();
|
||||
|
||||
this->callbacks.on_instruction(address);
|
||||
}
|
||||
@@ -436,6 +440,8 @@ void windows_emulator::setup_hooks()
|
||||
});
|
||||
|
||||
this->emu().hook_instruction(x86_hookable_instructions::rdtscp, [&] {
|
||||
this->callbacks.on_rdtscp();
|
||||
|
||||
const auto ticks = this->clock_->timestamp_counter();
|
||||
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
|
||||
@@ -448,6 +454,8 @@ void windows_emulator::setup_hooks()
|
||||
});
|
||||
|
||||
this->emu().hook_instruction(x86_hookable_instructions::rdtsc, [&] {
|
||||
this->callbacks.on_rdtsc();
|
||||
|
||||
const auto ticks = this->clock_->timestamp_counter();
|
||||
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
|
||||
@@ -502,12 +510,23 @@ void windows_emulator::setup_hooks()
|
||||
}
|
||||
});
|
||||
|
||||
this->emu().hook_memory_violation([&](const uint64_t address, const size_t size, const memory_operation operation,
|
||||
const memory_violation_type type) {
|
||||
this->callbacks.on_memory_violate(address, size, operation, type);
|
||||
dispatch_access_violation(this->emu(), this->process, address, operation);
|
||||
return memory_violation_continuation::resume;
|
||||
});
|
||||
this->emu().hook_memory_violation(
|
||||
[&](const uint64_t address, const size_t size, const memory_operation operation, const memory_violation_type type) {
|
||||
auto region = this->memory.get_region_info(address);
|
||||
if (region.permissions.is_guarded())
|
||||
{
|
||||
// Unset the GUARD_PAGE flag and dispatch a STATUS_GUARD_PAGE_VIOLATION
|
||||
this->memory.protect_memory(region.allocation_base, region.length, region.permissions & ~memory_permission_ext::guard);
|
||||
dispatch_guard_page_violation(this->emu(), this->process, address, operation);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->callbacks.on_memory_violate(address, size, operation, type);
|
||||
dispatch_access_violation(this->emu(), this->process, address, operation);
|
||||
}
|
||||
|
||||
return memory_violation_continuation::resume;
|
||||
});
|
||||
|
||||
this->emu().hook_memory_execution([&](const uint64_t address) {
|
||||
this->on_instruction_execution(address); //
|
||||
|
||||
@@ -27,11 +27,14 @@ struct emulator_callbacks : module_manager::callbacks, process_context::callback
|
||||
opt_func<void(uint64_t address, uint64_t length, memory_permission, bool commit)> on_memory_allocate{};
|
||||
opt_func<void(uint64_t address, uint64_t length, memory_operation, memory_violation_type type)> on_memory_violate{};
|
||||
|
||||
opt_func<void()> on_rdtsc{};
|
||||
opt_func<void()> on_rdtscp{};
|
||||
opt_func<continuation(uint32_t syscall_id, std::string_view syscall_name)> on_syscall{};
|
||||
opt_func<void(std::string_view data)> on_stdout{};
|
||||
opt_func<void(std::string_view type, std::u16string_view name)> on_generic_access{};
|
||||
opt_func<void(std::string_view description)> on_generic_activity{};
|
||||
opt_func<void(std::string_view description)> on_suspicious_activity{};
|
||||
opt_func<void(std::string_view message)> on_debug_string{};
|
||||
opt_func<void(uint64_t address)> on_instruction{};
|
||||
opt_func<void(io_device& device, std::u16string_view device_name, ULONG code)> on_ioctrl{};
|
||||
};
|
||||
@@ -95,11 +98,10 @@ class windows_emulator
|
||||
process_context process;
|
||||
syscall_dispatcher dispatcher;
|
||||
|
||||
windows_emulator(std::unique_ptr<x86_64_emulator> emu, const emulator_settings& settings = {},
|
||||
emulator_callbacks callbacks = {}, emulator_interfaces interfaces = {});
|
||||
windows_emulator(std::unique_ptr<x86_64_emulator> emu, application_settings app_settings,
|
||||
const emulator_settings& settings = {}, emulator_callbacks callbacks = {},
|
||||
windows_emulator(std::unique_ptr<x86_64_emulator> emu, const emulator_settings& settings = {}, emulator_callbacks callbacks = {},
|
||||
emulator_interfaces interfaces = {});
|
||||
windows_emulator(std::unique_ptr<x86_64_emulator> emu, application_settings app_settings, const emulator_settings& settings = {},
|
||||
emulator_callbacks callbacks = {}, emulator_interfaces interfaces = {});
|
||||
|
||||
windows_emulator(windows_emulator&&) = delete;
|
||||
windows_emulator(const windows_emulator&) = delete;
|
||||
|
||||
@@ -74,8 +74,7 @@ class windows_path
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(!std::is_same_v<std::remove_cvref_t<T>, windows_path> &&
|
||||
!std::is_same_v<std::remove_cvref_t<T>, std::filesystem::path> &&
|
||||
requires(!std::is_same_v<std::remove_cvref_t<T>, windows_path> && !std::is_same_v<std::remove_cvref_t<T>, std::filesystem::path> &&
|
||||
!std::is_same_v<std::remove_cvref_t<T>, utils::buffer_deserializer>)
|
||||
windows_path(T&& path_like)
|
||||
: windows_path(std::filesystem::path(std::forward<T>(path_like)))
|
||||
|
||||
Reference in New Issue
Block a user