четверг, 3 февраля 2011 г.

EtwEventRegister

а вот например как всем давно известно функция EventRegister является просто forwarded to ntdll!EtwEventRegister. Соотв-но после некоторого анализа ее кода в ntdll можно написать инструмент сомнительной полезности, показывающий какие события зарегистрированы в некотором процессе
Прототип EventRegister (взят из файла evntprov.h):

ULONG
EVNTAPI
EventRegister(
    __in LPCGUID ProviderId,
    __in_opt PENABLECALLBACK EnableCallback,
    __in_opt PVOID CallbackContext,
    __out PREGHANDLE RegHandle
    );

PENABLECALLBACK - указатель на функцию:

typedef
VOID
(NTAPI *PENABLECALLBACK) (
    __in LPCGUID SourceId,
    __in ULONG IsEnabled,
    __in UCHAR Level,
    __in ULONGLONG MatchAnyKeyword,
    __in ULONGLONG MatchAllKeyword,
    __in_opt PEVENT_FILTER_DESCRIPTOR FilterData,
    __in_opt PVOID CallbackContext
    );


В начале EtwEventRegister проверяется, заданы ли EnableCallback и CallbackContext и если да - выделяется структура размером в 2 указателя. Я назвал ее etw_cb_params:

struct etw_cb_params
{
  PVOID           CallbackContext;
  PENABLECALLBACK EnableCallback;
};

Далее вызывается главный метод - EtwNotificationRegister (он же зовется и из EtwRegisterTraceGuidsW), в котором и происходят всякие нужные и полезные вещи. Для начала вызывается RtlEnterCriticalSection(EtwProvCritSect). Далее вызывается EtwpGetNewRegEntry, из которой можно узнать что все зарегистрированные события находятся в массиве указателей EtwpRegList и размер его составляет 0x400 штук. Оттуда же можно вытащить и размер одной RegEntry:
  • под vista 32бита 0xB8 байт
  • под vista 64бита - 0xC8
  • под windows7 32бита 0xD0
  • под windows7 32бита 0xF0 байт
Структуры были отреверсены только до поля с указателем на etw_cb_params - похоже что далее в их телах содержатся только нули. Всегда впрочем возможно что я не прав

struct EtwRegEntry_vista
{
/* Win32 Win64 - offsets */
/*   0x0   0x0 */ GUID  ProviderId;
/*  0x10  0x10 */ PVOID unk1;
/*  0x14  0x18 */ WORD  InUse;
/*  0x18  0x1C */ DWORD Index;
/*  0x1C  0x20 */ PVOID InternalCallback;
/*  0x20  0x28 */ struct etw_cb_params *Params;

/*  0x24  0x30 */ DWORD type;
/*  0xB8  0xC8 - total size */
};

struct EtwRegEntry_w7
{
/* Win32 Win64 - offsets */
/*   0x0   0x0 */ GUID  ProviderId;
/*  0x10  0x10 */ PVOID unk1;
/*  0x14  0x18 */ WORD  InUse;
/*  0x18  0x1C */ DWORD Index;
/*  0x1C  0x20 */ RTL_CRITICAL_SECTION Lock;
/*  0x34  0x48 */ PVOID InternalCallback;
/*  0x38  0x50 */ struct etw_cb_params *Params;

/*  0x3C  0x58 */ DWORD type;
/*  0xD0  0xF0 - total size */
};


type равен 3 если был вызов EtwNotificationRegister из EtwEventRegister и 2 если из EtwRegisterTraceGuidsW.
Собственно это все что нужно знать для написания кода. Приведу примерчик результатов работы на vista 32bit:
InUse 1 Index 0 InternalCB 76F59C3B (C:\Windows\system32\ntdll.dll) Microsoft-Windows-LDAP-Client
EtwCallback[0] 77129FBD C:\Windows\system32\WLDAP32.dll

InUse 1 Index 1 InternalCB 76F48E50 (C:\Windows\system32\ntdll.dll) ProviderId: BDA92AE8-9F11-4D49-BA1D-A4C2ABCA692E

InUse 1 Index 2 InternalCB 76F59C3B (C:\Windows\system32\ntdll.dll) Microsoft-Windows-RPC

InUse 1 Index 3 InternalCB 76F48E50 (C:\Windows\system32\ntdll.dll) ProviderId: CC3DF8E3-4111-48D0-9B21-7631021F7CA6

InUse 1 Index 4 InternalCB 76F48E50 (C:\Windows\system32\ntdll.dll) ProviderId: 07A29C3D-26A4-41E2-856A-095B3EB8B6EF

1 комментарий: