Support ProcessInstrumentationCallback

This commit is contained in:
66hh
2025-12-27 13:51:10 +08:00
parent d3cb3f4995
commit ecc00216d6
5 changed files with 40 additions and 0 deletions

View File

@@ -1124,4 +1124,10 @@ struct PROCESS_PRIORITY_CLASS
UCHAR PriorityClass;
};
struct PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
ULONG Version;
ULONG Reserved;
PVOID Callback;
};
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)

View File

@@ -388,6 +388,7 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
this->rtl_user_thread_start = ntdll.find_export("RtlUserThreadStart");
this->ki_user_apc_dispatcher = ntdll.find_export("KiUserApcDispatcher");
this->ki_user_exception_dispatcher = ntdll.find_export("KiUserExceptionDispatcher");
this->instrumentation_callback = 0;
this->default_register_set = emu.save_registers();
}
@@ -413,6 +414,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
buffer.write_optional(this->rtl_user_thread_start32);
buffer.write(this->ki_user_apc_dispatcher);
buffer.write(this->ki_user_exception_dispatcher);
buffer.write(this->instrumentation_callback);
buffer.write(this->events);
buffer.write(this->files);
@@ -467,6 +469,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
buffer.read_optional(this->rtl_user_thread_start32);
buffer.read(this->ki_user_apc_dispatcher);
buffer.read(this->ki_user_exception_dispatcher);
buffer.read(this->instrumentation_callback);
buffer.read(this->events);
buffer.read(this->files);

View File

@@ -110,6 +110,7 @@ struct process_context
uint64_t rtl_user_thread_start{};
uint64_t ki_user_apc_dispatcher{};
uint64_t ki_user_exception_dispatcher{};
uint64_t instrumentation_callback{};
// For WOW64 processes
std::optional<emulator_object<PEB32>> peb32;

View File

@@ -101,6 +101,19 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
}
entry->second.handler(c);
if (context.instrumentation_callback != 0 && entry->second.name != "NtContinue")
{
uint64_t rip_old = emu.reg<uint64_t>(x86_register::rip);
// The increase in RIP caused by executing the syscall here has not yet occurred.
// If RIP is set directly, it will lead to an incorrect address, so the length of
// the syscall instruction needs to be subtracted.
emu.reg<uint64_t>(x86_register::rip, context.instrumentation_callback - 2);
emu.reg<uint64_t>(x86_register::r10, rip_old);
}
}
catch (std::exception& e)
{

View File

@@ -281,6 +281,23 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (info_class == ProcessInstrumentationCallback)
{
if (process_information_length != sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION))
{
return STATUS_BUFFER_OVERFLOW;
}
PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION info;
c.emu.read_memory(process_information, &info, sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION));
c.proc.instrumentation_callback = (uint64_t)info.Callback;
return STATUS_SUCCESS;
}
c.win_emu.log.error("Unsupported info process class: %X\n", info_class);
c.emu.stop();