mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 19:23:56 +00:00
Load environment variables from registry and other fixes (#243)
This PR aims to: - [Fix TimeZoneInformation](496fbd3a40) by moving `wDayOfWeek` to the end of the `SYSTEMTIME` structure. This goes against the public definitions of the `SYSTEMTIME` struct but I can confirm that this yields correct values when `GetTimeZoneInformation` is called. - [Load environment variables from registry](9d5338b168). - [Miscellaneous fixes](a629f77e31), to be more specific: - Add `NtOpenProcess` syscall stub. - Add logging to `handle_file_enumeration`. - Fix `FILE_ATTRIBUTE_NORMAL` being together with `FILE_ATTRIBUTE_DIRECTORY` (`FILE_ATTRIBUTE_NORMAL` means "no attributes are set"). - Properly handle relative filenames in `NtQueryFullAttributesFile`. - Properly handle "trap flag". - Handle "DbgPrint" interrupt.
This commit is contained in:
@@ -863,28 +863,26 @@ typedef struct _SYSTEM_TIMEOFDAY_INFORMATION64
|
||||
ULONGLONG SleepTimeBias;
|
||||
} SYSTEM_TIMEOFDAY_INFORMATION64, *PSYSTEM_TIMEOFDAY_INFORMATION64;
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
typedef struct _SYSTEMTIME
|
||||
typedef struct _SYSTEMTIME64
|
||||
{
|
||||
WORD wYear;
|
||||
WORD wMonth;
|
||||
WORD wDayOfWeek;
|
||||
WORD wDay;
|
||||
WORD wHour;
|
||||
WORD wMinute;
|
||||
WORD wSecond;
|
||||
WORD wMilliseconds;
|
||||
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
|
||||
#endif
|
||||
WORD wDayOfWeek;
|
||||
} SYSTEMTIME64, *PSYSTEMTIME64, *LPSYSTEMTIME64;
|
||||
|
||||
typedef struct _SYSTEM_TIMEZONE_INFORMATION
|
||||
{
|
||||
LONG Bias;
|
||||
ARRAY_CONTAINER<char16_t, 32> StandardName;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME64 StandardDate;
|
||||
LONG StandardBias;
|
||||
ARRAY_CONTAINER<char16_t, 32> DaylightName;
|
||||
SYSTEMTIME DaylightDate;
|
||||
SYSTEMTIME64 DaylightDate;
|
||||
LONG DaylightBias;
|
||||
} SYSTEM_TIMEZONE_INFORMATION, *PSYSTEM_TIMEZONE_INFORMATION;
|
||||
|
||||
@@ -892,10 +890,10 @@ typedef struct _SYSTEM_DYNAMIC_TIMEZONE_INFORMATION
|
||||
{
|
||||
LONG Bias;
|
||||
ARRAY_CONTAINER<char16_t, 32> StandardName;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME64 StandardDate;
|
||||
LONG StandardBias;
|
||||
ARRAY_CONTAINER<char16_t, 32> DaylightName;
|
||||
SYSTEMTIME DaylightDate;
|
||||
SYSTEMTIME64 DaylightDate;
|
||||
LONG DaylightBias;
|
||||
ARRAY_CONTAINER<char16_t, 128> TimeZoneKeyName;
|
||||
BOOLEAN DynamicDaylightTimeDisabled;
|
||||
|
||||
@@ -8,26 +8,28 @@
|
||||
|
||||
namespace utils
|
||||
{
|
||||
struct string_hash
|
||||
template <typename Elem, typename Traits>
|
||||
struct basic_string_hash
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
size_t operator()(const std::string_view str) const
|
||||
size_t operator()(const std::basic_string_view<Elem, Traits> str) const
|
||||
{
|
||||
constexpr std::hash<std::string_view> hasher{};
|
||||
constexpr std::hash<std::basic_string_view<Elem, Traits>> hasher{};
|
||||
return hasher(str);
|
||||
}
|
||||
};
|
||||
|
||||
struct insensitive_string_hash
|
||||
template <typename Elem, typename Traits>
|
||||
struct basic_insensitive_string_hash
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
size_t operator()(const std::string_view str) const
|
||||
size_t operator()(const std::basic_string_view<Elem, Traits> str) const
|
||||
{
|
||||
size_t hash = 0;
|
||||
constexpr std::hash<int> hasher{};
|
||||
for (const char c : str)
|
||||
for (const auto c : str)
|
||||
{
|
||||
hash ^= hasher(string::char_to_lower(c)) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
|
||||
}
|
||||
@@ -35,22 +37,39 @@ namespace utils
|
||||
}
|
||||
};
|
||||
|
||||
struct insensitive_string_equal
|
||||
template <typename Elem, typename Traits>
|
||||
struct basic_insensitive_string_equal
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()(const std::string_view lhs, const std::string_view rhs) const
|
||||
bool operator()(const std::basic_string_view<Elem, Traits> lhs,
|
||||
const std::basic_string_view<Elem, Traits> rhs) const
|
||||
{
|
||||
return string::equals_ignore_case(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
using string_hash = basic_string_hash<char, std::char_traits<char>>;
|
||||
using u16string_hash = basic_string_hash<char16_t, std::char_traits<char16_t>>;
|
||||
|
||||
using insensitive_string_hash = basic_insensitive_string_hash<char, std::char_traits<char>>;
|
||||
using insensitive_u16string_hash = basic_insensitive_string_hash<char16_t, std::char_traits<char16_t>>;
|
||||
|
||||
using insensitive_string_equal = basic_insensitive_string_equal<char, std::char_traits<char>>;
|
||||
using insensitive_u16string_equal = basic_insensitive_string_equal<char16_t, std::char_traits<char16_t>>;
|
||||
|
||||
template <typename T>
|
||||
using unordered_string_map = std::unordered_map<std::string, T, string_hash, std::equal_to<>>;
|
||||
template <typename T>
|
||||
using unordered_u16string_map = std::unordered_map<std::u16string, T, u16string_hash, std::equal_to<>>;
|
||||
|
||||
template <typename T>
|
||||
using unordered_insensitive_string_map =
|
||||
std::unordered_map<std::string, T, insensitive_string_hash, insensitive_string_equal>;
|
||||
template <typename T>
|
||||
using unordered_insensitive_u16string_map =
|
||||
std::unordered_map<std::u16string, T, insensitive_u16string_hash, insensitive_u16string_equal>;
|
||||
|
||||
using unordered_string_set = std::unordered_set<std::string, string_hash, std::equal_to<>>;
|
||||
using unordered_u16string_set = std::unordered_set<std::u16string, u16string_hash, std::equal_to<>>;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <intrin.h>
|
||||
#include <Windows.h>
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
@@ -458,6 +459,48 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_time_zone()
|
||||
{
|
||||
DYNAMIC_TIME_ZONE_INFORMATION current_dtzi = {};
|
||||
DWORD result = GetDynamicTimeZoneInformation(¤t_dtzi);
|
||||
|
||||
if (result == TIME_ZONE_ID_INVALID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current_dtzi.Bias != -60 || current_dtzi.StandardBias != 0 || current_dtzi.DaylightBias != -60 ||
|
||||
current_dtzi.DynamicDaylightTimeDisabled != FALSE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wcscmp(current_dtzi.StandardName, L"W. Europe Standard Time") != 0 ||
|
||||
wcscmp(current_dtzi.DaylightName, L"W. Europe Daylight Time") != 0 ||
|
||||
wcscmp(current_dtzi.TimeZoneKeyName, L"W. Europe Standard Time") != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current_dtzi.StandardDate.wYear != 0 || current_dtzi.StandardDate.wMonth != 10 ||
|
||||
current_dtzi.StandardDate.wDayOfWeek != 0 || current_dtzi.StandardDate.wDay != 5 ||
|
||||
current_dtzi.StandardDate.wHour != 3 || current_dtzi.StandardDate.wMinute != 0 ||
|
||||
current_dtzi.StandardDate.wSecond != 0 || current_dtzi.StandardDate.wMilliseconds != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current_dtzi.DaylightDate.wYear != 0 || current_dtzi.DaylightDate.wMonth != 3 ||
|
||||
current_dtzi.DaylightDate.wDayOfWeek != 0 || current_dtzi.DaylightDate.wDay != 5 ||
|
||||
current_dtzi.DaylightDate.wHour != 2 || current_dtzi.DaylightDate.wMinute != 0 ||
|
||||
current_dtzi.DaylightDate.wSecond != 0 || current_dtzi.DaylightDate.wMilliseconds != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void throw_exception()
|
||||
{
|
||||
if (do_the_task)
|
||||
@@ -599,6 +642,36 @@ namespace
|
||||
return test_access_violation_exception() && test_illegal_instruction_exception();
|
||||
}
|
||||
|
||||
bool trap_flag_cleared = false;
|
||||
constexpr DWORD TRAP_FLAG_MASK = 0x100;
|
||||
|
||||
LONG NTAPI single_step_handler(PEXCEPTION_POINTERS exception_info)
|
||||
{
|
||||
if (exception_info->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
|
||||
{
|
||||
PCONTEXT context = exception_info->ContextRecord;
|
||||
trap_flag_cleared = (context->EFlags & TRAP_FLAG_MASK) == 0;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
bool test_interrupts()
|
||||
{
|
||||
PVOID veh_handle = AddVectoredExceptionHandler(1, single_step_handler);
|
||||
if (!veh_handle)
|
||||
return false;
|
||||
|
||||
__writeeflags(__readeflags() | TRAP_FLAG_MASK);
|
||||
|
||||
__nop();
|
||||
|
||||
RemoveVectoredExceptionHandler(veh_handle);
|
||||
|
||||
return trap_flag_cleared;
|
||||
}
|
||||
|
||||
void print_time()
|
||||
{
|
||||
const auto epoch_time = std::chrono::system_clock::now().time_since_epoch();
|
||||
@@ -651,10 +724,15 @@ int main(const int argc, const char* argv[])
|
||||
RUN_TEST(test_working_directory, "Working Directory")
|
||||
RUN_TEST(test_registry, "Registry")
|
||||
RUN_TEST(test_system_info, "System Info")
|
||||
RUN_TEST(test_time_zone, "Time Zone")
|
||||
RUN_TEST(test_threads, "Threads")
|
||||
RUN_TEST(test_env, "Environment")
|
||||
RUN_TEST(test_exceptions, "Exceptions")
|
||||
RUN_TEST(test_native_exceptions, "Native Exceptions")
|
||||
if (!getenv("EMULATOR_ICICLE"))
|
||||
{
|
||||
RUN_TEST(test_interrupts, "Interrupts")
|
||||
}
|
||||
RUN_TEST(test_tls, "TLS")
|
||||
RUN_TEST(test_socket, "Socket")
|
||||
RUN_TEST(test_apc, "APC")
|
||||
|
||||
@@ -25,11 +25,121 @@ namespace
|
||||
emu.write_memory<uint64_t>(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF);
|
||||
emu.reg<uint16_t>(x86_register::ss, 0x2B);
|
||||
}
|
||||
|
||||
std::u16string expand_environment_string(const std::u16string& input,
|
||||
const utils::unordered_insensitive_u16string_map<std::u16string>& env_map)
|
||||
{
|
||||
std::u16string result;
|
||||
result.reserve(input.length());
|
||||
size_t pos = 0;
|
||||
|
||||
while (pos < input.length())
|
||||
{
|
||||
size_t start = input.find(u'%', pos);
|
||||
if (start == std::u16string::npos)
|
||||
{
|
||||
result.append(input.substr(pos));
|
||||
break;
|
||||
}
|
||||
|
||||
result.append(input.substr(pos, start - pos));
|
||||
|
||||
size_t end = input.find(u'%', start + 1);
|
||||
if (end == std::u16string::npos)
|
||||
{
|
||||
result.append(input.substr(start));
|
||||
break;
|
||||
}
|
||||
|
||||
std::u16string var_name = input.substr(start + 1, end - start - 1);
|
||||
|
||||
if (var_name.empty())
|
||||
{
|
||||
result.append(u"%%");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = env_map.find(var_name);
|
||||
result.append(it != env_map.end() ? it->second : input.substr(start, end - start + 1));
|
||||
}
|
||||
|
||||
pos = end + 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
utils::unordered_insensitive_u16string_map<std::u16string> get_environment_variables(registry_manager& registry)
|
||||
{
|
||||
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)"});
|
||||
if (env_key)
|
||||
{
|
||||
for (size_t i = 0; const auto value_opt = registry.get_value(*env_key, i); i++)
|
||||
{
|
||||
const auto& value = *value_opt;
|
||||
|
||||
if (value.type != REG_SZ && value.type != REG_EXPAND_SZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.data.empty() || value.data.size() % 2 != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto char_count = value.data.size() / sizeof(char16_t);
|
||||
const auto* data_ptr = reinterpret_cast<const char16_t*>(value.data.data());
|
||||
if (data_ptr[char_count - 1] != u'\0')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env_map[u"EMULATOR"] = u"1";
|
||||
|
||||
const auto* env = getenv("EMULATOR_ICICLE");
|
||||
if (env && (env == "1"sv || env == "true"sv))
|
||||
{
|
||||
env_map[u"EMULATOR_ICICLE"] = u"1";
|
||||
}
|
||||
|
||||
env_map[u"COMPUTERNAME"] = u"momo";
|
||||
env_map[u"USERNAME"] = u"momo";
|
||||
env_map[u"SystemDrive"] = u"C:";
|
||||
env_map[u"SystemRoot"] = u"C:\\WINDOWS";
|
||||
|
||||
for (const auto& key : keys_to_expand)
|
||||
{
|
||||
auto it = env_map.find(key);
|
||||
if (it != env_map.end())
|
||||
{
|
||||
std::u16string expanded = expand_environment_string(it->second, env_map);
|
||||
if (expanded != it->second)
|
||||
{
|
||||
it->second = expanded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return env_map;
|
||||
}
|
||||
}
|
||||
|
||||
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
|
||||
const mapped_module& executable, const mapped_module& ntdll,
|
||||
const apiset::container& apiset_container)
|
||||
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)
|
||||
{
|
||||
setup_gdt(emu, memory);
|
||||
|
||||
@@ -66,9 +176,17 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, const
|
||||
proc_params.StandardError = proc_params.StandardOutput;
|
||||
|
||||
proc_params.Environment = allocator.copy_string(u"=::=::\\");
|
||||
allocator.copy_string(u"EMULATOR=1");
|
||||
allocator.copy_string(u"COMPUTERNAME=momo");
|
||||
allocator.copy_string(u"SystemRoot=C:\\WINDOWS");
|
||||
|
||||
const auto env_map = get_environment_variables(registry);
|
||||
for (const auto& [name, value] : env_map)
|
||||
{
|
||||
std::u16string entry;
|
||||
entry += name;
|
||||
entry += u"=";
|
||||
entry += value;
|
||||
allocator.copy_string(entry);
|
||||
}
|
||||
|
||||
allocator.copy_string(u"");
|
||||
|
||||
const auto application_str = app_settings.application.u16string();
|
||||
|
||||
@@ -59,8 +59,9 @@ struct process_context
|
||||
{
|
||||
}
|
||||
|
||||
void setup(x86_64_emulator& emu, memory_manager& memory, 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);
|
||||
|
||||
@@ -5,6 +5,25 @@
|
||||
#include "serialization_helper.hpp"
|
||||
#include "../handles.hpp"
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
#define REG_NONE (0ul) // No value type
|
||||
#define REG_SZ (1ul) // Unicode nul terminated string
|
||||
#define REG_EXPAND_SZ \
|
||||
(2ul) // Unicode nul terminated string
|
||||
// (with environment variable references)
|
||||
#define REG_BINARY (3ul) // Free form binary
|
||||
#define REG_DWORD (4ul) // 32-bit number
|
||||
#define REG_DWORD_LITTLE_ENDIAN (4ul) // 32-bit number (same as REG_DWORD)
|
||||
#define REG_DWORD_BIG_ENDIAN (5ul) // 32-bit number
|
||||
#define REG_LINK (6ul) // Symbolic Link (unicode)
|
||||
#define REG_MULTI_SZ (7ul) // Multiple Unicode strings
|
||||
#define REG_RESOURCE_LIST (8ul) // Resource list in the resource map
|
||||
#define REG_FULL_RESOURCE_DESCRIPTOR (9ul) // Resource list in the hardware description
|
||||
#define REG_RESOURCE_REQUIREMENTS_LIST (10ul)
|
||||
#define REG_QWORD (11ul) // 64-bit number
|
||||
#define REG_QWORD_LITTLE_ENDIAN (11ul) // 64-bit number (same as REG_QWORD)
|
||||
#endif
|
||||
|
||||
struct registry_key : ref_counted_object
|
||||
{
|
||||
utils::path_key hive{};
|
||||
|
||||
@@ -215,6 +215,7 @@ namespace syscalls
|
||||
emulator_object<uint32_t> return_length);
|
||||
NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, handle process_handle, uint32_t info_class,
|
||||
uint64_t process_information, uint32_t process_information_length);
|
||||
NTSTATUS handle_NtOpenProcess();
|
||||
NTSTATUS handle_NtOpenProcessToken(const syscall_context&, handle process_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<handle> token_handle);
|
||||
NTSTATUS handle_NtOpenProcessTokenEx(const syscall_context& c, handle process_handle, ACCESS_MASK desired_access,
|
||||
@@ -769,6 +770,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtCreateFile);
|
||||
add_handler(NtDeviceIoControlFile);
|
||||
add_handler(NtQueryWnfStateData);
|
||||
add_handler(NtOpenProcess);
|
||||
add_handler(NtOpenProcessToken);
|
||||
add_handler(NtOpenProcessTokenEx);
|
||||
add_handler(NtQuerySecurityAttributesToken);
|
||||
|
||||
@@ -140,9 +140,20 @@ namespace syscalls
|
||||
{
|
||||
if (!f->enumeration_state || query_flags & SL_RESTART_SCAN)
|
||||
{
|
||||
const auto mask = file_mask ? read_unicode_string(c.emu, file_mask) : u"";
|
||||
|
||||
if (!mask.empty())
|
||||
{
|
||||
c.win_emu.log.print(color::dark_gray, "--> Enumerating directory: %s (Mask: \"%s\")\n",
|
||||
u16_to_u8(f->name).c_str(), u16_to_u8(mask).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
c.win_emu.log.print(color::dark_gray, "--> Enumerating directory: %s\n", u16_to_u8(f->name).c_str());
|
||||
}
|
||||
|
||||
f->enumeration_state.emplace(file_enumeration_state{});
|
||||
f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name),
|
||||
file_mask ? read_unicode_string(c.emu, file_mask) : u"");
|
||||
f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name), mask);
|
||||
}
|
||||
|
||||
auto& enum_state = *f->enumeration_state;
|
||||
@@ -154,6 +165,10 @@ namespace syscalls
|
||||
|
||||
if (current_index >= enum_state.files.size())
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = 0;
|
||||
io_status_block.write(block);
|
||||
|
||||
return STATUS_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
@@ -191,11 +206,7 @@ namespace syscalls
|
||||
T info{};
|
||||
info.NextEntryOffset = 0;
|
||||
info.FileIndex = static_cast<ULONG>(current_index);
|
||||
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
if (current_file.is_directory)
|
||||
{
|
||||
info.FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
info.FileAttributes = current_file.is_directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
|
||||
info.FileNameLength = static_cast<ULONG>(file_name.size() * 2);
|
||||
info.EndOfFile.QuadPart = current_file.file_size;
|
||||
|
||||
@@ -722,9 +733,21 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto filename = read_unicode_string(
|
||||
auto filename = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
|
||||
if (attributes.RootDirectory)
|
||||
{
|
||||
const auto* root = c.proc.files.get(attributes.RootDirectory);
|
||||
if (!root)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
const auto has_separator = root->name.ends_with(u"\\") || root->name.ends_with(u"/");
|
||||
filename = root->name + (has_separator ? u"" : u"\\") + filename;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
@@ -348,6 +348,11 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenProcess()
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -171,6 +171,9 @@ namespace syscalls
|
||||
|
||||
c.emu.write_memory(obj_address + 0x9C8, 0xFFFFFFFF); // TIME_ZONE_ID_INVALID
|
||||
|
||||
// Windows 2019 offset!
|
||||
c.emu.write_memory(obj_address + 0xA70, 0xFFFFFFFF); // TIME_ZONE_ID_INVALID
|
||||
|
||||
if (view_size)
|
||||
{
|
||||
view_size.write(shared_section_size);
|
||||
|
||||
@@ -345,7 +345,7 @@ void windows_emulator::setup_process(const application_settings& app_settings)
|
||||
|
||||
const auto apiset_data = apiset::obtain(this->emulation_root);
|
||||
|
||||
this->process.setup(this->emu(), this->memory, app_settings, *executable, *ntdll, apiset_data);
|
||||
this->process.setup(this->emu(), this->memory, this->registry, app_settings, *executable, *ntdll, apiset_data);
|
||||
|
||||
const auto ntdll_data = emu.read_memory(ntdll->image_base, static_cast<size_t>(ntdll->size_of_image));
|
||||
const auto win32u_data = emu.read_memory(win32u->image_base, static_cast<size_t>(win32u->size_of_image));
|
||||
@@ -515,6 +515,7 @@ void windows_emulator::setup_hooks()
|
||||
|
||||
this->emu().hook_interrupt([&](const int interrupt) {
|
||||
const auto rip = this->emu().read_instruction_pointer();
|
||||
const auto eflags = this->emu().reg<uint32_t>(x86_register::eflags);
|
||||
|
||||
switch (interrupt)
|
||||
{
|
||||
@@ -522,7 +523,15 @@ void windows_emulator::setup_hooks()
|
||||
dispatch_integer_division_by_zero(this->emu(), this->process);
|
||||
return;
|
||||
case 1:
|
||||
this->log.print(color::pink, "Singlestep: 0x%" PRIx64 "\n", rip);
|
||||
if ((eflags & 0x100) != 0)
|
||||
{
|
||||
this->log.print(color::pink, "Singlestep (Trap Flag): 0x%" PRIx64 "\n", rip);
|
||||
this->emu().reg(x86_register::eflags, eflags & ~0x100);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->log.print(color::pink, "Singlestep: 0x%" PRIx64 "\n", rip);
|
||||
}
|
||||
dispatch_single_step(this->emu(), this->process);
|
||||
return;
|
||||
case 3:
|
||||
@@ -532,6 +541,10 @@ void windows_emulator::setup_hooks()
|
||||
case 6:
|
||||
dispatch_illegal_instruction_violation(this->emu(), this->process);
|
||||
return;
|
||||
case 45:
|
||||
this->log.print(color::pink, "DbgPrint: 0x%" PRIx64 "\n", rip);
|
||||
dispatch_breakpoint(this->emu(), this->process);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user