News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

ETW Event Consumer, StartTraceA API

Started by Fraile, February 11, 2024, 07:54:00 AM

Previous topic - Next topic

Fraile

Sure, no problem, this is something personal, hehehe. I'm really into it. I really appreciate your help. And the project, it could turn out really well, the idea is to create an article explaining how a SIEM works.


AsigText Macro Name, Text:VarArg
Local lbl
Jmp lbl
Name DB Text, 0
lbl:
EndM
ZeroMemory Macro lpAddress:Req, dwSize:Req
    Local zero_loop
    Mov Edi, lpAddress
    Mov Ecx, dwSize
    Xor Eax, Eax
    Rep Stosb
EndM

.Const

  WNODE_FLAG_TRACED_GUID                 Equ 00020000H ; Constante para indicar que el GUID del proveedor está incluido en el nodo
  EVENT_TRACE_REAL_TIME_MODE             Equ 00000100H
  EVENT_TRACE_USE_PAGED_MEMORY           Equ 01000000H

  PROCESS_TRACE_MODE_EVENT_RECORD        Equ 1000H

  EVENT_TRACE_NO_PER_PROCESSOR_BUFFERING Equ 10000000H
  EVENT_TRACE_FLAG_SECURITY              Equ 00000800H
  EVENT_TRACE_INDEPENDENT_SESSION_MODE   Equ 08000000H
  EVENT_TRACE_FILE_MODE_SEQUENTIAL       Equ 00000001H

  EVENT_CONTROL_CODE_DISABLE_PROVIDER    Equ 0
  EVENT_CONTROL_CODE_ENABLE_PROVIDER     Equ 1
  EVENT_CONTROL_CODE_CAPTURE_STATE       Equ 2

  EVENT_TRACE_CONTROL_QUERY              Equ 0
  EVENT_TRACE_CONTROL_STOP               Equ 1



  MiGuidProviderGuid TextEqu   <{054849625H, 05478H, 04994H, {0A5H, 0BAH, 03EH, 03BH, 003H, 028H, 0C3H, 00DH}}>


.Data?



.Data

WNODE_HEADER Struct
    BufferSize DWord ?
    ProviderId DWord ?
    Union
        HistoricalContext QWord ?
Struc
    Version DWord ?
        Linkage DWord ?
EndS
    EndS
    Union
        KernelHandle HANDLE ?
        TimeStamp LARGE_INTEGER <>
    EndS
    Guidx GUID <>
    ClientContext DWord ?
    Flags DWord ?
WNODE_HEADER EndS
EVENT_TRACE_PROPERTIES Struct
    Wnode WNODE_HEADER <>
    BufferSize DWord ?
    MinimumBuffers DWord ?
    MaximumBuffers DWord ?
    MaximumFileSize DWord ?
    LogFileMode DWord ?
    FlushTimer DWord ?
    EnableFlags DWord ?
Union DUMMYUNIONNAME
        AgeLimit DWord ?
        FlushThreshold DWord ?
EndS
    NumberOfBuffers DWord ?
    FreeBuffers DWord ?
    EventsLost DWord ?
    BuffersWritten DWord ?
    LogBuffersLost DWord ?
    RealTimeBuffersLost DWord ?
    LoggerThreadId HANDLE ?
    LogFileNameOffset DWord ?
    LoggerNameOffset DWord ?
EVENT_TRACE_PROPERTIES EndS
EventTracePropertyData Struct
Props        EVENT_TRACE_PROPERTIES <>
Padding DB 4 Dup(0)                ; Cuadramos alineacion.
LoggerName   DB 1024 Dup (0)
LogFileName  DB 'Frailog.etl', 0
EventTracePropertyData EndS

  HandleConsola   DD 0
  CarroDeRetorno          DB 13 ; Código ASCII para retorno de carro
  NuevaLinea              DB 10 ; Código ASCII para nueva línea

  LoggerNameAux      DB 'frailepatito', 0


  TraceProperties     EventTracePropertyData <>


  sessionHandle           DWord 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  <>
  ProviderId    GUID  < 05484962H, 0548H, 0499H, < 0A5H, 0BAH, 03EH, 03BH, 003H, 028H, 0C3H, 00DH>> ;MiGuidProviderGuid


  guidText      Byte 40 Dup(0)  ; Buffer para almacenar el GUID formateado
  formatGUID1   Byte "%08X-", 0 ; Formato para formatear el GUID
  formatGUID2   Byte "%04X-", 0 ; Formato para formatear el GUID
  formatGUID3   Byte "%02X", 0  ; Formato para formatear el 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

;=====================

AsigText Cabecera0, "----------------------------------"
    Invoke WriteConsoleA, HandleConsola, Addr Cabecera0, 25, 0, 0
    Invoke ImprimirSaltoDeLinea

AsigText Cabecera1, "FraiETW by Fraile - 2024."
    Invoke WriteConsoleA, HandleConsola, Addr Cabecera1, 25, 0, 0
    Invoke ImprimirSaltoDeLinea

AsigText Cabecera2, "----------------------------------"
    Invoke WriteConsoleA, HandleConsola, Addr Cabecera2, 25, 0, 0
    Invoke ImprimirSaltoDeLinea
    Invoke ImprimirSaltoDeLinea

;=====================


    ; 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

    ; Formatear el GUID como una cadena

AsigText CreateGUID, "[+] Obtenemos GUID de session: "
    Invoke WriteConsoleA, HandleConsola, Addr CreateGUID, 31, 0, 0

Invoke wsprintf, Addr guidText, Addr formatGUID1, generatedGuid.Data1
Invoke WriteConsoleA, HandleConsola, Addr guidText, 9, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, generatedGuid.Data2
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, generatedGuid.Data3
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [0]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [1]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [2]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [3]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [4]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [5]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [6]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, generatedGuid.Data4 [7]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL


    Invoke ImprimirSaltoDeLinea

;
    ; Llama a CoUninitialize para finalizar la biblioteca COM
    Invoke CoUninitialize

AsigText CreateGUIDProveedor, "[+] GUID de Proveedor: "
    Invoke WriteConsoleA, HandleConsola, Addr CreateGUIDProveedor, 23, 0, 0

Invoke wsprintf, Addr guidText, Addr formatGUID1, ProviderId.Data1
Invoke WriteConsoleA, HandleConsola, Addr guidText, 9, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, ProviderId.Data2
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, ProviderId.Data3
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [0]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [1]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [2]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [3]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [4]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [5]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [6]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, ProviderId.Data4 [7]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL


    Invoke ImprimirSaltoDeLinea
    Invoke ImprimirSaltoDeLinea



Invoke RtlZeroMemory, Addr TraceProperties, SizeOf EVENT_TRACE_PROPERTIES



   ; 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

; Push Edi
;
; Invoke PasarADecimal, ProviderHandle
; Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
;
; Pop Edi



; 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.Props.Wnode.BufferSize, SizeOf EventTracePropertyData
    Mov TraceProperties.Props.Wnode.ClientContext, 2
    Mov TraceProperties.Props.Wnode.Flags, WNODE_FLAG_TRACED_GUID



Push Esi
Push Edi

        ; Copia el GUID generado a la estructura WNODE_HEADER

        Mov Eax, generatedGuid.Data1
Mov TraceProperties.Props.Wnode.Guidx.Data1, Eax
        Mov Ax, generatedGuid.Data2
Mov TraceProperties.Props.Wnode.Guidx.Data2, Ax
        Mov Ax, generatedGuid.Data3
Mov TraceProperties.Props.Wnode.Guidx.Data3, Ax

        ; Copia el GUID generado a la estructura WNODE_HEADER
Lea Esi, generatedGuid.Data4
    Lea Edi, TraceProperties.Props.Wnode.Guidx.Data4
    Mov Ecx, 8
    Rep Movsb


    Pop Edi
    Pop Esi


    Mov TraceProperties.Props.LogFileMode, EVENT_TRACE_FILE_MODE_SEQUENTIAL + EVENT_TRACE_INDEPENDENT_SESSION_MODE ;+ EVENT_TRACE_NO_PER_PROCESSOR_BUFFERING + EVENT_TRACE_INDEPENDENT_SESSION_MODE


        Mov TraceProperties.Props.MinimumBuffers, 64
        Mov TraceProperties.Props.MaximumBuffers, 320

        Mov TraceProperties.Props.LoggerNameOffset, SizeOf TraceProperties - 1036
        Mov TraceProperties.Props.LogFileNameOffset, SizeOf TraceProperties - 12



Lea Eax, TraceProperties.Props ;.Props
Push Eax
Lea Eax, LoggerNameAux
Push Eax
Lea Eax, sessionHandle
Push Eax

Call Esi
    Test Eax, Eax
    Jnz error_exit


Push Esi
Push Edi


        ; Comprobamos que el handle de sesion es correcto.
        Xor Eax, Eax
        Mov Eax, sessionHandle
        Test Eax, Eax
        Jz Error_HandleSesion

AsigText StartTraceA, "[+] StartTraceA Correcto."
    Invoke WriteConsoleA, HandleConsola, Addr StartTraceA, 25, 0, 0
    Invoke ImprimirSaltoDeLinea


AsigText StartTraceAHandle, "    Handle:"
    Invoke WriteConsoleA, HandleConsola, Addr StartTraceAHandle, 11, 0, 0
    Invoke PasarADecimal, sessionHandle
    Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0
    Invoke ImprimirSaltoDeLinea


AsigText WnodeGUID, "    GUID:"
    Invoke WriteConsoleA, HandleConsola, Addr WnodeGUID, 9, 0, 0

Invoke wsprintf, Addr guidText, Addr formatGUID1, TraceProperties.Props.Wnode.Guidx.Data1
Invoke WriteConsoleA, HandleConsola, Addr guidText, 9, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, TraceProperties.Props.Wnode.Guidx.Data2
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID2, TraceProperties.Props.Wnode.Guidx.Data3
Invoke WriteConsoleA, HandleConsola, Addr guidText, 5, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [0]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [1]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [2]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [3]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [4]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [5]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [6]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL

Invoke wsprintf, Addr guidText, Addr formatGUID3, TraceProperties.Props.Wnode.Guidx.Data4 [7]
Invoke WriteConsoleA, HandleConsola, Addr guidText, 2, NULL, NULL


Invoke ImprimirSaltoDeLinea


AsigText WnodeBufferSize, "    BufferSize:"
    Invoke WriteConsoleA, HandleConsola, Addr WnodeBufferSize, 15, 0, 0
    Invoke PasarADecimal, TraceProperties.Props.BufferSize
    Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 2, 0, 0
    Invoke ImprimirSaltoDeLinea

AsigText WnodeName, "    Name:"
    Invoke WriteConsoleA, HandleConsola, Addr WnodeName, 9, 0, 0
    Invoke WriteConsoleA, HandleConsola, Addr TraceProperties.LoggerName, 12, 0, 0
    Invoke ImprimirSaltoDeLinea



;     Invoke WriteConsoleA, HandleConsola, Addr TraceProperties.LogFileName, SizeOf TraceProperties.LogFileName, 0, 0
;     Invoke ImprimirSaltoDeLinea



    Pop Edi
    Pop Esi

Jmp exit

       ; *******************************************************
       ; 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,

Mov Edi, HandleLibrary

    Invoke GetProcAddress, Edi, TextStr("EnableTrace")
Mov Esi, Eax

Push sessionHandle
Lea Eax, ProviderId
Push Eax
Push 4
Push 0
Push 1



;    Invoke GetProcAddress, Edi, TextStr("EnableTraceEx2")
; Mov Esi, Eax
;
; Push 0
; Push 0
; Push 0
; Push 0
; Push 5
; Push 1
; Lea Eax, ProviderId
; Push Eax
;     Push sessionHandle

Call Esi
Test Eax, Eax
Jnz Error_ExitSeis

Push Edi

Invoke PasarADecimal, 1
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0

Pop Edi



; ******************************************************************
; Armamos el identificador de seguimiento ETW para consumir eventos.
    ; ******************************************************************



   .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

Error_ExitDiez:

Invoke PasarADecimal, Eax
Invoke WriteConsoleA, HandleConsola, Addr tempbuffer, 4, 0, 0

    AsigText Error15, "Error en ControlTraceA."
Invoke WriteConsoleA, HandleConsola, Addr Error15, 23, 0, 0
Jmp exitFinal


exit:

;Invoke Sleep, 30000

Mov Edi, HandleLibrary

;    Invoke GetProcAddress, Edi, TextStr("StopTrace")
;    Test Eax, Eax
;    Jz exitFinal
;
; Mov Esi, Eax
;
; Push NULL
; Push sessionHandle


        Mov TraceProperties.Props.LogFileNameOffset, 0

    Invoke GetProcAddress, Edi, TextStr("ControlTraceA")
    Test Eax, Eax
    Jz exitFinal

Mov Esi, Eax

Push EVENT_TRACE_CONTROL_QUERY ;EVENT_TRACE_CONTROL_STOP
Lea Eax, TraceProperties
Push Eax
;Lea Eax, LoggerNameAux
Push NULL
Push sessionHandle

Call Esi
Test Eax, Eax
Jnz Error_ExitDiez


exitFinal:

    AsigText SalidaPrograma, "Fin programa."
Invoke WriteConsoleA, HandleConsola, Addr SalidaPrograma, 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
ImprimirSaltoDeLinea Proc
    ; Imprime un retorno de carro (CR) y una nueva línea (LF) en la consola
    Invoke WriteConsole, HandleConsola, Addr CarroDeRetorno, 1, 0, 0
    Invoke WriteConsole, HandleConsola, Addr NuevaLinea, 1, 0, 0
    Ret
ImprimirSaltoDeLinea EndP


End start




_japheth

I haven't tried your code yet ( it's still not complete, btw ), but caught 2 things

a) is LARGE_INTEGER indeed defined as a qword?
b) this calculations

   Mov TraceProperties.Props.LoggerNameOffset, SizeOf TraceProperties - 1036
   Mov TraceProperties.Props.LogFileNameOffset, SizeOf TraceProperties - 12
are correct (I guess), but the proper way to do this is:
   Mov TraceProperties.Props.LoggerNameOffset, EventTracePropertyData.LoggerName
   Mov TraceProperties.Props.LogFileNameOffset, EventTracePropertyData.LogFileName

Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

Fraile

Well, it's a small example, I haven't completed it because I can't get past 'controltraceA', as you can see. Regarding the calculation question, according to Microsoft, you have to provide the starting offset of the buffer where 'starttraceA' will store the name of the event logger and the buffer for the event file name.


EventTracePropertyData Struct
    Props        EVENT_TRACE_PROPERTIES <>
    Padding        DB 4 Dup(0)                ; Cuadramos alineacion.
    LoggerName  DB 1024 Dup (0)
    LogFileName  DB 'Frailog.etl', 0
EventTracePropertyData EndS


1024 buffer to store the session name and 12 for the event file name, making 1036 the start of the first buffer. That's why the calculation.


EventTracePropertyData Struct
    Props        EVENT_TRACE_PROPERTIES <>
    Padding        DB 4 Dup(0)                ; Cuadramos alineacion.
    LoggerName  DB 1024 Dup (0)
    LogFileName  DB 'Frailog.etl', 0
EventTracePropertyData EndS
.
.
.


Mov TraceProperties.Props.LoggerNameOffset, SizeOf TraceProperties - 1036
Mov TraceProperties.Props.LogFileNameOffset, SizeOf TraceProperties - 12


Padding db 4 dup(0), it's because of the alignment issue, it doesn't allow the session name to start at the beginning of the LoggerName buffer.





_japheth

Quote from: Fraile on March 09, 2024, 07:02:06 AM1024 buffer to store the session name and 12 for the event file name, making 1036 the start of the first buffer. That's why the calculation.

I understand the calculation. I proposed the "proper way", because it does the same thing WITHOUT having to do calculations - because expression STRUCTNAME.MEMBERNAME actually returns the offset of the member within the struct.


Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

Fraile

Ah!! Right, you're correct. But the reason why I can't use EnableTraceEx, or EnableTraceEx, ControlTraceA to stop the session initiated with StartTraceA... I just can't seem to figure out the error. I've realized that a possible issue might be the size of the buffer defined in "Mov TraceProperties.Props.Wnode.BufferSize, SizeOf EventTracePropertyData". Playing with the code and altering the buffer, the function that used to work, EnableTrace (obsolete), fails if it's not given the correct configuration. This could possibly be what's causing the other mentioned functions to fail...

sinsi

Which version of Windows are you using? Different functions are in different DLLs, are you looking in the right place?
Quote from: EnableTraceEx2 functionSechost.dll on Windows 8.1 and Windows Server 2012 R2; Advapi32.dll on Windows 8, Windows Server 2012, Windows 7 and Windows Server 2008 R2

_japheth

Quote from: Fraile on March 09, 2024, 10:50:19 PMAh!! Right, you're correct. But the reason why I can't use EnableTraceEx, or EnableTraceEx, ControlTraceA to stop the session initiated with StartTraceA... I just can't seem to figure out the error. I've realized that a possible issue might be the size of the buffer defined in "Mov TraceProperties.Props.Wnode.BufferSize, SizeOf EventTracePropertyData".

The simple fact that you have to add "padding bytes" to your structure is a sign that there's something wrong with the struct's definition.

Try to create and post a listing file...
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

Fraile

Yes, that's correct, but the thing is that the structures seem to be fine, both in C and in masm32 they have the same number of bits. I'm at a loss...

It's just that we're only talking about two structures... it's got me really puzzled

Fraile


sinsi

OK, so EnableTraceEx2 would be found in sechost.dll but I think you're looking in advapi32.

Fraile

In Microsoft documentation:
Library Sechost.lib on Windows 8.1 and Windows Server 2012 R2; Advapi32.lib on Windows 8, Windows Server 2012, Windows 7, and Windows Server 2008 R2
DLL Sechost.dll on Windows 8.1 and Windows Server 2012 R2; Advapi32.dll on Windows 8, Windows Server 2012, Windows 7, and Windows Server 2008 R2

Fraile

My idea is simply to open a session with StartTraceA, which seems to be working fine (apparently), and close it with ControlTraceA. This way, I'll know I'm on the right track. Right now, opening it seems to be working, as I confirm with "D:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit>xperf -loggers". Or, I could use EnableTraceEx...

Fraile

Example in C


// ETW CLR Tracker, by aaaddress1@chroot.org
// rewrite from post "Hiding your .NET - ETW"
// URL: https://blog.xpnsec.com/hiding-your-dotnet-etw/
#define AssemblyDCStart_V1 155
#define AssemblyLoad_V1 154
#define MethodLoadVerbose_V1 143

#include <windows.h>
#include <stdio.h>
#include <wbemidl.h>
#include <wmistr.h>
#include <evntrace.h>
#include <Evntcons.h>

static GUID ClrRuntimeProviderGuid = { 0xe13c0d23, 0xccbc, 0x4e12, { 0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4 } };

// Can be stopped with 'logman stop "dotnet trace" -ets'
const char name[] = "dotnet trace\0";

#pragma pack(1)
typedef struct _AssemblyLoadUnloadRundown_V1
{
ULONG64 AssemblyID;
ULONG64 AppDomainID;
ULONG64 BindingID;
ULONG AssemblyFlags;
WCHAR FullyQualifiedAssemblyName[1];
} AssemblyLoadUnloadRundown_V1, * PAssemblyLoadUnloadRundown_V1;

typedef struct _MethodLoadVerbose_V1
{
ULONG64 MethodID;
ULONG64 ModuleID;
ULONG64 MethodStartAddress;
DWORD MethodSize;
DWORD MethodToken;
DWORD MethodFlags;
WCHAR MethodNameSpace[1];
} MethodLoadUnloadVerbose_V1, * PMethodLoadUnloadVerbose_V1;
#pragma pack()

static void NTAPI ProcessEvent(PEVENT_RECORD EventRecord) {

PEVENT_HEADER eventHeader = &EventRecord->EventHeader;
PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor;
AssemblyLoadUnloadRundown_V1* assemblyUserData;
MethodLoadUnloadVerbose_V1* methodUserData;

switch (eventDescriptor->Id) {
case AssemblyLoad_V1:
assemblyUserData = (AssemblyLoadUnloadRundown_V1*)EventRecord->UserData;
wprintf(L"[%d] - Assembly: %s\n", eventHeader->ProcessId, assemblyUserData->FullyQualifiedAssemblyName);
break;
/*case MethodLoadVerbose_V1:
methodUserData = (struct _MethodLoadVerbose_V1*)EventRecord->UserData;
WCHAR* MethodNameSpace = methodUserData->MethodNameSpace;
WCHAR* MethodName = (WCHAR*)(((char*)methodUserData->MethodNameSpace) + (lstrlenW(methodUserData->MethodNameSpace) * 2) + 2);
WCHAR* MethodSignature = (WCHAR*)(((char*)MethodName) + (lstrlenW(MethodName) * 2) + 2);
wprintf(L"[%d] - MethodNameSpace: %s\n", eventHeader->ProcessId, methodUserData->MethodNameSpace);
wprintf(L"[%d] - MethodName: %s\n", eventHeader->ProcessId, MethodName);
wprintf(L"[%d] - MethodSignature: %s\n", eventHeader->ProcessId, MethodSignature);
break;*/
}
}

int main(void)
{
TRACEHANDLE hTrace = 0;
ULONG result, bufferSize;
EVENT_TRACE_LOGFILEA trace;
EVENT_TRACE_PROPERTIES* traceProp;

printf("ETW .NET Trace example - @_xpn_\n\n");

memset(&trace, 0, sizeof(EVENT_TRACE_LOGFILEA));
trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
trace.LoggerName = (LPSTR)name;
trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)ProcessEvent;

bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(name) + sizeof(WCHAR);

traceProp = (EVENT_TRACE_PROPERTIES*)LocalAlloc(LPTR, bufferSize);
traceProp->Wnode.BufferSize = bufferSize;
traceProp->Wnode.ClientContext = 2;
traceProp->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
traceProp->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
traceProp->LogFileNameOffset = 0;
traceProp->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);

if ((result = StartTraceA(&hTrace, (LPCSTR)name, traceProp)) != ERROR_SUCCESS) {
printf("[!] Error starting trace: %d\n", result);
return 1;
}

if ((result = EnableTraceEx(
&ClrRuntimeProviderGuid,
NULL,
hTrace,
1,
TRACE_LEVEL_VERBOSE,
0x8 | 0x10, // LoaderKeyword | JITKeyword
0,
0,
NULL
)) != ERROR_SUCCESS) {
printf("[!] Error EnableTraceEx\n");
return 2;
}

hTrace = OpenTraceA(&trace);
if (hTrace == INVALID_PROCESSTRACE_HANDLE) {
printf("[!] Error OpenTrace\n");
return 3;
}

result = ProcessTrace(&hTrace, 1, NULL, NULL);
if (result != ERROR_SUCCESS) {
printf("[!] Error ProcessTrace\n");
return 4;
}

return 0;
}

Fraile

I think I've got it now. I can create a session with StartTraceA and close it with ControlTraceA. One of the issues is the alignment, as I've already mentioned. The other problem is the variable passed to StartTraceA, 'sessionHandle.' This variable has to be of type Qword and needs to be moved onto the stack in the following way:

 :eusa_boohoo:  :eusa_dance:

..

    Invoke GetProcAddress, Edi, TextStr("EnableTraceEx2")
Mov Esi, Eax

Push 0
Push 0
Push 0
Push 0
Push 4
Push 1
Lea Eax, ProviderId
Push Eax
Push DWord Ptr [sessionHandle + 4]
        Push DWord Ptr [sessionHandle]
 
        Call Esi

..

I'm still working on the project. The idea is to capture Windows security events, such as connection attempts...



six_L

#29
hi,Fraile
this translated from your c codes.
win64,No errors happened. but i don't know whether it works.
option casemap:none
option win64:7

include \UASM64\include\windows.inc

includelib \UASM64\Lib\user32.lib
includelib \UASM64\Lib\kernel32.lib
includelib \UASM64\Lib\Advapi32.lib

AssemblyLoadUnloadRundown_V1 STRUCT
AssemblyID ULONG64 ?
AppDomainID ULONG64 ?
BindingID ULONG64 ?
AssemblyFlags DWORD ?
FullyQualifiedAssemblyName WCHAR 1 dup(?)
AssemblyLoadUnloadRundown_V1 ENDS
PAssemblyLoadUnloadRundown_V1 typedef ptr AssemblyLoadUnloadRundown_V1

_MethodLoadVerbose_V1 STRUCT
MethodID ULONG64 ?
ModuleID ULONG64 ?
MethodStartAddress ULONG64 ?
MethodSize DWORD ?
MethodToken DWORD ?
MethodFlags DWORD ?
MethodNameSpace WCHAR 1 dup(?)
_MethodLoadVerbose_V1 ENDS
PMethodLoadUnloadVerbose_V1 typedef ptr _MethodLoadVerbose_V1

ETW_BUFFER_CONTEXT STRUCT
union DUMMYUNIONNAME
STRUCT DUMMYSTRUCTNAME
ProcessorNumber BYTE ?
Alignment BYTE ?
ENDS
ProcessorIndex WORD ?
ENDS
LoggerId WORD ?
ETW_BUFFER_CONTEXT ENDS
PETW_BUFFER_CONTEXT typedef ptr ETW_BUFFER_CONTEXT

EVENT_DESCRIPTOR STRUCT
Id WORD ?
Version BYTE ?
Channel BYTE ?
Level BYTE ?
Opcode BYTE ?
Task WORD ?
Keyword REAL8 ?
EVENT_DESCRIPTOR ENDS
PEVENT_DESCRIPTOR typedef ptr EVENT_DESCRIPTOR

EVENT_HEADER STRUCT
size1 WORD ? ; Event Size
HeaderType WORD ? ; Header Type
Flags WORD ? ; Flags
EventProperty WORD ? ; User given event property
ThreadId DWORD ? ; Thread Id
ProcessId DWORD ? ; Process Id
TimeStamp LARGE_INTEGER <> ; Event Timestamp
ProviderId GUID <> ; Provider Id
EventDescriptor EVENT_DESCRIPTOR <> ; Event Descriptor
union DUMMYUNIONNAME
STRUCT DUMMYSTRUCTNAME
KernelTime DWORD ? ; Kernel Mode CPU ticks
UserTime DWORD ? ; User mode CPU ticks
ENDS
ProcessorTime QWORD ? ; Processor Clock
ENDS
ActivityId GUID <> ; Activity Id
EVENT_HEADER ENDS
PEVENT_HEADER typedef ptr EVENT_HEADER

EVENT_RECORD STRUCT
EventHeader EVENT_HEADER <> ; Event header
BufferContext ETW_BUFFER_CONTEXT <>  ; Buffer context
ExtendedDataCount WORD ? ; Number of extended
UserDataLength WORD ? ; User data length
ExtendedData QWORD ? ; extended data items                                               
UserData QWORD ? ; Pointer to user data
UserContext QWORD ? ; Context from OpenTrace
EVENT_RECORD ENDS
PEVENT_RECORD typedef ptr EVENT_RECORD

EVENT_TRACE_HEADER STRUCT
size1 WORD ? ; Size of entire record
union DUMMYUNIONNAME
FieldTypeFlags WORD ? ; Indicates valid fields
STRUCT DUMMYSTRUCTNAME
HeaderType BYTE ? ; Header type - internal use only
MarkerFlags BYTE ? ; Marker - internal use only
ENDS
ENDS
union DUMMYUNIONNAME2
Version DWORD ?
STRUCT Class
type1 BYTE ? ; event type
Level BYTE ? ; trace instrumentation level
Version WORD ? ; version of trace record
ENDS
ENDS
ThreadId DWORD ? ; Thread Id
ProcessId DWORD ? ; Process Id
TimeStamp LARGE_INTEGER <> ; time when event happens
union DUMMYUNIONNAME3
Guid GUID <> ; Guid that identifies event
GuidPtr ULONGLONG ? ; use with WNODE_FLAG_USE_GUID_PTR
ENDS
union DUMMYUNIONNAME4
STRUCT DUMMYSTRUCTNAME5
KernelTime DWORD ? ; Kernel Mode CPU ticks
UserTime DWORD ? ; User mode CPU ticks
ENDS
ProcessorTime QWORD ? ; Processor Clock
STRUCT DUMMYSTRUCTNAME6
ClientContext DWORD ? ; Reserved
_Flags DWORD ? ; Event Flags
ENDS
ENDS
EVENT_TRACE_HEADER ENDS
PEVENT_TRACE_HEADER typedef ptr EVENT_TRACE_HEADER

EVENT_TRACE STRUCT
Header EVENT_TRACE_HEADER <> ; Event trace header
InstanceId DWORD ? ; Instance Id of this event
ParentInstanceId DWORD ? ; Parent Instance Id.
ParentGuid GUID <> ; Parent Guid;
MofData QWORD ? ; Pointer to Variable Data
MofLength DWORD ? ; Variable Datablock Length
union DUMMYUNIONNAME
ClientContext DWORD ?
BufferContext ETW_BUFFER_CONTEXT <>
ENDS
EVENT_TRACE ENDS
PEVENT_TRACE typedef ptr EVENT_TRACE

TRACE_LOGFILE_HEADER STRUCT
BufferSize DWORD ? ; Logger buffer size in Kbytes
union DUMMYUNIONNAME
Version DWORD ? ; Logger version
STRUCT VersionDetail
MajorVersion BYTE ?
MinorVersion BYTE ?
SubVersion BYTE ?
SubMinorVersion BYTE ?
ENDS
ENDS
ProviderVersion DWORD ? ; defaults to NT version
NumberOfProcessors DWORD ? ; Number of Processors
EndTime LARGE_INTEGER <> ; Time when logger stops
TimerResolution DWORD ? ; assumes timer is constant!!!
MaximumFileSize DWORD ? ; Maximum in Mbytes
LogFileMode DWORD ? ; specify logfile mode
BuffersWritten DWORD ? ; used to file start of Circular File
union DUMMYUNIONNAME2
LogInstanceGuid GUID <> ; For RealTime Buffer Delivery
STRUCT DUMMYSTRUCTNAME
StartBuffers DWORD ? ; Count of buffers written at start.
PointerSize DWORD ? ; Size of pointer type in bits
EventsLost DWORD ? ; Events losts during log session
CpuSpeedInMHz DWORD ? ; Cpu Speed in MHz
ENDS
ENDS
;IF DEFINED(_WMIKM_) ;ring0
;LoggerName QWORD ?
;LogFileName QWORD ?
;TimeZone RTL_TIME_ZONE_INFORMATION ?
;ELSE ;ring3
LoggerName QWORD ?
LogFileName QWORD ?
TimeZone TIME_ZONE_INFORMATION <>
;ENDIF
BootTime LARGE_INTEGER <>
PerfFreq LARGE_INTEGER <> ; Reserved
StartTime LARGE_INTEGER <> ; Reserved
ReservedFlags DWORD ? ; ClockType
BuffersLost DWORD ?
TRACE_LOGFILE_HEADER ENDS
PTRACE_LOGFILE_HEADER typedef ptr TRACE_LOGFILE_HEADER

EVENT_TRACE_LOGFILEA STRUCT
LogFileName QWORD ? ; Logfile Name
LoggerName QWORD ? ; LoggerName
CurrentTime LONGLONG ? ; timestamp of last event
BuffersRead ULONG ? ; buffers read to date
union DUMMYUNIONNAME
LogFileMode DWORD ? ; Mode of the logfile
ProcessTraceMode DWORD ? ; Processing flags
ENDS
CurrentEvent EVENT_TRACE <> ; Current Event from this stream
LogfileHeader TRACE_LOGFILE_HEADER <> ; logfile header structure
BufferCallback QWORD ? ; is read
BufferSize DWORD ?
Filled DWORD ?
EventsLost DWORD ?
union DUMMYUNIONNAME2
EventCallback QWORD ? ; callback for every event
EventRecordCallback QWORD ?
ENDS
IsKernelTrace DWORD ? ; TRUE for kernel logfile
Context QWORD ? ; reserved for internal use
EVENT_TRACE_LOGFILEA ENDS
PEVENT_TRACE_LOGFILEA typedef ptr EVENT_TRACE_LOGFILEA

WNODE_HEADER STRUCT
BufferSize DWORD ? ; Size of entire buffer inclusive of this ULONG
ProviderId DWORD ? ; Provider Id of driver returning this buffer
union DUMMYUNIONNAME
HistoricalContext QWORD ? ; Logger use
STRUCT DUMMYSTRUCTNAME
Version DWORD ? ; Reserved
Linkage DWORD ? ; Linkage field reserved for WMI
ENDS
ENDS
union DUMMYUNIONNAME2
CountLost DWORD ? ; Reserved
KernelHandle HANDLE ? ; Kernel handle for data block
TimeStamp LARGE_INTEGER <>  ; Timestamp as returned in units of 100ns
ENDS
Guid GUID <> ; Guid for data block returned with results
ClientContext DWORD ?
Flags DWORD ? ; Flags, see below
WNODE_HEADER ENDS

EVENT_TRACE_PROPERTIES STRUCT
Wnode WNODE_HEADER <>
BufferSize DWORD ? ; buffer size for logging (kbytes)
MinimumBuffers DWORD ? ; minimum to preallocate
MaximumBuffers DWORD ? ; maximum buffers allowed
MaximumFileSize DWORD ? ; maximum logfile size (in MBytes)
LogFileMode DWORD ? ; sequential, circular
FlushTimer DWORD ? ; buffer flush timer, in seconds
EnableFlags DWORD ? ; trace enable flags
union DUMMYUNIONNAME
AgeLimit DWORD ? ; unused
FlushThreshold DWORD ? ; Number of buffers to fill before flushing
ENDS
NumberOfBuffers DWORD ? ; no of buffers in use
FreeBuffers DWORD ? ; no of buffers free
EventsLost DWORD ? ; event records lost
BuffersWritten DWORD ? ; no of buffers written to file
LogBuffersLost DWORD ? ; no of logfile write failures
RealTimeBuffersLost DWORD ? ; no of rt delivery failures
LoggerThreadId HANDLE ? ; thread id of Logger
LogFileNameOffset DWORD ? ; Offset to LogFileName
LoggerNameOffset DWORD ? ; Offset to LoggerName
EVENT_TRACE_PROPERTIES ENDS
PEVENT_TRACE_PROPERTIES typedef ptr EVENT_TRACE_PROPERTIES

_StartTraceA typedef PROTO TraceHandle:QWORD,InstanceName:QWORD,Properties:QWORD
@StartTraceA typedef ptr _StartTraceA
_EnableTraceEx typedef PROTO ProviderId:QWORD,SourceId:QWORD,TraceHandle:QWORD,IsEnabled:DWORD,Level:DWORD,MatchAnyKeyword:DWORD,MatchAllKeyword:DWORD,EnableProperty:DWORD,EnableFilterDesc:QWORD
@EnableTraceEx typedef ptr _EnableTraceEx
_OpenTraceA typedef PROTO Logfile:QWORD
@OpenTraceA typedef ptr _OpenTraceA
_ProcessTrace typedef PROTO HandleArray:QWORD,HandleCount:DWORD,StartTime:QWORD,EndTime:QWORD
@ProcessTrace typedef ptr _ProcessTrace

.const
IDD_DIALOG equ 100
IDI_ICON equ 200

IDC_TEST equ 3002
IDC_EXIT equ 3003
IDC_OUTPUT equ 3004

AssemblyDCStart_V1 equ 155
AssemblyLoad_V1 equ 154
MethodLoadVerbose_V1 equ 143

PROCESS_TRACE_MODE_REAL_TIME equ < 000000100h>
PROCESS_TRACE_MODE_EVENT_RECORD equ < 010000000h>
WNODE_FLAG_TRACED_GUID equ < 000020000h>
EVENT_TRACE_REAL_TIME_MODE equ < 000000100h>
EVENT_TRACE_USE_PAGED_MEMORY equ < 001000000h>
TRACE_LEVEL_VERBOSE equ < 5>


.data
Name db "dotnet trace",0
;GUID { 0xe13c0d23, 0xccbc, 0x4e12, { 0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4 } }
ClrRuntimeProviderGuid \
dd 0e13c0d23h
dw 0ccbch
dw 04e12h
db 093h, 01bh, 0d9h, 0cch, 02eh, 0eeh, 027h, 0e4h

.data?
hUserDll dq ?
hInstance HINSTANCE ?
hMain dq ?
hHeap dq ?
pStartTraceA @StartTraceA ?
pEnableTraceEx @EnableTraceEx ?
pOpenTraceA @OpenTraceA ?
pProcessTrace @ProcessTrace ?

.code

ErrorMessage Proc uses rbx lpCaption:qword
Local lpErrorMessage:QWORD

call GetLastError
lea rbx,lpErrorMessage
invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, NULL, eax, LANG_NEUTRAL,rbx,0,NULL

invoke MessageBox, 0, lpErrorMessage, lpCaption, MB_OK or MB_ICONINFORMATION
invoke LocalFree, lpErrorMessage
ret   

ErrorMessage EndP

GetTraceApiFunctions proc

invoke LoadLibrary,CStr("Advapi32.dll")
.if rax
mov hUserDll,rax
invoke GetProcAddress,hUserDll,CStr("StartTraceA")
mov pStartTraceA,rax
.if rax == NULL
invoke ErrorMessage,CStr("StartTraceA")
jmp @Err
.endif

invoke GetProcAddress,hUserDll,CStr("EnableTraceEx")
mov pEnableTraceEx,rax
.if rax == NULL
invoke ErrorMessage,CStr("EnableTraceEx")
jmp @Err
.endif

invoke GetProcAddress,hUserDll,CStr("OpenTraceA")
mov pOpenTraceA,rax
.if rax == NULL
invoke ErrorMessage,CStr("OpenTraceA")
jmp @Err
.endif

invoke GetProcAddress,hUserDll,CStr("ProcessTrace")
mov pProcessTrace,rax
.if rax == NULL
invoke ErrorMessage,CStr("ProcessTrace")
jmp @Err
.endif
.else
invoke MessageBox,NULL,CStr("Advapi32.dll load Failed"),CStr("GetModuleHandle"),MB_OK
jmp @Err
.endif
mov rax,0
ret
@Err:
mov rax,1
ret

GetTraceApiFunctions endp

AddLog proc pStr:QWORD

        invoke  SendDlgItemMessage, hMain,IDC_OUTPUT,EM_GETLINECOUNT,0,0
        dec     rax
        invoke  SendDlgItemMessage, hMain,IDC_OUTPUT,EM_LINEINDEX,rax,0
        invoke  SendDlgItemMessage, hMain,IDC_OUTPUT,EM_SETSEL,rax,rax
        invoke  SendDlgItemMessage, hMain,IDC_OUTPUT,EM_REPLACESEL,FALSE,pStr
invoke SendDlgItemMessage, hMain,IDC_OUTPUT, EM_SCROLLCARET, 0, 0
        ret

AddLog endp

ProcessEvent proc uses rbx rsi rdi EventRecord:PEVENT_RECORD
Local eventHeader:PEVENT_HEADER
Local eventDescriptor:PEVENT_DESCRIPTOR
Local assemblyUserData:AssemblyLoadUnloadRundown_V1
Local methodUserData:_MethodLoadVerbose_V1
Local MethodNameSpace:QWORD
Local MethodName:QWORD
Local MethodSignature:QWORD
Local szTmpBuf[1024]:BYTE
Local szTmpBuf1[128]:BYTE

  invoke RtlZeroMemory,ADDR szTmpBuf,sizeof szTmpBuf

mov rbx,EventRecord
mov rax,(EVENT_RECORD PTR [rbx]).EventHeader
mov eventHeader,rax

mov rsi,eventHeader
lea rax,(EVENT_HEADER PTR [rsi]).EventDescriptor
mov eventDescriptor,rax

mov rdi,eventDescriptor
mov cx,(EVENT_DESCRIPTOR PTR [rdi]).Id

.if cx == AssemblyLoad_V1
mov rax,(EVENT_RECORD PTR [rbx]).UserData
mov assemblyUserData,rax
invoke  wsprintf,addr szTmpBuf,CStr("[%d] - Assembly: %s",13,10),(EVENT_HEADER PTR [rsi]).ProcessId,(AssemblyLoadUnloadRundown_V1 PTR [rax]).FullyQualifiedAssemblyName
invoke  AddLog,addr szTmpBuf

;.elseif cx == MethodLoadVerbose_V1 ;/*case MethodLoadVerbose_V1:
; mov rax,(EVENT_RECORD PTR [rbx]).UserData
; mov methodUserData,rax
;
; ;MethodNameSpace = methodUserData->MethodNameSpace
; lea rcx,(_MethodLoadVerbose_V1 PTR [rax]).MethodNameSpace
; mov MethodNameSpace,rcx
;
; lea rsi,methodUserData
; ;MethodName = (WCHAR*)(((char*)methodUserData->MethodNameSpace) + (lstrlenW(methodUserData->MethodNameSpace) * 2) + 2)
; invoke  lstrlenW,addr (_MethodLoadVerbose_V1 PTR [rsi]).MethodNameSpace
; shl rax,1 ;*2
; lea rcx,(_MethodLoadVerbose_V1 PTR [rsi]).MethodNameSpace
; add rcx,rax
; add rcx,2
; mov MethodName,rcx
;
; ;MethodSignature = (WCHAR*)(((char*)MethodName) + (lstrlenW(MethodName) * 2) + 2);
; invoke  lstrlenW,MethodName
; shl rax,1 ;*2
; mov rcx,MethodName
; add rcx,rax
; add rcx,2
; mov MethodSignature,rcx
;
; mov rbx,eventHeader
; invoke  wsprintf,addr szTmpBuf,CStr("[%d] - MethodNameSpace: %s",13,10),(EVENT_HEADER PTR [rbx]).ProcessId,(_MethodLoadVerbose_V1 PTR [rsi]).MethodNameSpace
  ;
; invoke RtlZeroMemory,ADDR szTmpBuf1,sizeof szTmpBuf1
; invoke  wsprintf,addr szTmpBuf1,CStr("[%d] - MethodName: %s",13,10),(EVENT_HEADER PTR [rbx]).ProcessId,MethodName
; invoke lstrcat,addr szTmpBuf,addr szTmpBuf1
  ;
; invoke RtlZeroMemory,ADDR szTmpBuf1,sizeof szTmpBuf1
; invoke  wsprintf,addr szTmpBuf1,CStr("[%d] - MethodSignature: %s",13,10),(EVENT_HEADER PTR [rbx]).ProcessId,MethodSignature
; invoke lstrcat,addr szTmpBuf,addr szTmpBuf1
; invoke  AddLog,addr szTmpBuf
.endif

ret

ProcessEvent endp

WorkerThread proc uses rbx szpBuf:QWORD ;int main(void)
Local szTmp[1024]:BYTE
Local hTrace:QWORD
Local result:ULONG
Local bufferSize:ULONG
Local trace:EVENT_TRACE_LOGFILEA
Local traceProp:PEVENT_TRACE_PROPERTIES

invoke  AddLog,CStr("ETW .NET Trace example - @_xpn_",13,10)

invoke RtlZeroMemory,ADDR trace,sizeof trace
mov trace.ProcessTraceMode,PROCESS_TRACE_MODE_REAL_TIME or PROCESS_TRACE_MODE_EVENT_RECORD
lea rax,Name
mov trace.LoggerName,rax
lea rax,ProcessEvent
mov trace.EventRecordCallback,rax

mov eax,sizeof Name
add eax,sizeof EVENT_TRACE_PROPERTIES
add eax,sizeof WCHAR
mov bufferSize,eax

invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY, bufferSize
mov traceProp,rax

mov rbx,traceProp
mov eax,bufferSize
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).Wnode.BufferSize,eax
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).Wnode.ClientContext,2
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).Wnode.Flags,WNODE_FLAG_TRACED_GUID
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).LogFileMode,EVENT_TRACE_REAL_TIME_MODE or EVENT_TRACE_USE_PAGED_MEMORY
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).LogFileNameOffset,0
mov (EVENT_TRACE_PROPERTIES PTR [rbx]).LoggerNameOffset,sizeof EVENT_TRACE_PROPERTIES

invoke pStartTraceA,addr hTrace,addr Name, traceProp
.if rax != ERROR_SUCCESS
invoke ErrorMessage,CStr("StartTraceA")
mov rax,1
ret
.endif
invoke pEnableTraceEx,addr ClrRuntimeProviderGuid,NULL,hTrace,1,\
TRACE_LEVEL_VERBOSE,08h or 010h,0,0,NULL
.if rax != ERROR_SUCCESS
invoke ErrorMessage,CStr("EnableTraceEx")
mov rax,2
ret
.endif
invoke pOpenTraceA,addr trace
.if rax == 0
invoke ErrorMessage,CStr("OpenTraceA")
mov rax,3
ret
.endif
mov hTrace,rax
invoke pProcessTrace,addr hTrace,1,NULL,NULL
.if rax != ERROR_SUCCESS
invoke ErrorMessage,CStr("ProcessTrace")
mov rax,4
ret
.endif
  invoke HeapFree,hHeap,HEAP_ZERO_MEMORY,traceProp

mov rax,0
ret

WorkerThread endp

DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

mov eax,uMsg
.if eax==WM_INITDIALOG
invoke LoadIcon,hInstance,IDI_ICON
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,rax

mov rax,hWnd
mov hMain,rax

invoke GetTraceApiFunctions

invoke GetProcessHeap
mov hHeap, rax

.elseif eax==WM_COMMAND
mov rax,wParam
mov rdx,rax
shr edx,16
.if edx == BN_CLICKED
.if ax==IDC_EXIT
invoke SendMessage,hWnd,WM_CLOSE,0, 0
.elseif ax==IDC_TEST
invoke CreateThread,NULL,NULL,offset WorkerThread,NULL,NULL,NULL
invoke CloseHandle,rax
.endif
.endif
.elseif eax==WM_CLOSE
invoke  FreeLibrary,hUserDll
invoke EndDialog,hWnd,0
.endif
xor rax,rax
ret

DlgProc endp

WinMainCRTStartup Proc
invoke GetModuleHandle,NULL
mov hInstance,rax
invoke DialogBoxParam,hInstance,IDD_DIALOG,0,addr DlgProc,0
invoke ExitProcess,NULL
WinMainCRTStartup Endp


end

#include <\UASM64\include\resource.h>
#define    IDC_TEST        3002
#define    IDC_EXIT        3003
#define    IDC_OUTPUT        3004
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
100 DIALOGEX 0,0,290,140, 0
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Process trace demo"
FONT 9, "Consolas", 700, 0
BEGIN
    EDITTEXT IDC_OUTPUT, 2, 2,285, 120,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_BORDER | WS_TABSTOP | WS_VSCROLL
    PUSHBUTTON "Test", IDC_TEST, 2,124,30,14,WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON
    PUSHBUTTON "Exit", IDC_EXIT, 264,124,25,14,WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON
END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
200 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "Amain.ICO"
Say you, Say me, Say the codes together for ever.