Compare commits

...

7 Commits

Author SHA1 Message Date
Maurice Heumann
0de53515ed Fix waiting (#675)
This PR fixes `INFINITE` waiting (`SleepEx`, `WaitForSingleObject`,
etc). Currently `INFINITE` is not infinite but "at this moment" (waiting
point in time == `clock.steady_now()`).
2026-01-02 22:14:02 +01:00
Maurice Heumann
818a4a4b88 Support SystemEmulationProcessorInformation (#672)
This PR implements `SystemEmulationProcessorInformation`. It is used,
for example, in 32-bit `ole32.dll`.
2026-01-02 22:10:52 +01:00
Maurice Heumann
f6f87bf23d Refactor emulator_object (#673)
This PR refactors `emulator_object` to make future support easier.
2026-01-02 22:09:54 +01:00
ssvine
7724b0d416 Refactor emulator_object 2026-01-02 19:03:54 +03:00
ssvine
9bdb5c9562 Fix INFINITE time waiting 2026-01-02 18:33:27 +03:00
ssvine
b9df0682ad Support SystemEmulationProcessorInformation 2026-01-02 18:28:38 +03:00
ssvine
254475e308 Don't read null ptr in NtDelayExecution 2026-01-02 17:36:05 +03:00
9 changed files with 32 additions and 27 deletions

View File

@@ -94,6 +94,7 @@
#define IMAGE_FILE_MACHINE_CEE 0xC0EE
#endif
#define PROCESSOR_ARCHITECTURE_INTEL 0
#define PROCESSOR_ARCHITECTURE_AMD64 9
enum class PEMachineType : std::uint16_t

View File

@@ -3,8 +3,14 @@
namespace utils
{
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(clock& c, const LARGE_INTEGER delay_interval)
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(clock& c, const LARGE_INTEGER delay_interval,
const LARGE_INTEGER infinite_value)
{
if (delay_interval.QuadPart == infinite_value.QuadPart)
{
return std::chrono::steady_clock::time_point::min();
}
if (delay_interval.QuadPart <= 0)
{
const auto relative_time = -delay_interval.QuadPart;

View File

@@ -102,7 +102,9 @@ namespace utils
}
};
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(clock& c, LARGE_INTEGER delay_interval);
std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(clock& c, LARGE_INTEGER delay_interval,
LARGE_INTEGER infinite_value = {.LowPart = 0,
.HighPart = -2147483648});
KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp);
void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp);

View File

@@ -1006,7 +1006,8 @@ namespace
std::optional<std::chrono::steady_clock::time_point> timeout{};
if (info.Timeout.QuadPart != std::numeric_limits<int64_t>::max())
{
timeout = utils::convert_delay_interval_to_time_point(win_emu.clock(), info.Timeout);
timeout = utils::convert_delay_interval_to_time_point(win_emu.clock(), info.Timeout,
{.QuadPart = std::numeric_limits<int64_t>::max()});
}
this->delay_ioctrl(c, {}, timeout, timeout_callback);

View File

@@ -109,7 +109,8 @@ class emulator_thread : public ref_counted_object
bool is_await_time_over(utils::clock& clock) const
{
return this->await_time.has_value() && this->await_time.value() < clock.steady_now();
constexpr auto infinite = std::chrono::steady_clock::time_point::min();
return this->await_time.has_value() && this->await_time.value() != infinite && this->await_time.value() < clock.steady_now();
}
bool is_terminated() const;

View File

@@ -66,8 +66,6 @@ class emulator_object
public:
using value_type = T;
emulator_object() = default;
emulator_object(const x64_emulator_wrapper& wrapper, const uint64_t address = 0)
: emulator_object(wrapper.get(), address)
{
@@ -84,6 +82,11 @@ class emulator_object
{
}
emulator_object(utils::buffer_deserializer& buffer)
: emulator_object(buffer.read<memory_manager_wrapper>().get())
{
}
uint64_t value() const
{
return this->address_;
@@ -175,11 +178,6 @@ class emulator_object
this->address_ = address;
}
void set_memory_interface(memory_interface& memory)
{
this->memory_ = &memory;
}
emulator_object<T> shift(const int64_t offset) const
{
return emulator_object<T>(*this->memory_, this->address_ + offset);

View File

@@ -453,15 +453,6 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
buffer.read_optional(this->process_params32);
buffer.read(this->kusd);
if (this->peb32.has_value())
{
this->peb32->set_memory_interface(*this->peb64.get_memory_interface());
}
if (this->process_params32.has_value())
{
this->process_params32->set_memory_interface(*this->peb64.get_memory_interface());
}
buffer.read(this->is_wow64_process);
buffer.read(this->ntdll_image_base);
buffer.read(this->ldr_initialize_thunk);

View File

@@ -199,12 +199,14 @@ namespace syscalls
});
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;
});
case SystemEmulationProcessorInformation:
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 =
(info_class == SystemProcessorInformation ? PROCESSOR_ARCHITECTURE_AMD64 : PROCESSOR_ARCHITECTURE_INTEL);
});
case SystemNumaProcessorMap:
return handle_query<SYSTEM_NUMA_INFORMATION64>(c.emu, system_information, system_information_length, return_length,

View File

@@ -403,7 +403,10 @@ namespace syscalls
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());
if (delay_interval.value())
{
t.await_time = utils::convert_delay_interval_to_time_point(c.win_emu.clock(), delay_interval.read());
}
c.win_emu.yield_thread(alertable);
return STATUS_SUCCESS;