Add KsecDD device and other improvements (#357)

This PR aims to:
- [Improve
NtQueryInformationToken](d7b8b78cef),
by handling more token types and also fixing TokenIntegrityLevel to
return a proper integrity SID.
- [Add new
pseudo-handles](ac804939d9).
- [Add the KsecDD device and support for devices in
NtQueryObject](ca61a7cd3b).
- [Add new
syscalls](4b6e0f088d),
to be more specific, the syscalls added were the following ones:
`NtRemoveIoCompletion`, `NtSetInformationWorkerFactory`,
`NtShutdownWorkerFactory`, `NtGetCurrentProcessorNumber`,
`NtCreateTimer`, `NtSetTimer`, `NtSetTimer2`, `NtCancelTimer`,
`NtAssociateWaitCompletionPacket`, `NtCancelWaitCompletionPacket`,
`NtSetWnfProcessNotificationEvent`, `NtQuerySecurityObject`.

Most of the changes in this PR were made to get BCryptGenRandom working
in the emulator. Even with the KsecDD device implemented,
BCryptGenRandom only works for subsequent calls if NtCreateWorkerFactory
returns STATUS_SUCCESS. Returning STATUS_SUCCESS from
NtCreateWorkerFactory causes most of the newly added syscalls to be
called, and most of them need to return STATUS_SUCCESS as well;
otherwise, the executable just fails to run. Fortunately, from my
testing, nothing seems to break from just returning STATUS_SUCCESS
without a proper implementation.
This commit is contained in:
Maurice Heumann
2025-06-02 19:53:16 +02:00
committed by GitHub
13 changed files with 512 additions and 19 deletions

View File

@@ -785,6 +785,43 @@ struct TOKEN_OWNER64
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PSID) Owner;
};
struct TOKEN_PRIMARY_GROUP64
{
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PSID) PrimaryGroup;
};
#ifndef OS_WINDOWS
struct ACL
{
BYTE AclRevision;
BYTE Sbz1;
WORD AclSize;
WORD AceCount;
WORD Sbz2;
};
struct ACE_HEADER
{
BYTE AceType;
BYTE AceFlags;
WORD AceSize;
};
typedef DWORD ACCESS_MASK;
struct ACCESS_ALLOWED_ACE
{
ACE_HEADER Header;
ACCESS_MASK Mask;
DWORD SidStart;
};
#endif
struct TOKEN_DEFAULT_DACL64
{
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PACL) DefaultDacl;
};
struct TOKEN_BNO_ISOLATION_INFORMATION64
{
EmulatorTraits<Emu64>::PVOID IsolationPrefix;
@@ -796,6 +833,11 @@ struct TOKEN_MANDATORY_LABEL64
SID_AND_ATTRIBUTES64 Label;
};
struct TOKEN_PROCESS_TRUST_LEVEL64
{
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PSID) TrustLevelSid;
};
#ifndef OS_WINDOWS
typedef enum _TOKEN_TYPE
@@ -852,6 +894,52 @@ typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION
} Attribute;
} TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION;
#ifndef OS_WINDOWS
#define SECURITY_DESCRIPTOR_REVISION 1
#define SECURITY_DESCRIPTOR_REVISION1 1
typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
#define SE_OWNER_DEFAULTED 0x0001
#define SE_GROUP_DEFAULTED 0x0002
#define SE_DACL_PRESENT 0x0004
#define SE_DACL_DEFAULTED 0x0008
#define SE_SACL_PRESENT 0x0010
#define SE_SACL_DEFAULTED 0x0020
#define SE_DACL_AUTO_INHERIT_REQ 0x0100
#define SE_SACL_AUTO_INHERIT_REQ 0x0200
#define SE_DACL_AUTO_INHERITED 0x0400
#define SE_SACL_AUTO_INHERITED 0x0800
#define SE_DACL_PROTECTED 0x1000
#define SE_SACL_PROTECTED 0x2000
#define SE_RM_CONTROL_VALID 0x4000
#define SE_SELF_RELATIVE 0x8000
struct SECURITY_DESCRIPTOR_RELATIVE
{
BYTE Revision;
BYTE Sbz1;
SECURITY_DESCRIPTOR_CONTROL Control;
DWORD Owner;
DWORD Group;
DWORD Sacl;
DWORD Dacl;
};
typedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION;
#define OWNER_SECURITY_INFORMATION 0x00000001L
#define GROUP_SECURITY_INFORMATION 0x00000002L
#define DACL_SECURITY_INFORMATION 0x00000004L
#define SACL_SECURITY_INFORMATION 0x00000008L
#define LABEL_SECURITY_INFORMATION 0x00000010L
#define ATTRIBUTE_SECURITY_INFORMATION 0x00000020L
#define SCOPE_SECURITY_INFORMATION 0x00000040L
#define PROCESS_TRUST_LABEL_SECURITY_INFORMATION 0x00000080L
#define ACCESS_FILTER_SECURITY_INFORMATION 0x00000100L
#define BACKUP_SECURITY_INFORMATION 0x00010000L
#endif
struct GDI_HANDLE_ENTRY64
{
union

View File

@@ -0,0 +1,58 @@
#include "../std_include.hpp"
#include "security_support_provider.hpp"
#include "../windows_emulator.hpp"
namespace
{
struct security_support_provider : stateless_device
{
// 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};
NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& c) override
{
win_emu.log.print(color::dark_gray, "--> KSEC IOCTL: 0x%X\n", c.io_control_code);
if (c.io_control_code != 0x390400)
{
return STATUS_NOT_SUPPORTED;
}
const auto operation = win_emu.emu().read_memory<USHORT>(c.input_buffer + 6);
if (operation == 2)
{
win_emu.emu().write_memory(c.output_buffer, output_data);
if (c.io_status_block)
{
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
block.Information = sizeof(output_data);
c.io_status_block.write(block);
}
}
return STATUS_SUCCESS;
}
};
}
std::unique_ptr<io_device> create_security_support_provider()
{
return std::make_unique<security_support_provider>();
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "../io_device.hpp"
std::unique_ptr<io_device> create_security_support_provider();

View File

@@ -408,6 +408,7 @@ constexpr auto NULL_HANDLE = make_handle(0ULL);
constexpr auto KNOWN_DLLS_DIRECTORY = make_pseudo_handle(0x1, handle_types::directory);
constexpr auto BASE_NAMED_OBJECTS_DIRECTORY = make_pseudo_handle(0x2, handle_types::directory);
constexpr auto RPC_CONTROL_DIRECTORY = make_pseudo_handle(0x3, handle_types::directory);
constexpr auto KNOWN_DLLS_SYMLINK = make_pseudo_handle(0x1, handle_types::symlink);
constexpr auto SHARED_SECTION = make_pseudo_handle(0x1, handle_types::section);
@@ -417,6 +418,7 @@ constexpr auto WER_PORT_READY = make_pseudo_handle(0x1, handle_types::event);
constexpr auto DBWIN_DATA_READY = make_pseudo_handle(0x2, handle_types::event);
constexpr auto DBWIN_BUFFER_READY = make_pseudo_handle(0x3, handle_types::event);
constexpr auto SVCCTRL_START_EVENT = make_pseudo_handle(0x4, handle_types::event);
constexpr auto LSA_AUTHENTICATION_INITIALIZED = make_pseudo_handle(0x5, handle_types::event);
constexpr auto CONSOLE_HANDLE = make_pseudo_handle(0x1, handle_types::file);
constexpr auto STDOUT_HANDLE = make_pseudo_handle(0x2, handle_types::file);

View File

@@ -2,6 +2,7 @@
#include "io_device.hpp"
#include "devices/afd_endpoint.hpp"
#include "devices/mount_point_manager.hpp"
#include "devices/security_support_provider.hpp"
namespace
{
@@ -19,7 +20,6 @@ std::unique_ptr<io_device> create_device(const std::u16string_view device)
if (device == u"CNG" //
|| device == u"Nsi" //
|| device == u"RasAcd" //
|| device == u"KsecDD" //
|| device == u"PcwDrv" //
|| device == u"DeviceApi\\CMApi" //
|| device == u"ConDrv\\Server")
@@ -42,5 +42,10 @@ std::unique_ptr<io_device> create_device(const std::u16string_view device)
return create_mount_point_manager();
}
if (device == u"KsecDD")
{
return create_security_support_provider();
}
throw std::runtime_error("Unsupported device: " + u16_to_u8(device));
}

View File

@@ -175,13 +175,25 @@ class io_device_container : public io_device
template <typename T = io_device>
requires(std::is_base_of_v<io_device, T> || std::is_same_v<io_device, T>)
T* get_internal_device()
T* get_internal_device() const
{
this->assert_validity();
auto* value = this->device_.get();
return dynamic_cast<T*>(value);
}
std::u16string_view get_device_name() const
{
this->assert_validity();
return this->device_name_;
}
std::u16string get_device_path() const
{
this->assert_validity();
return u"\\Device\\" + this->device_name_;
}
private:
std::u16string device_name_{};
std::unique_ptr<io_device> device_{};

View File

@@ -183,6 +183,10 @@ namespace syscalls
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);
// syscalls/port.cpp:
NTSTATUS handle_NtConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
@@ -344,6 +348,7 @@ namespace syscalls
emulator_object<PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>> attribute_list);
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);
@@ -361,8 +366,15 @@ namespace syscalls
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);
NTSTATUS handle_NtSetTimer();
NTSTATUS handle_NtSetTimer2();
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_NtCancelTimer();
// syscalls/token.cpp:
NTSTATUS
@@ -410,7 +422,17 @@ namespace syscalls
NTSTATUS handle_NtCreateWorkerFactory()
{
return STATUS_NOT_SUPPORTED;
return STATUS_SUCCESS;
}
NTSTATUS handle_NtSetInformationWorkerFactory()
{
return STATUS_SUCCESS;
}
NTSTATUS handle_NtShutdownWorkerFactory()
{
return STATUS_SUCCESS;
}
NTSTATUS handle_NtCreateIoCompletion(
@@ -426,6 +448,21 @@ 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)
{
if (timeout && timeout.read().QuadPart == 0)
{
return STATUS_TIMEOUT;
}
key_context.write_if_valid(-1);
return STATUS_SUCCESS;
}
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)
@@ -925,6 +962,21 @@ namespace syscalls
return STATUS_SUCCESS;
}
NTSTATUS handle_NtAssociateWaitCompletionPacket()
{
return STATUS_SUCCESS;
}
NTSTATUS handle_NtCancelWaitCompletionPacket()
{
return STATUS_SUCCESS;
}
NTSTATUS handle_NtSetWnfProcessNotificationEvent()
{
return STATUS_NOT_SUPPORTED;
}
}
void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& handler_mapping)
@@ -957,8 +1009,11 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtAllocateVirtualMemoryEx);
add_handler(NtCreateIoCompletion);
add_handler(NtSetIoCompletion);
add_handler(NtRemoveIoCompletion);
add_handler(NtCreateWaitCompletionPacket);
add_handler(NtCreateWorkerFactory);
add_handler(NtSetInformationWorkerFactory);
add_handler(NtShutdownWorkerFactory);
add_handler(NtManageHotPatch);
add_handler(NtOpenSection);
add_handler(NtMapViewOfSection);
@@ -1035,6 +1090,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtCreateKey);
add_handler(NtNotifyChangeKey);
add_handler(NtGetCurrentProcessorNumberEx);
add_handler(NtGetCurrentProcessorNumber);
add_handler(NtQueryObject);
add_handler(NtQueryAttributesFile);
add_handler(NtWaitForMultipleObjects);
@@ -1105,8 +1161,16 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtQueryInformationByName);
add_handler(NtUserSetCursor);
add_handler(NtOpenMutant);
add_handler(NtCreateTimer);
add_handler(NtCreateTimer2);
add_handler(NtSetTimer);
add_handler(NtSetTimer2);
add_handler(NtSetTimerEx);
add_handler(NtCancelTimer);
add_handler(NtAssociateWaitCompletionPacket);
add_handler(NtCancelWaitCompletionPacket);
add_handler(NtSetWnfProcessNotificationEvent);
add_handler(NtQuerySecurityObject);
#undef add_handler
}

View File

@@ -114,6 +114,12 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (name == u"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED")
{
event_handle.write(LSA_AUTHENTICATION_INITIALIZED.bits);
return STATUS_SUCCESS;
}
if (name == u"DBWIN_DATA_READY")
{
event_handle.write(DBWIN_DATA_READY.bits);

View File

@@ -1022,6 +1022,12 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (object_name == u"\\RPC Control")
{
directory_handle.write(RPC_CONTROL_DIRECTORY);
return STATUS_SUCCESS;
}
return STATUS_NOT_SUPPORTED;
}

View File

@@ -70,21 +70,35 @@ namespace syscalls
{
if (object_information_class == ObjectNameInformation)
{
if (handle.value.type != handle_types::file)
std::u16string device_path;
switch (handle.value.type)
{
case handle_types::file: {
const auto* file = c.proc.files.get(handle);
if (!file)
{
return STATUS_INVALID_HANDLE;
}
device_path = windows_path(file->name).to_device_path();
break;
}
case handle_types::device: {
const auto* device = c.proc.devices.get(handle);
if (!device)
{
return STATUS_INVALID_HANDLE;
}
device_path = device->get_device_path();
break;
}
default:
c.win_emu.log.error("Unsupported handle type for name information query: %X\n", handle.value.type);
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
const auto* file = c.proc.files.get(handle);
if (!file)
{
return STATUS_INVALID_HANDLE;
}
const auto device_path = windows_path(file->name).to_device_path();
const auto required_size = sizeof(UNICODE_STRING<EmulatorTraits<Emu64>>) + (device_path.size() + 1) * 2;
return_length.write(static_cast<ULONG>(required_size));
@@ -187,4 +201,120 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
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)
{
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};
// Group SID: S-1-5-18 (Local System)
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
const uint8_t group_sid[] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00};
// 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};
// 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};
ULONG total_size = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
if (security_information & OWNER_SECURITY_INFORMATION)
{
total_size += sizeof(owner_sid);
}
if (security_information & GROUP_SECURITY_INFORMATION)
{
total_size += sizeof(group_sid);
}
if (security_information & DACL_SECURITY_INFORMATION)
{
total_size += sizeof(dacl_data);
}
if (security_information & LABEL_SECURITY_INFORMATION)
{
total_size += sizeof(sacl_data);
}
length_needed.write(total_size);
if (length < total_size)
{
return STATUS_BUFFER_TOO_SMALL;
}
if (!security_descriptor)
{
return STATUS_INVALID_PARAMETER;
}
SECURITY_DESCRIPTOR_RELATIVE sd = {};
sd.Revision = SECURITY_DESCRIPTOR_REVISION;
sd.Control = SE_SELF_RELATIVE;
ULONG current_offset = sizeof(sd);
if (security_information & OWNER_SECURITY_INFORMATION)
{
sd.Owner = current_offset;
c.emu.write_memory(security_descriptor + current_offset, owner_sid);
current_offset += sizeof(owner_sid);
}
if (security_information & GROUP_SECURITY_INFORMATION)
{
sd.Group = current_offset;
c.emu.write_memory(security_descriptor + current_offset, group_sid);
current_offset += sizeof(group_sid);
}
if (security_information & DACL_SECURITY_INFORMATION)
{
sd.Control |= SE_DACL_PRESENT;
sd.Dacl = current_offset;
c.emu.write_memory(security_descriptor + current_offset, dacl_data);
current_offset += sizeof(dacl_data);
}
if (security_information & LABEL_SECURITY_INFORMATION)
{
sd.Control |= SE_SACL_PRESENT | SE_SACL_AUTO_INHERITED;
sd.Sacl = current_offset;
c.emu.write_memory(security_descriptor + current_offset, sacl_data);
current_offset += sizeof(sacl_data);
}
assert(current_offset == total_size);
c.emu.write_memory(security_descriptor, sd);
return STATUS_SUCCESS;
}
}

View File

@@ -584,6 +584,11 @@ namespace syscalls
return STATUS_SUCCESS;
}
ULONG handle_NtGetCurrentProcessorNumber()
{
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,

View File

@@ -69,10 +69,33 @@ 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)
{
return handle_NtCreateTimer2(c, timer_handle, 0, object_attributes, timer_type, desired_access);
}
NTSTATUS handle_NtSetTimer()
{
return STATUS_SUCCESS;
}
NTSTATUS handle_NtSetTimer2()
{
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*/)
{
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtCancelTimer()
{
return STATUS_SUCCESS;
}
}

View File

@@ -58,7 +58,7 @@ namespace syscalls
if (token_information_class == TokenUser)
{
constexpr auto required_size = sizeof(sid) + 0x10;
constexpr auto required_size = sizeof(TOKEN_USER64) + sizeof(sid);
return_length.write(required_size);
if (required_size > token_information_length)
@@ -68,10 +68,10 @@ namespace syscalls
TOKEN_USER64 user{};
user.User.Attributes = 0;
user.User.Sid = token_information + 0x10;
user.User.Sid = token_information + sizeof(TOKEN_USER64);
emulator_object<TOKEN_USER64>{c.emu, token_information}.write(user);
c.emu.write_memory(token_information + 0x10, sid, sizeof(sid));
c.emu.write_memory(token_information + sizeof(TOKEN_USER64), sid, sizeof(sid));
return STATUS_SUCCESS;
}
@@ -113,6 +113,65 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (token_information_class == TokenPrimaryGroup)
{
constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_PRIMARY_GROUP64);
return_length.write(required_size);
if (required_size > token_information_length)
{
return STATUS_BUFFER_TOO_SMALL;
}
TOKEN_PRIMARY_GROUP64 primary_group{};
primary_group.PrimaryGroup = token_information + sizeof(TOKEN_PRIMARY_GROUP64);
emulator_object<TOKEN_PRIMARY_GROUP64>{c.emu, token_information}.write(primary_group);
c.emu.write_memory(token_information + sizeof(TOKEN_PRIMARY_GROUP64), sid, sizeof(sid));
return STATUS_SUCCESS;
}
if (token_information_class == TokenDefaultDacl)
{
constexpr auto acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sid) - sizeof(ULONG);
constexpr auto required_size = sizeof(TOKEN_DEFAULT_DACL64) + acl_size;
return_length.write(required_size);
if (required_size > token_information_length)
{
return STATUS_BUFFER_TOO_SMALL;
}
TOKEN_DEFAULT_DACL64 default_dacl{};
default_dacl.DefaultDacl = token_information + sizeof(TOKEN_DEFAULT_DACL64);
emulator_object<TOKEN_DEFAULT_DACL64>{c.emu, token_information}.write(default_dacl);
const auto acl_offset = token_information + sizeof(TOKEN_DEFAULT_DACL64);
ACL acl{};
acl.AclRevision = 2; // ACL_REVISION
acl.Sbz1 = 0;
acl.AclSize = static_cast<USHORT>(acl_size);
acl.AceCount = 1;
acl.Sbz2 = 0;
c.emu.write_memory(acl_offset, acl);
const auto ace_offset = acl_offset + sizeof(ACL);
ACCESS_ALLOWED_ACE ace{};
ace.Header.AceType = 0; // ACCESS_ALLOWED_ACE_TYPE
ace.Header.AceFlags = 0;
ace.Header.AceSize = static_cast<USHORT>(sizeof(ACCESS_ALLOWED_ACE) + sizeof(sid) - sizeof(ULONG));
ace.Mask = GENERIC_ALL;
c.emu.write_memory(ace_offset, ace);
const auto sid_offset = ace_offset + sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG);
c.emu.write_memory(sid_offset, sid, sizeof(sid));
return STATUS_SUCCESS;
}
if (token_information_class == TokenType)
{
constexpr auto required_size = sizeof(TOKEN_TYPE);
@@ -209,7 +268,14 @@ namespace syscalls
return STATUS_BUFFER_TOO_SMALL;
}
c.emu.write_memory(token_information, TOKEN_STATISTICS{});
TOKEN_STATISTICS stats{};
stats.TokenType = get_token_type(token_handle);
stats.ImpersonationLevel =
stats.TokenType == TokenImpersonation ? SecurityImpersonation : SecurityAnonymous;
stats.GroupCount = 1;
stats.PrivilegeCount = 0;
c.emu.write_memory(token_information, stats);
return STATUS_SUCCESS;
}
@@ -236,7 +302,13 @@ namespace syscalls
if (token_information_class == TokenIntegrityLevel)
{
constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_MANDATORY_LABEL64);
// 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,
};
constexpr auto required_size = sizeof(medium_integrity_sid) + sizeof(TOKEN_MANDATORY_LABEL64);
return_length.write(required_size);
if (required_size > token_information_length)
@@ -245,11 +317,29 @@ namespace syscalls
}
TOKEN_MANDATORY_LABEL64 label{};
label.Label.Attributes = 0;
label.Label.Attributes = 0x60;
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), sid, sizeof(sid));
c.emu.write_memory(token_information + sizeof(TOKEN_MANDATORY_LABEL64), medium_integrity_sid,
sizeof(medium_integrity_sid));
return STATUS_SUCCESS;
}
if (token_information_class == TokenProcessTrustLevel)
{
constexpr auto required_size = sizeof(TOKEN_PROCESS_TRUST_LEVEL64);
return_length.write(required_size);
if (required_size > token_information_length)
{
return STATUS_BUFFER_TOO_SMALL;
}
c.emu.write_memory(token_information, TOKEN_PROCESS_TRUST_LEVEL64{
.TrustLevelSid = 0,
});
return STATUS_SUCCESS;
}