You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am trying to track object creation, destruction and duplication on a live Windows 10 machine. According to the MOF definitions on MSDN, these events correspond to opcodes 32, 33 and 34 respectively:
According to the examples, object_manager_provider is the struct to go for when tracking these events. And indeed, I can receive and parse events with opcode 32 and 33. However, events with opcode 34 seem to never be reported by the callback. Am I missing something, should I enable some extra flags/options, or could this be a bug?
To Reproduce
I use the following source code, which is heavily inspired by the provided examples:
krabstest.cpp
#include<krabs.hpp>
#include<iostream>// Mapping for process IDs to their image names.
std::map<uint32_t, std::string> process_names;
// Set of image names that we want to print out to the console.
std::set<std::string> included_processes;
/** * Prints "[<pid> <image name>]: "*/voidprint_header(const EVENT_RECORD& record)
{
auto entry = process_names.find(record.EventHeader.ProcessId);
auto process_name = entry != process_names.end() ? entry->second : "<unknown>";
std::cout << "[" << std::dec << record.EventHeader.ProcessId << "" << process_name << "]: ";
}
intmain()
{
// Set up some processes to print output for.
included_processes.insert("notepad.exe");
included_processes.insert("TesterApp.exe");
krabs::kernel_trace trace(L"My Trace");
// In order to filter events by process name, we need to track all process start/stop events to translate IDs to names.
krabs::kernel::process_provider process_provider;
process_provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& context) {
// For maintaining the process_names mapping, we only care about start, end and DC start events.if (record.EventHeader.EventDescriptor.Opcode > 3)
return;
// Obtain schema.
krabs::schema schema(record, context.schema_locator);
krabs::parser parser(schema);
// Parse out proc id and file name.auto processId = parser.parse<uint32_t>(L"ProcessId");
auto imageName = parser.parse<std::string>(L"ImageFileName");
// Update process_names mapping accordingly.switch (record.EventHeader.EventDescriptor.Opcode) {
case1: // Process startcase3: // Process DC Start
process_names[processId] = imageName;
break;
case2: // Process end
process_names.erase(processId);
break;
}
});
trace.enable(process_provider);
// Set up the object ETW source.
krabs::kernel::object_manager_provider ob_provider;
ob_provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& context)
{
// Should we print information for this process?auto processName = process_names.find(record.EventHeader.ProcessId);
if (processName == process_names.end() || included_processes.find(processName->second) == included_processes.end()) {
return;
}
// Obtain event data schema.
krabs::schema schema(record, context.schema_locator);
krabs::parser parser(schema);
switch (record.EventHeader.EventDescriptor.Opcode) {
case32: // CreateHandleprint_header(record);
std::cout << "CreateHandle"
<< "(Handle: " << std::hex << parser.parse<uint32_t>(L"Handle")
<< ")" << std::endl;
break;
case33: // CloseHandleprint_header(record);
std::cout << "CloseHandle"
<< "(Handle: " << std::hex << parser.parse<uint32_t>(L"Handle")
<< ")" << std::endl;
break;
case34: // DuplicateHandleprint_header(record);
std::cout << "DuplicateHandle"
<< "(SourceHandle: " << std::hex << parser.parse<uint32_t>(L"SourceHandle")
<< ", TargetHandle: " << std::hex << parser.parse<uint32_t>(L"TargetHandle")
<< ", TargetProcessId: " << std::hex << parser.parse<uint32_t>(L"TargetProcessId")
<< ")" << std::endl;
break;
default:
std::wcout << L"Unhandled object event " << schema.opcode_name() << std::endl;
break;
}
});
trace.enable(ob_provider);
std::cout << "Starting trace...\n";
trace.start();
}
As a test application, I have a basic program that creates a new file object, duplicates it 10 times, then closes all duplicated handles, and finally closes the main handle.
testerapp.cpp
#include<Windows.h>
#include<iostream>intmain()
{
std::cin.get(); // activate the krabs log before pressing enter to clearly see which handles are belonging to the following code.auto handle = CreateFile(L"file.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
std::cout << "Opened file (" << std::hex << handle << ")" << std::endl;
constsize_t duplicate_count = 10;
auto duplicates = new HANDLE[duplicate_count];
for (size_t i = 0; i < duplicate_count; i++) {
!DuplicateHandle(
GetCurrentProcess(),
handle,
GetCurrentProcess(),
&duplicates[i],
0,
TRUE,
DUPLICATE_SAME_ACCESS
);
std::cout << "Duplicated file (" << std::hex << duplicates[i] << ")" << std::endl;
}
for (size_t i = 0; i < duplicate_count; i++) {
CloseHandle(duplicates[i]);
std::cout << "Closed duplicated file (" << std::hex << duplicates[i] << ")" << std::endl;
}
CloseHandle(handle);
std::cout << "Closed main handle file (" << std::hex << handle << ")" << std::endl;
std::cin.get();
}
When running this with admin rights on a Windows 10 Pro N x64 machine, version 22H2, build 19045.3086, I only get the following output:
Notice how a single file object creation (12c) is directly followed up by 11 handle closure events, without any report of the file handle being duplicated.
Additional Context
It is maybe worth mentioning that other libraries that consume ETW events do seem to be able to report on object duplication. For example, using Microsoft.Diagnostics.Tracing.TraceEvent of the perfview project, reporting on handle duplication works fine:
The text was updated successfully, but these errors were encountered:
Update: If it may be of any help, when I inspect errors using add_on_error_callback, I get the following message for every duplicate handle event (34):
Could not find the schema: status_code=1168 provider_id=89497f50-effe-4440-8cf2-ce6b1cdcaca7 event_id=0
I suppose 1168 refers to ERROR_NOT_FOUND. It seems krabs cannot obtain the schema for this type of event.
jstarink
changed the title
The object_manager_provider does not receive DuplicateHandle events in the callback
The object_manager_provider does not support DuplicateHandle events
Jun 30, 2023
Summary
I am trying to track object creation, destruction and duplication on a live Windows 10 machine. According to the MOF definitions on MSDN, these events correspond to opcodes 32, 33 and 34 respectively:
According to the examples,
object_manager_provider
is the struct to go for when tracking these events. And indeed, I can receive and parse events with opcode 32 and 33. However, events with opcode 34 seem to never be reported by the callback. Am I missing something, should I enable some extra flags/options, or could this be a bug?To Reproduce
I use the following source code, which is heavily inspired by the provided examples:
krabstest.cpp
As a test application, I have a basic program that creates a new file object, duplicates it 10 times, then closes all duplicated handles, and finally closes the main handle.
testerapp.cpp
When running this with admin rights on a Windows 10 Pro N x64 machine, version 22H2, build 19045.3086, I only get the following output:
Notice how a single file object creation (
12c
) is directly followed up by 11 handle closure events, without any report of the file handle being duplicated.Additional Context
It is maybe worth mentioning that other libraries that consume ETW events do seem to be able to report on object duplication. For example, using
Microsoft.Diagnostics.Tracing.TraceEvent
of the perfview project, reporting on handle duplication works fine:The text was updated successfully, but these errors were encountered: