fix(syscalls): fix VirtualQuery return size, ignore unimplemented APC flags and log a warning. (#202)

fix(syscalls): fix VirtualQuery return size, ignore unimplemented APC
flags and log a warning.
This commit is contained in:
Maurice Heumann
2025-04-14 13:22:10 +02:00
committed by GitHub
9 changed files with 169 additions and 39 deletions

View File

@@ -73,6 +73,7 @@
#define SL_NO_CURSOR_UPDATE 0x10
#define SEC_IMAGE 0x01000000
#define SEC_RESERVE 0x04000000
typedef enum _FSINFOCLASS
{
@@ -97,7 +98,7 @@ typedef enum _FSINFOCLASS
FileFsMaximumInformation
} FSINFOCLASS, *PFSINFOCLASS;
typedef enum _FSINFOCLASS FS_INFORMATION_CLASS;
using FS_INFORMATION_CLASS = enum _FSINFOCLASS;
typedef enum _FILE_INFORMATION_CLASS
{
@@ -210,7 +211,7 @@ typedef enum _FILE_INFORMATION_CLASS
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef enum _OBJECT_INFORMATION_CLASS
using OBJECT_INFORMATION_CLASS = enum _OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation, // q: OBJECT_BASIC_INFORMATION
ObjectNameInformation, // q: OBJECT_NAME_INFORMATION
@@ -220,9 +221,9 @@ typedef enum _OBJECT_INFORMATION_CLASS
ObjectSessionInformation, // s: void // change object session // (requires SeTcbPrivilege)
ObjectSessionObjectInformation, // s: void // change object session // (requires SeTcbPrivilege)
MaxObjectInfoClass
} OBJECT_INFORMATION_CLASS;
};
typedef enum _HARDERROR_RESPONSE_OPTION
using HARDERROR_RESPONSE_OPTION = enum _HARDERROR_RESPONSE_OPTION
{
OptionAbortRetryIgnore,
OptionOk,
@@ -233,9 +234,9 @@ typedef enum _HARDERROR_RESPONSE_OPTION
OptionShutdownSystem,
OptionOkNoWait,
OptionCancelTryContinue
} HARDERROR_RESPONSE_OPTION;
};
typedef enum _HARDERROR_RESPONSE
using HARDERROR_RESPONSE = enum _HARDERROR_RESPONSE
{
ResponseReturnToCaller,
ResponseNotHandled,
@@ -248,9 +249,9 @@ typedef enum _HARDERROR_RESPONSE
ResponseYes,
ResponseTryAgain,
ResponseContinue
} HARDERROR_RESPONSE;
};
typedef USHORT RTL_ATOM;
using RTL_ATOM = USHORT;
template <typename Traits>
struct IO_STATUS_BLOCK
@@ -333,6 +334,17 @@ typedef struct _FILE_BASIC_INFORMATION
ULONG FileAttributes; // Specifies one or more FILE_ATTRIBUTE_XXX flags.
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
typedef struct _FILE_NETWORK_OPEN_INFORMATION
{
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG FileAttributes;
} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
typedef struct _FILE_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;

View File

@@ -25,7 +25,7 @@
(CONTEXT_CONTROL_64 | CONTEXT_INTEGER_64 | CONTEXT_SEGMENTS_64 | CONTEXT_FLOATING_POINT_64 | \
CONTEXT_DEBUG_REGISTERS_64)
typedef enum _SYSTEM_INFORMATION_CLASS
using SYSTEM_INFORMATION_CLASS = enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION
SystemProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION
@@ -323,7 +323,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemBreakOnContextUnwindFailureInformation, // ULONG (requires SeDebugPrivilege)
SystemOslRamdiskInformation, // SYSTEM_OSL_RAMDISK_INFORMATION
MaxSystemInfoClass
} SYSTEM_INFORMATION_CLASS;
};
#ifndef OS_WINDOWS
typedef enum _TOKEN_INFORMATION_CLASS
@@ -383,7 +383,7 @@ typedef enum _TOKEN_INFORMATION_CLASS
#endif
typedef enum _PROCESSINFOCLASS
using PROCESSINFOCLASS = enum _PROCESSINFOCLASS
{
ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
@@ -502,9 +502,9 @@ typedef enum _PROCESSINFOCLASS
ProcessNetworkIoCounters, // q: PROCESS_NETWORK_COUNTERS
ProcessFindFirstThreadByTebValue, // PROCESS_TEB_VALUE_INFORMATION
MaxProcessInfoClass
} PROCESSINFOCLASS;
};
typedef enum _PS_ATTRIBUTE_NUM
using PS_ATTRIBUTE_NUM = enum _PS_ATTRIBUTE_NUM
{
PsAttributeParentProcess, // in HANDLE
PsAttributeDebugObject, // in HANDLE
@@ -542,7 +542,7 @@ typedef enum _PS_ATTRIBUTE_NUM
PsAttributeSupportedMachines, // since 24H2
PsAttributeSveVectorLength, // PPS_PROCESS_CREATION_SVE_VECTOR_LENGTH
PsAttributeMax
} PS_ATTRIBUTE_NUM;
};
struct SYSTEM_PROCESSOR_INFORMATION64
{
@@ -583,11 +583,11 @@ typedef struct _XMM_SAVE_AREA32
#endif
typedef struct _NEON128
using NEON128 = struct _NEON128
{
ULONGLONG Low;
LONGLONG High;
} NEON128;
};
typedef struct DECLSPEC_ALIGN(16) _CONTEXT64
{
@@ -768,6 +768,11 @@ struct TOKEN_USER64
SID_AND_ATTRIBUTES64 User;
};
struct TOKEN_OWNER64
{
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PSID) Owner;
};
struct TOKEN_BNO_ISOLATION_INFORMATION64
{
EmulatorTraits<Emu64>::PVOID IsolationPrefix;

View File

@@ -79,6 +79,9 @@ namespace syscalls
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,
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
@@ -93,6 +96,19 @@ namespace syscalls
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,
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);
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);
// syscalls/locale.cpp:
NTSTATUS handle_NtInitializeNlsFiles(const syscall_context& c, emulator_object<uint64_t> base_address,
@@ -109,7 +125,7 @@ namespace syscalls
// 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,
uint32_t memory_information_length, emulator_object<uint32_t> return_length);
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,
@@ -769,6 +785,9 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtQueueApcThreadEx);
add_handler(NtQueueApcThread);
add_handler(NtCreateUserProcess);
add_handler(NtCreateNamedPipeFile);
add_handler(NtFsControlFile);
add_handler(NtQueryFullAttributesFile);
#undef add_handler
}
}

View File

@@ -24,10 +24,10 @@ 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)
{

View File

@@ -1,6 +1,7 @@
#include "../std_include.hpp"
#include "../emulator_utils.hpp"
#include "../syscall_utils.hpp"
#include "utils/io.hpp"
#include <iostream>
#include <utils/finally.hpp>
@@ -660,6 +661,47 @@ 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)
{
if (!object_attributes)
{
return STATUS_INVALID_PARAMETER;
}
const auto attributes = object_attributes.read();
if (!attributes.ObjectName)
{
return STATUS_INVALID_PARAMETER;
}
const auto filename = read_unicode_string(
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str());
const auto local_filename = c.win_emu.file_sys.translate(filename).string();
struct _stat64 file_stat{};
if (_stat64(local_filename.c_str(), &file_stat) != 0)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
file_information.access([&](FILE_NETWORK_OPEN_INFORMATION& info) {
info.CreationTime = utils::convert_unix_to_windows_time(file_stat.st_atime);
info.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime);
info.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime);
info.AllocationSize.QuadPart = file_stat.st_size;
info.EndOfFile.QuadPart = file_stat.st_size;
info.ChangeTime = info.LastWriteTime;
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
});
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)
@@ -778,4 +820,32 @@ 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*/)
{
c.win_emu.log.error("Unimplemented syscall NtCreateNamedPipeFile!");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
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*/)
{
c.win_emu.log.error("Unimplemented syscall NtFsControlFile!");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
}

View File

@@ -8,8 +8,8 @@ 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 uint32_t memory_information_length,
const emulator_object<uint32_t> return_length)
const uint64_t memory_information, const uint64_t memory_information_length,
const emulator_object<uint64_t> return_length)
{
if (process_handle != CURRENT_PROCESS)
{
@@ -28,9 +28,9 @@ namespace syscalls
return_length.write(sizeof(EMU_MEMORY_BASIC_INFORMATION64));
}
if (memory_information_length != sizeof(EMU_MEMORY_BASIC_INFORMATION64))
if (memory_information_length < sizeof(EMU_MEMORY_BASIC_INFORMATION64))
{
return STATUS_BUFFER_OVERFLOW;
return STATUS_BUFFER_TOO_SMALL;
}
const emulator_object<EMU_MEMORY_BASIC_INFORMATION64> info{c.emu, memory_information};
@@ -198,7 +198,7 @@ namespace syscalls
const bool reserve = allocation_type & MEM_RESERVE;
const bool commit = allocation_type & MEM_COMMIT;
if ((allocation_type & ~(MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN)) || (!commit && !reserve))
if ((allocation_type & ~(MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN | MEM_WRITE_WATCH)) || (!commit && !reserve))
{
throw std::runtime_error("Unsupported allocation type!");
}

View File

@@ -225,10 +225,11 @@ namespace syscalls
size = page_align_up(file_data.size());
}
const auto reserve_only = section_entry->allocation_attributes == SEC_RESERVE;
const auto protection = map_nt_to_emulator_protection(section_entry->section_page_protection);
const auto address = c.win_emu.memory.allocate_memory(size, protection);
const auto address = c.win_emu.memory.allocate_memory(size, protection, reserve_only);
if (!file_data.empty())
if (!reserve_only && !file_data.empty())
{
c.emu.write_memory(address, file_data.data(), file_data.size());
}
@@ -263,19 +264,24 @@ namespace syscalls
}
const auto* mod = c.win_emu.mod_manager.find_by_address(base_address);
if (!mod)
if (mod != nullptr)
{
c.win_emu.log.error("Unmapping non-module section not supported!\n");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
if (c.win_emu.mod_manager.unmap(base_address, c.win_emu.log))
{
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
if (c.win_emu.mod_manager.unmap(base_address, c.win_emu.log))
if (c.win_emu.memory.release_memory(base_address, 0))
{
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
c.win_emu.log.error("Unmapping non-module/non-memory section not supported!\n");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, const handle process_handle,

View File

@@ -577,9 +577,9 @@ namespace syscalls
if (apc_flags)
{
c.win_emu.log.error("Unsupported APC flags: %X\n", apc_flags);
c.emu.stop();
return STATUS_NOT_SUPPORTED;
c.win_emu.log.warn("Unsupported APC flags: %X\n", apc_flags);
// c.emu.stop();
// return STATUS_NOT_SUPPORTED;
}
thread->pending_apcs.push_back({
@@ -590,7 +590,7 @@ namespace syscalls
.apc_argument3 = apc_argument3,
});
return STATUS_NOT_SUPPORTED;
return STATUS_SUCCESS;
}
NTSTATUS handle_NtQueueApcThreadEx(const syscall_context& c, const handle thread_handle,

View File

@@ -75,6 +75,24 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (token_information_class == TokenOwner)
{
constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_OWNER64);
return_length.write(required_size);
if (required_size > token_information_length)
{
return STATUS_BUFFER_TOO_SMALL;
}
TOKEN_OWNER64 owner{};
owner.Owner = token_information + sizeof(TOKEN_OWNER64);
emulator_object<TOKEN_OWNER64>{c.emu, token_information}.write(owner);
c.emu.write_memory(token_information + sizeof(TOKEN_OWNER64), sid, sizeof(sid));
return STATUS_SUCCESS;
}
if (token_information_class == TokenType)
{
constexpr auto required_size = sizeof(TOKEN_TYPE);