Prepare timer support

This commit is contained in:
momo5502
2025-06-01 13:30:10 +02:00
parent c605131a80
commit da658e5178
12 changed files with 110 additions and 21 deletions

View File

@@ -52,3 +52,22 @@ inline memory_permission& operator^=(memory_permission& x, const memory_permissi
x = x ^ y;
return x;
}
/*****************************************************************************
*
****************************************************************************/
inline bool is_executable(const memory_permission permission)
{
return (permission & memory_permission::exec) != memory_permission::none;
}
inline bool is_readable(const memory_permission permission)
{
return (permission & memory_permission::read) != memory_permission::none;
}
inline bool is_writable(const memory_permission permission)
{
return (permission & memory_permission::write) != memory_permission::none;
}

View File

@@ -20,6 +20,7 @@ struct handle_types
mutant,
token,
window,
timer,
};
};

View File

@@ -272,6 +272,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
buffer.write(this->ports);
buffer.write(this->mutants);
buffer.write(this->windows);
buffer.write(this->timers);
buffer.write(this->registry_keys);
buffer.write_map(this->atoms);
@@ -311,6 +312,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
buffer.read(this->ports);
buffer.read(this->mutants);
buffer.read(this->windows);
buffer.read(this->timers);
buffer.read(this->registry_keys);
buffer.read_map(this->atoms);

View File

@@ -115,6 +115,7 @@ struct process_context
handle_store<handle_types::port, port> ports{};
handle_store<handle_types::mutant, mutant> mutants{};
handle_store<handle_types::window, window> windows{};
handle_store<handle_types::timer, timer> timers{};
handle_store<handle_types::registry, registry_key, 2> registry_keys{};
std::map<uint16_t, atom_entry> atoms{};

View File

@@ -358,14 +358,16 @@ namespace syscalls
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);
// syscalls/token.cpp:
NTSTATUS handle_NtDuplicateToken(const syscall_context&, handle existing_token_handle,
ACCESS_MASK /*desired_access*/,
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
/*object_attributes*/,
BOOLEAN /*effective_only*/, TOKEN_TYPE type,
emulator_object<handle> new_token_handle);
NTSTATUS
handle_NtDuplicateToken(const syscall_context&, handle existing_token_handle, ACCESS_MASK /*desired_access*/,
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);
@@ -758,11 +760,6 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtCreateTimer2()
{
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtUserMapVirtualKeyEx()
{
return 0;

View File

@@ -63,6 +63,7 @@ namespace syscalls
if (attributes.ObjectName)
{
name = read_unicode_string(c.emu, attributes.ObjectName);
c.win_emu.log.print(color::dark_gray, "--> Event name: %s\n", u16_to_u8(name).c_str());
}
}

View File

@@ -210,14 +210,16 @@ namespace syscalls
if (commit && !reserve &&
c.win_emu.memory.commit_memory(potential_base, static_cast<size_t>(allocation_bytes), protection))
{
c.win_emu.log.print(color::dark_gray, "--> Committed 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
c.win_emu.log.print(is_executable(protection) ? color::gray : color::dark_gray,
"--> Committed 0x%" PRIx64 " - 0x%" PRIx64 " (%s)\n", potential_base,
potential_base + allocation_bytes, get_permission_string(protection).c_str());
return STATUS_SUCCESS;
}
c.win_emu.log.print(color::dark_gray, "--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
c.win_emu.log.print(is_executable(protection) ? color::gray : color::dark_gray,
"--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 " (%s)\n", potential_base,
potential_base + allocation_bytes, get_permission_string(protection).c_str());
return c.win_emu.memory.allocate_memory(potential_base, static_cast<size_t>(allocation_bytes), protection,
!commit)

View File

@@ -77,8 +77,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, attributes.ObjectName);
c.win_emu.log.print(color::dark_gray, "--> Mutant name: %s\n", u16_to_u8(name).c_str());
}
}

View File

@@ -30,4 +30,43 @@ 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*/)
{
std::u16string name{};
if (object_attributes)
{
const auto attributes = object_attributes.read();
if (attributes.ObjectName)
{
name = read_unicode_string(c.emu, attributes.ObjectName);
c.win_emu.log.print(color::dark_gray, "--> Timer name: %s\n", u16_to_u8(name).c_str());
}
}
if (!name.empty())
{
for (auto& entry : c.proc.timers)
{
if (entry.second.name == name)
{
++entry.second.ref_count;
timer_handle.write(c.proc.timers.make_handle(entry.first));
return STATUS_OBJECT_NAME_EXISTS;
}
}
}
timer t{};
t.name = std::move(name);
const auto h = c.proc.timers.store(std::move(t));
timer_handle.write(h);
return STATUS_SUCCESS;
}
}

View File

@@ -346,8 +346,10 @@ void windows_emulator::yield_thread(const bool alertable)
this->emu().stop();
}
void windows_emulator::perform_thread_switch()
bool windows_emulator::perform_thread_switch()
{
const auto needed_switch = std::exchange(this->switch_thread_, false);
this->switch_thread_ = false;
while (!switch_to_next_thread(*this))
{
@@ -359,7 +361,15 @@ void windows_emulator::perform_thread_switch()
{
std::this_thread::sleep_for(1ms);
}
if (this->should_stop)
{
this->switch_thread_ = needed_switch;
return false;
}
}
return true;
}
bool windows_emulator::activate_thread(const uint32_t id)
@@ -597,7 +607,10 @@ void windows_emulator::start(size_t count)
{
if (this->switch_thread_ || !this->current_thread().is_thread_ready(this->process, this->clock()))
{
this->perform_thread_switch();
if (!this->perform_thread_switch())
{
break;
}
}
this->emu().start(count);

View File

@@ -182,7 +182,7 @@ class windows_emulator
bool fuzzing{false};
void yield_thread(bool alertable = false);
void perform_thread_switch();
bool perform_thread_switch();
bool activate_thread(uint32_t id);
private:

View File

@@ -6,6 +6,21 @@
#include <utils/file_handle.hpp>
#include <platform/synchronisation.hpp>
struct timer : ref_counted_object
{
std::u16string name{};
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->name);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->name);
}
};
struct event : ref_counted_object
{
bool signaled{};