I find myself in the following predicament: I am attempting to capture events according to a C++ example. However, the issue arises when it gets stuck in the EnableTraceEx function. According to Microsoft documentation, the error it gives, which is error code 87, occurs because the "sessionHandle" or "GUID" is equal to NULL. However, this is not the case. If I do not use EnableTraceEx and instead use EnableTrace, it proceeds to the next function of the program, but ultimately fails in ProcessTrace. Any assistance would be greatly appreciated. Thank you in advance.
Code in c++: https://gist.github.com/aaaddress1/4add6b873ae6ed70cb125a7587d2e1bc
Code in Masm32:
AsigText Macro Name, Text:VarArg
Local lbl
Jmp lbl
Name DB Text, 0
lbl:
EndM
.Const
WNODE_FLAG_TRACED_GUID Equ 20000H ; Constante para indicar que el GUID del proveedor está incluido en el nodo
EVENT_TRACE_REAL_TIME_MODE Equ 100H
EVENT_TRACE_USE_PAGED_MEMORY Equ 4000H
PROCESS_TRACE_MODE_EVENT_RECORD Equ 1000H
.Data?
.Data
_SYSTEMTIME Struct
wYear Word 0
wMonth Word 0
wDayOfWeek Word 0
wDay Word 0
wHour Word 0
wMinute Word 0
wSecond Word 0
wMilliseconds Word 0
_SYSTEMTIME EndS
_TIME_ZONE_INFORMATION Struct
Bias LONG 0
StandardName WCHAR 32 Dup (0)
StandardDate _SYSTEMTIME <>
StandardBias LONG 0
DaylightName WCHAR 32 Dup (0)
DaylightDate _SYSTEMTIME <>
DaylightBias LONG 0
_TIME_ZONE_INFORMATION EndS
TRACE_LOGFILE_HEADER Struct
BufferSize DWord 0
Union
VersionA DWord 0
Struc
MajorVersion Byte 0
MinorVersion Byte 0
SubVersion Byte 0
SubMinorVersion Byte 0
EndS
EndS
ProviderVersion DWord 0
NumberOfProcessors DWord 0
EndTime LARGE_INTEGER <>
TimerResolution DWord 0
MaximumFileSize DWord 0
LogFileMode DWord 0
BuffersWritten DWord 0
Union
LogInstanceGuid GUID <>
Struc
StartBuffers DWord 0
PointerSize DWord 0
EventsLost DWord 0
CpuSpeedInMHz DWord 0
EndS
EndS
LoggerName DWord 0
LogFileName DWord 0
TimeZone _TIME_ZONE_INFORMATION <>
BootTime LARGE_INTEGER <>
PerfFreq LARGE_INTEGER <>
StartTime LARGE_INTEGER <>
ReservedFlags DWORD ?
BuffersLost DWORD ?
TRACE_LOGFILE_HEADER EndS
ETW_BUFFER_CONTEXT Struct
Union
Struct
ProcessorNumber Byte 0
Alignment Byte 0
EndS
ProcessorIndex Word 0
EndS
LoggerId Word ?
ETW_BUFFER_CONTEXT EndS
EVENT_TRACE_HEADER Struct
SizeA Word 0
Union
FieldTypeFlags Word 0
Struct
HeaderType Byte 0
MarkerFlags Byte 0
EndS
EndS
Union
Version DWord 0
Struc
TypeA Byte 0
Level Byte 0
VersionA Byte 0
EndS
EndS
ThreadId DWord 0
ProcessId DWord 0
TimeStamp LARGE_INTEGER <>
Union
Guid GUID <>
GuidPtr QWord 0
EndS
Union
Struct
KernelTime DWord 0
UserTime DWord 0
EndS
ProcessorTime QWord 0
Struct
ClientContext DWord 0
Flags DWord 0
EndS
EndS
EVENT_TRACE_HEADER EndS
EVENT_TRACE Struct
Header EVENT_TRACE_HEADER <>
InstanceId DWord 0
ParentInstanceId DWord 0
ParentGuid GUID <>
MofData DWord 0
MofLength DWord 0
Union
ClientContext DWord 0
BufferContext ETW_BUFFER_CONTEXT <>
EndS
EVENT_TRACE EndS
EventTraceLogfileA Struct
LogFileName DWord 0
LoggerName DWord 0
CurrentTime QWord 0
BuffersRead DWord 0
Union
LogFileMode DWord 0
ProcessTraceMode DWord 0
EndS
CurrentEvent EVENT_TRACE <>
LogfileHeader TRACE_LOGFILE_HEADER <>
BufferCallback DWord 0
BufferSize DWord 0
Filled DWord 0
EventsLost DWord 0
Union
EventCallback DWord 0
EventRecordCallback DWord 0
EndS
IsKernelTrace DWord 0
Context DWord 0
EventTraceLogfileA EndS
WNODE_HEADER Struct
BufferSize DWORD ?
ProviderId DWORD ?
union
HistoricalContext ULONG64 ?
struct
Version DWORD ?
Linkage DWORD ?
ends
ends
union
KernelHandle HANDLE ?
TimeStamp LARGE_INTEGER <>
ends
Guid GUID <>
ClientContext DWORD ?
Flags DWORD ?
WNODE_HEADER EndS
EVENT_TRACE_PROPERTIES Struct
Wnode WNODE_HEADER <>
BufferSize DWord 0
MinimumBuffers DWord 0
MaximumBuffers DWord 0
MaximumFileSize DWord 0
LogFileMode DWord 0
FlushTimer DWord 0
EnableFlags DWord 0
AgeLimit DWord 0
FlushThreshold DWord 0
NumberOfBuffers DWord 0
FreeBuffers DWord 0
EventsLost DWord 0
BuffersWritten DWord 0
LogBuffersLost DWord 0
RealTimeBuffersLost DWord 0
LoggerThreadId HANDLE 0
LogFileNameOffset DWord 0
LoggerNameOffset DWord 0
EVENT_TRACE_PROPERTIES EndS
ENABLE_TRACE_PARAMETERS STRUCT
Version DWord 0
EnableProperty DWord 0
ControlFlags DWord 0
SourceId GUID <>
EnableFilterDesc DWord 0
FilterDescCount DWord 0
ENABLE_TRACE_PARAMETERS EndS
EVENT_FILTER_DESCRIPTOR STRUCT
PtrA QWord 0
SizeA DWord 0
TypeA DWord 0
EVENT_FILTER_DESCRIPTOR EndS
EVENT_DESCRIPTOR Struct
Id Word 0
Version Byte 0
Channel Byte 0
Level Byte 0
Opcode Byte 0
Task Word 0
Keyword QWord 0
EVENT_DESCRIPTOR EndS
EVENT_HEADER Struct
SizeA Word 0
HeaderType Word 0
Flags Word 0
EventProperty Word 0
ThreadId DWord 0
ProcessId DWord 0
TimeStamp LARGE_INTEGER <>
ProviderId GUID <>
EventDescriptor EVENT_DESCRIPTOR <>
Union ; Comienzo de la unión
Struct ; Comienzo de la estructura anidada
KernelTime DWord ?
UserTime DWORD ?
ProcessorTime QWord ? ; Puedes ajustar el tamaño dependiendo del uso
EndS
EndS ; Fin de la unión
ActivityId GUID <>
EVENT_HEADER EndS
EVENT_RECORD Struct
EventHeader EVENT_HEADER <>
BufferContext ETW_BUFFER_CONTEXT <>
ExtendedDataCount Word 0
UserDataLength Word 0
ExtendedData PVOID ?
UserData PVOID ?
UserContext PVOID ?
EVENT_RECORD EndS
HandleConsola DD 0
Trace EventTraceLogfileA <>
TraceProperties EVENT_TRACE_PROPERTIES <>
TraceParam ENABLE_TRACE_PARAMETERS <>
LoggerName DB 'frai18', 0
LogFileName DB 0
sessionHandle HANDLE 0
ProviderHandle HANDLE 0
tempbuffer DB 10 Dup(NULL) ; Buffer temporal para la rutina de paso a numeros decimales.
; Definir la estructura de GUID para el proveedor de eventos
generatedGuid GUID <>
BufferSize DD 0
HandleLibrary DD 0
.Code
start:
Invoke GetStdHandle, STD_OUTPUT_HANDLE
Mov HandleConsola, Eax ; edx ahora contiene el identificador de la consola
; Llama a CoInitialize para inicializar la biblioteca COM
Invoke CoInitialize, NULL
;
; Llama a CoCreateGuid para generar un GUID
Invoke CoCreateGuid, Addr generatedGuid
Test Eax, Eax
Jnz Error_ExitSiete
; Copia el GUID generado a la estructura WNODE_HEADER
; Lea Esi, generatedGuid
; Lea Edi, TraceProperties.Props.Wnode.Guid
; Mov Ecx, SizeOf GUID
; Rep Movsb
;
; Llama a CoUninitialize para finalizar la biblioteca COM
Invoke CoUninitialize
; Convertir el GUID a una cadena hexadecimal
; Cargar la biblioteca dinámica wnetapi32.dll
Invoke LoadLibrary, TextStr("Advapi32.dll")
.If Eax
Mov Edi, Eax
Mov HandleLibrary, Eax
; Registramos un proveedor para registro de eventos.
Invoke GetProcAddress, Edi, TextStr("EventRegister")
Mov Esi, Eax
Lea Eax, ProviderHandle
Push Eax
Push NULL
Push NULL
Lea Eax, generatedGuid
Push Eax
Call Esi
Test Eax, Eax
Jnz error_exitCinco
; Obtener el puntero a la función StartTraceA
; Crear una sesión de ETW
Invoke GetProcAddress, Edi, TextStr("StartTraceA")
Mov Esi, Eax
; Inicializar las propiedades de traza
Mov TraceProperties.Wnode.BufferSize, SizeOf EVENT_TRACE_PROPERTIES + SizeOf LoggerName
Mov TraceProperties.Wnode.ClientContext, 2
Mov TraceProperties.Wnode.Flags, WNODE_FLAG_TRACED_GUID
; Push Esi
; Push Edi
;
; ; Copia el GUID generado a la estructura WNODE_HEADER
; Lea Esi, generatedGuid
; Lea Edi, TraceProperties.Wnode.Guid
; Mov Ecx, SizeOf GUID
; Rep Movsb
;
; Pop Edi
; Pop Esi
Mov TraceProperties.LogFileMode, EVENT_TRACE_REAL_TIME_MODE + EVENT_TRACE_USE_PAGED_MEMORY
Mov TraceProperties.LoggerNameOffset, SizeOf EVENT_TRACE_PROPERTIES
Mov TraceProperties.LogFileNameOffset, 0
Lea Eax, TraceProperties
Push Eax
Lea Eax, LoggerName
Push Eax
Lea Eax, sessionHandle
Push Eax
Call Esi
Test Eax, Eax
Jnz error_exit
Push Esi
Push Edi
Mov Eax, SizeOf generatedGuid ; Obtener el tamaño de ProviderGuid
Cmp Eax, SizeOf GUID ; Comparar con el tamaño esperado de un GUID
Jne guid_invalido ; Si los tamaños no coinciden, salta a guid_invalido
; Comprobamos que el handle de sesion es correcto.
Xor Eax, Eax
Mov Eax, sessionHandle
Test Eax, Eax
Jz Error_HandleSesion
Pop Edi
Pop Esi
; *******************************************************
; Habilitamos el traceo de eventos.
; *******************************************************
; WINEVENT_KEYWORD_PROCESS = 0x10,
; WINEVENT_KEYWORD_THREAD = 0x20,
; WINEVENT_KEYWORD_IMAGE = 0x40,
; WINEVENT_KEYWORD_CPU_PRIORITY = 0x80,
; WINEVENT_KEYWORD_OTHER_PRIORITY = 0x100,
; WINEVENT_KEYWORD_PROCESS_FREEZE = 0x200,
; Invoke GetProcAddress, Edi, TextStr("EnableTrace")
; Mov Esi, Eax
;
; Push sessionHandle
; Lea Eax, generatedGuid
; Push Eax
; Push 4
; Push 0
; Push 1
Invoke GetProcAddress, Edi, TextStr("EnableTraceEx")
Mov Esi, Eax
Push NULL
Push 0
Push 0
Push 0
Push 4
Push 1
Push sessionHandle
Push NULL
Lea Eax, generatedGuid
Push Eax
Call Esi
Test Eax, Eax
Jnz Error_ExitSeis
; ******************************************************************
; Armamos el identificador de seguimiento ETW para consumir eventos.
; ******************************************************************
Mov Trace.ProcessTraceMode, EVENT_TRACE_REAL_TIME_MODE + PROCESS_TRACE_MODE_EVENT_RECORD
Mov Trace.LogFileName, NULL
Mov Trace.LoggerName, Offset LoggerName
Mov Trace.EventRecordCallback, Offset ProcessEvent
;Mov Trace.BufferCallback, Offset ProcessEvent
Mov Trace.Context, 2
Invoke GetProcAddress, Edi, TextStr("OpenTraceA")
Mov Esi, Eax
Lea Eax, Trace
Push Eax
Call Esi
Cmp Eax, -1
Je Error_ExitOcho
Mov sessionHandle, Eax
Invoke GetProcAddress, Edi, TextStr("ProcessTrace")
Mov Esi, Eax
Push NULL
Push NULL
Push 1
Push sessionHandle
Call Esi
Test Eax, Eax
Jnz Error_ExitNueve
Push Edi
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
Pop Edi
Jmp exit
.EndIf
; ; Terminar la sesión de ETW y liberar los recursos
; invoke ControlTrace, NULL, ADDR ETW_SESSION_NAME, ADDR sessionHandle, 2
jmp exit
error_exit:
; Manejar errores aquí
; Por ejemplo, imprimir un mensaje de error y salir
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error1, "Error al iniciar StartTraceA."
Invoke WriteConsoleA, HandleConsola, Addr Error1, 29, 0, 0
Jmp exit
error_exitDos:
; Manejar errores aquí
; Por ejemplo, imprimir un mensaje de error y salir
AsigText Error2, "Error al iniciar EnableTrace."
Invoke WriteConsoleA, HandleConsola, Addr Error2, 29, 0, 0
Jmp exit
error_exitTres:
; Manejar errores aquí
; Por ejemplo, imprimir un mensaje de error y salir
AsigText Error3, "Error al iniciar el procesador de eventos."
Invoke WriteConsoleA, HandleConsola, Addr Error3, 42, 0, 0
Jmp exit
error_exitCuatro:
AsigText Error4, "Error en captura de fundion de proceso de evento."
Invoke WriteConsoleA, HandleConsola, Addr Error4, 49, 0, 0
Jmp exit
error_exitCinco:
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error8, "Erron al iniciar EventRegister."
Invoke WriteConsoleA, HandleConsola, Addr Error8, 31, 0, 0
Jmp exit
Error_ExitSeis:
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error6, "Erron al iniciar EnableTraceEx2."
Invoke WriteConsoleA, HandleConsola, Addr Error6, 32, 0, 0
Jmp exit
Error_ExitSiete:
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error9, "Erron al iniciar CreandoGUID."
Invoke WriteConsoleA, HandleConsola, Addr Error9, 29, 0, 0
Jmp exit
guid_invalido:
AsigText Error10, "Erron validar GUID."
Invoke WriteConsoleA, HandleConsola, Addr Error10, 19, 0, 0
Jmp exit
Error_HandleSesion:
AsigText Error11, "Erron validar Handle Sesion."
Invoke WriteConsoleA, HandleConsola, Addr Error11, 28, 0, 0
Jmp exit
Error_ExitOcho:
Invoke GetLastError
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error13, "Error en OpenTraceA."
Invoke WriteConsoleA, HandleConsola, Addr Error13, 20, 0, 0
Jmp exit
Error_ExitNueve:
Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
AsigText Error14, "Error en ProcessTrace."
Invoke WriteConsoleA, HandleConsola, Addr Error14, 22, 0, 0
Jmp exit
exit:
Mov Edi, HandleLibrary
Invoke GetProcAddress, Edi, TextStr("StopTrace")
Mov Esi, Eax
Push NULL
Push NULL
Push sessionHandle
Call Esi
Invoke GetProcAddress, Edi, TextStr("CloseTrace")
Mov Esi, Eax
Push sessionHandle
Call Esi
AsigText Error15, "Fin programa."
Invoke WriteConsoleA, HandleConsola, Addr Error15, 13, 0, 0
invoke ExitProcess, 0
ProcessEvent Proc Uses Ebx Esi Edi, pEvent:Ptr EVENT_RECORD
AsigText Error12, "Entra captura."
Invoke WriteConsoleA, HandleConsola, Addr Error12, 14, 0, 0
Ret
ProcessEvent EndP
PasarADecimal Proc Valor:DWord
Push Esi
Push Edi
Mov Esi, Valor
Mov Edi, Offset tempbuffer
Invoke dwtoa, Esi, Edi
Pop Edi
Pop Esi
Ret
PasarADecimal EndP
End start
I haven't scrutinized your code, but one thing caught my eye:
Quote from: Fraile on February 13, 2024, 10:03:20 PMEVENT_HEADER Struct
SizeA Word 0
HeaderType Word 0
Flags Word 0
EventProperty Word 0
ThreadId DWord 0
ProcessId DWord 0
TimeStamp LARGE_INTEGER <>
ProviderId GUID <>
EventDescriptor EVENT_DESCRIPTOR <>
Union ; Comienzo de la unión
Struct ; Comienzo de la estructura anidada
KernelTime DWord ?
UserTime DWORD ?
ProcessorTime QWord ? ; Puedes ajustar el tamaño dependiendo del uso
EndS
EndS ; Fin de la unión
ActivityId GUID <>
EVENT_HEADER EndS
The union that is defined in this structure contains just one member - and that's obviously not a smart thing to do. So I guessed it might be wrong - and it indeed is: there are 2 members, variable ProcessorTime should be placed behind the ENDS belonging to the struct.
Don't you use a reliable tool to convert C structs to MASM structs?
I look at the structures in Microsoft and convert them to MASM32 using ChatGPT (which, to be honest, doesn't convert very well...). Then I tweak them, in this case, the flaw you've seen has been on my part. Thank you very much for the feedback.
Hello _japheth, thank you very much for your help and for taking the time to convert the C structures to masm32. I do use tools like Lib, dumpbind, l2inc... The mention of ChatGPT was partly a joke, but well, don't think it's going badly either, it helps. Anyway, I continue with the project, I have made some progress, some calls are no longer giving me errors. Once I have it finished, I'll publish it here, in case it can help the community. I'm learning a lot about ETW, I'm reading documentation to write a book, hehehehe. Best regards and thank you very much.