Seguimiento de eventos de aprendizaje para Windows: teoría y práctica

Buenas tardes. Recientemente, necesitaba tratar con el servicio de rastreo de Windows. Este servicio apareció en Windows 2000, sin embargo, había muy pocos artículos sobre este servicio en Internet, por lo que apareció la idea de escribir este artículo. ¡Vamos a empezar!

Hoy trataré de hablar sobre:

  1. Teoría del servicio de seguimiento de Windows
  2. Creando su sesión ETW
  3. Uso de API de seguimiento de eventos para trabajar con ETW
  4. Usando tracerpt y xperf para trabajar con ETW

Teoría del servicio de seguimiento de Windows


Event Tracing for Windows (ETW) es un servicio que le permite recibir eventos de uno o más proveedores de eventos en tiempo real o de un archivo * .etl durante un período de tiempo determinado. ¿Poco claro? Ahora vamos a resolverlo!

Para comprender cómo funciona ETW, debe comprender la estructura de este servicio. La

imagen

arquitectura ETW incluye 4 elementos

  1. proveedores de eventos
  2. consumidores de eventos
  3. Controladores ETW
  4. Sesiones ETW (sesiones de seguimiento de eventos)

El principio de funcionamiento es el siguiente.

Varios proveedores de eventos están registrados en el sistema, es decir aplicaciones que pueden compartir sus experiencias con sesiones ETW. Además, en este sistema hay un cierto número de sesiones ETW activas que pueden consumir eventos de uno o más proveedores y proporcionarlos al usuario en tiempo real o escribir todos los eventos de los proveedores en un archivo de registro (* .etl). Y los controladores controlan todo este movimiento.

¡Y ahora consideraremos cada elemento de la arquitectura considerado anteriormente con más detalle para finalmente comprender el principio del trabajo!

Proveedores de eventos


Los proveedores de eventos son aplicaciones que contienen herramientas de seguimiento de eventos. Después de que el proveedor se haya registrado, el controlador puede habilitar o deshabilitar el seguimiento de eventos en el proveedor. El proveedor determina su interpretación de encendido o apagado. Normalmente, un proveedor habilitado genera eventos, pero un proveedor deshabilitado no. Esto le permite agregar seguimiento de eventos a nuestra aplicación sin requerir que genere eventos todo el tiempo.

Un proveedor puede compartir sus eventos con múltiples sesiones ETW a la vez.

Cada evento consta de dos elementos: un encabezado y datos. El encabezado del evento incluye información sobre el evento: identificador de proveedor, identificador de evento, marca de tiempo, etc. Un proveedor específico determina el resto de los datos: ETW recibe los datos y los escribe en el búfer, y su interpretación se asigna a los consumidores de información.
Existen cuatro tipos principales de proveedores: proveedores

MOF (clásicos)
proveedores WPP
basados ​​en los
proveedores de manifiesto TraceLogging.

Los proveedores de eventos difieren en los tipos de campos que almacenan en las cargas útiles de eventos.

Los proveedores de eventos parecen estar resueltos. ¡Siga adelante!

Controladores


Un controlador es una aplicación responsable de la operación de una o más sesiones ETW. Es el controlador el que determina el tamaño y la ubicación del archivo de registro, inicia y detiene las sesiones de seguimiento de eventos (sesiones ETW) y permite a los proveedores registrar eventos en la sesión. Como se mencionó anteriormente, ¡es el controlador el que le permite al proveedor compartir sus eventos!

Los consumidores


Los consumidores son aplicaciones que reciben y procesan eventos de una o más sesiones de rastreo al mismo tiempo. Los consumidores pueden recibir eventos almacenados en archivos de registro o de sesiones que entregan eventos en tiempo real. Como ya sabemos, una sesión ETW puede tener varios proveedores. Surge la pregunta: ¿habrá confusión? ¿Cómo se relacionarán los eventos de las diversas sesiones de ETW? Los eventos se ordenan por el momento en que ocurren, es decir ¡El sistema entrega eventos en orden cronológico!

Sesiones de ETW


Las sesiones de seguimiento de eventos (sesiones ETW) registran eventos de uno o más proveedores que el controlador permite. La sesión también es responsable de administrar y vaciar los buffers.

El seguimiento de eventos admite hasta 64 sesiones de seguimiento de eventos que se ejecutan simultáneamente. De estas sesiones, hay dos sesiones de propósito especial. Las sesiones restantes están disponibles para uso general. Dos sesiones de propósito especial:

  • Sesión de registrador global
  • NT Kernel Logger Session

Una sesión de rastreo de eventos de Global Logger registra eventos que ocurren al comienzo del proceso de arranque del sistema operativo, como los generados por los controladores de dispositivos.
Un Registro de kernel de sesión de seguimiento de eventos de NT registra eventos predefinidos del sistema generados por el sistema operativo, como eventos de E / S de disco o fallas de página.

Entonces, ahora vamos a practicar !!!

Creando su sesión ETW


Antes de comenzar a trabajar, necesitamos conocer varias utilidades, a saber: una

lista de proveedores disponibles en un sistema operativo particular

logman query providers

obtener información completa sobre el proveedor

wevtutil gp < > /ge /gm

lista de todas las sesiones ETW activas

xperf -loggers

Además, para ver archivos, es recomendable tener Notepad ++.

Después de mirar la lista de proveedores en su computadora (y hay más de 1000 en Windows 10), elegiremos uno de ellos para nuestra sesión:

imagen

elegí Microsoft-Windows-WinINet (este servicio registra todas nuestras acciones cuando trabaja en el navegador Microsoft Edge).

1. Win + R -> compmgmt.msc
2. "Rendimiento"
3. "Conjuntos de recopiladores de datos"
4. "Sesiones de seguimiento de eventos"
5. "Nuevo"
6. "Conjunto de recopiladores de datos"
7. Especifique el nombre del recopilador de datos
8. "Crear manualmente (Avanzado)" (Agregar manualmente (para experimentados) ")

imagen
9. Agregar interesante proveedores de EE. UU. por sesión
10. Especifique las palabras clave que nos interesan en el campo "Palabras clave (Cualquiera)" - 0xFFFFFFFFFFFFFFFFFF
11. Especifique el nivel de registro 0xFF
= imagen

12. Seleccione la ruta donde se guardará el archivo de registro de la sesión
13. Seleccione el " Inicie este conjunto de recopiladores de datos ahora "(" Ejecute el grupo de recopiladores de datos ahora ")

Ahora la sesión que creamos funciona. ¡Microsoft Edge necesita algo de trabajo para obtener la sesión para recopilar información sobre nosotros!

Después de que haya pasado un tiempo, vamos al lugar donde guardamos el archivo de registro. Ejecutamos el siguiente comando allí.

tracerpt "   .etl" -o -report -summary -lr

Después de ejecutar este comando, se generarán 4 archivos.

imagen

Actualmente estamos interesados ​​en dumpfile.xml. Puede abrir este archivo a través de Notepad ++, también puede hacerlo en Excel.

¡Después de estudiar cuidadosamente este archivo, puede ver que esta sesión recopiló casi toda la información sobre nuestro movimiento en Internet! Puede leer más sobre esto aquí. Estudiamos ETW y extraemos ganancias .

Bueno, y seguimos adelante. Acabamos de crear una sesión con un único proveedor de eventos. Se recibieron datos de sesión del archivo de registro. ¡Es hora de codificar!

Uso de API de seguimiento de eventos para trabajar con ETW


En habr hay un artículo interesante, la peor API jamás creada .

¡En este artículo encontrará respuestas a muchas preguntas que probablemente tendrá al escribir aplicaciones!

Codificaremos en C ++.

Comencemos con lo más simple.

Configurar e iniciar una sesión de seguimiento de eventos.


Primero, considere la idea general.

Para iniciar una sesión de rastreo, debe:

1) Establecer la estructura EVENT_TRACE_PROPERTIES

2) Iniciar la sesión usando StartTrace
Siguiente, habilitar los proveedores de eventos

3) Habilitar los proveedores usando EnableTrace | EnableTraceEx | EnableTraceEx2
Para detener la sesión de rastreo, debe:

4) Antes de detener la sesión de rastreo, debe deshabilitar los proveedores que usan EnableTrace | EnableTraceEx | EnableTraceEx2, pasando EVENT_CONTROL_CODE_DISABLE_PROVIDER

5) Llame a la función ControlTrace y páselo EVENT_TRACE_CONTROL_STOP

En el siguiente ejemplo, estoy creando una sesión llamada MyEventTraceSession. El archivo de registro en el directorio actual se llama WriteThePuth.etl.

El proveedor de eventos es Microsoft-Windows-Kernel-Process. Puedes encontrar su GUID usando

wevtutil gp Microsoft-Windows-Kernel-Process /ge /gm

Codificar directamente:

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <strsafe.h>
#include <wmistr.h>
#include <evntrace.h>
#include <iostream>
#define LOGFILE_PATH L"WriteThePuth.etl"
#define LOGSESSION_NAME L"MyEventTraceSession"


// GUID,     .
//      GUID .

// {AE44CB98-BD11-4069-8093-770EC9258A12}
static const GUID SessionGuid =
{ 0xae44cb98, 0xbd11, 0x4069, { 0x80, 0x93, 0x77, 0xe, 0xc9, 0x25, 0x8a, 0x12 } };


// GUID,   ,   
//    .

//{22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716} Microsoft-Windows-Kernel-Process
static const GUID ProviderGuid =
{ 0xd22FB2CD6, 0x0E7B, 0x422B, {0xA0, 0xC7, 0x2F, 0xAD, 0x1F, 0xD0, 0xE7, 0x16 } };

void wmain(void)
{
    setlocale(LC_ALL, "ru");
    ULONG status = ERROR_SUCCESS;
    TRACEHANDLE SessionHandle = 0;
    EVENT_TRACE_PROPERTIES* pSessionProperties = NULL;
    ULONG BufferSize = 0;
    BOOL TraceOn = TRUE;

    
    BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGFILE_PATH) + sizeof(LOGSESSION_NAME);
    pSessionProperties = (EVENT_TRACE_PROPERTIES*)malloc(BufferSize);
    if (NULL == pSessionProperties)
    {
        wprintf(L"Unable to allocate %d bytes for properties structure.\n", BufferSize);
        goto cleanup;
    }

    ZeroMemory(pSessionProperties, BufferSize);
    pSessionProperties->Wnode.BufferSize = BufferSize;
    pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    pSessionProperties->Wnode.ClientContext = 1; //QPC clock resolution
    pSessionProperties->Wnode.Guid = SessionGuid;
    pSessionProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;
    pSessionProperties->MaximumFileSize = 1024;  // 1024 MB
    pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
    pSessionProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGSESSION_NAME);
    StringCbCopy((LPWSTR)((char*)pSessionProperties + pSessionProperties->LogFileNameOffset), sizeof(LOGFILE_PATH), LOGFILE_PATH);
    

    status = StartTrace((PTRACEHANDLE)&SessionHandle, LOGSESSION_NAME, pSessionProperties);
    if (ERROR_SUCCESS != status)
    {
        wprintf(L"StartTrace() failed with %lu\n", status);
        goto cleanup;
    }

    //  ,   ,      .

    status = EnableTraceEx2(
        SessionHandle,
        (LPCGUID)&ProviderGuid,
        EVENT_CONTROL_CODE_ENABLE_PROVIDER,
        TRACE_LEVEL_INFORMATION,
        0,
        0,
        0,
        NULL
        );

    if (ERROR_SUCCESS != status)
    {
        wprintf(L"EnableTrace() failed with %lu\n", status);
        TraceOn = FALSE;
        goto cleanup;
    }

    //   .    ,   
    wprintf(L"Run the provider application. Then hit any key to stop the session.\n");
    _getch();
   

cleanup:
    if (SessionHandle)
    {
        if (TraceOn)
        {
            status = EnableTraceEx2(
                SessionHandle,
                (LPCGUID)&ProviderGuid,
                EVENT_CONTROL_CODE_DISABLE_PROVIDER,
                TRACE_LEVEL_INFORMATION,
                0,
                0,
                0,
                NULL
                );
        }

        status = ControlTrace(SessionHandle, LOGSESSION_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP);

        if (ERROR_SUCCESS != status)
        {
            wprintf(L"ControlTrace(stop) failed with %lu\n", status);
        }
    }

    if (pSessionProperties)
    {
        free(pSessionProperties);
        pSessionProperties = NULL;
    }
}

Analizaremos el programa anterior con más detalle.

1) Establecer la estructura EVENT_TRACE_PROPERTIES

Para configurar una sesión de seguimiento de eventos, debe usar la estructura EVENT_TRACE_PROPERTIES para especificar las propiedades de la sesión. La memoria que asigne para la estructura EVENT_TRACE_PROPERTIES debe ser lo suficientemente grande como para contener también los nombres de la sesión y los archivos de registro que siguen la estructura en la memoria.

2) Inicie la sesión usando StartTrace

Después de especificar las propiedades de la sesión, llame a la función StartTrace para iniciar la sesión. Si la función tiene éxito, el parámetro SessionHandle contendrá el descriptor de la sesión y la propiedad LoggerNameOffset contendrá el desplazamiento del nombre de la sesión.

3) Encienda proveedores usando EnableTrace | EnableTraceEx | EnableTraceEx2

Para habilitar los proveedores a los que desea permitir la grabación de eventos en su sesión, llame a la función EnableTrace para habilitar proveedores clásicos y a la función EnableTraceEx para habilitar proveedores basados ​​en manifiesto. En otros casos, EnableTraceEx2.

4) Antes de detener la sesión de rastreo, debe deshabilitar los proveedores que usan EnableTrace | EnableTraceEx | EnableTraceEx2 pasando EVENT_CONTROL_CODE_DISABLE_PROVIDER

Para detener la sesión de rastreo después de recopilar eventos, llame a la función ControlTrace y pase EVENT_TRACE_CONTROL_STOP como código de control. Para especificar que se detenga una sesión, puede pasar el descriptor de sesión de seguimiento de eventos obtenido de una llamada anterior a la función StartTrace, o el nombre de una sesión iniciada previamente. Asegúrese de desconectar a todos los proveedores antes de detener la sesión. Si detiene la sesión antes de apagar el proveedor por primera vez, ETW lo desconectará e intentará llamar a la función de control de devolución de llamada del proveedor. Si la aplicación que inició la sesión finaliza sin desconectar el proveedor o llamar a la función ControlTrace, el proveedor permanece activado.

5) Para detener la sesión de rastreo, llame a la función ControlTrace y pásela EVENT_TRACE_CONTROL_STOP

Como vimos en el ejemplo anterior, usar la API de seguimiento de eventos no es la más fácil. Dependiendo de lo que haga, puede continuar escribiendo proveedores de eventos o escribiendo consumidores de eventos. Sin embargo, ambas tareas son bastante voluminosas y no serán consideradas en este artículo. La complejidad adicional es creada por 4 tipos de proveedores de eventos y, en consecuencia, 4 opciones para escribir eventos y 4 opciones para su consumo. El trabajo con la API de seguimiento de eventos se describe con gran detalle y bien en el sitio web oficial de Microsoft Uso del seguimiento de eventos

Después de trabajar durante un tiempo con la API de seguimiento de eventos, tuve una pregunta: ¿hay alguna utilidad que simplifique mi vida?

Usando tracerpt y xperf para trabajar con ETW


En este capítulo, no consideraré estas utilidades desde un punto de vista teórico.

Puede usar el comando Tracerpt para analizar registros de seguimiento de eventos, archivos de registro generados por el monitor de rendimiento y proveedores de seguimiento de eventos en tiempo real. Crea archivos de volcado, archivos de informes y esquemas de informes. Esta utilidad tiene una gran cantidad de parámetros, pero el siguiente "mínimo" es adecuado para comenzar a trabajar

tracerpt " 1- .etl" ... " n- .etl" -o <   > -report <    > -summary<    > 

La utilidad xperf.exe es un controlador completo. Admite argumentos de línea de comandos para administrar proveedores y sesiones de ETW. Los controladores pueden solicitar el estado de las sesiones activas actualmente y recibir listas de todos los proveedores registrados en el sistema. Por ejemplo, para obtener todas las sesiones activas, use el siguiente comando:

C:\>xperf -loggers

y para obtener una lista de todos los proveedores registrados en el sistema, use el comando:

C:\>xperf -providers

Los controladores tienen algunas características clave más. Pueden actualizar sesiones y vaciar buffers al disco.

¡Eso es todo por ahora!

Desafortunadamente, en este artículo no abordé una serie de cuestiones interesantes (por ejemplo, el consumo de eventos en tiempo real o trabajar con sesiones de propósito especial).

Puede leer sobre esto en los siguientes sitios:

Rastreo de eventos : documentación oficial de Microsoft.
Estudiamos ETW y extraemos los beneficios del
Rastreo de eventos para Windows en el lado malo. Pero esta no es exactamente la
peor API jamás creada

All Articles