تتبع حدث التعلم لـ Windows: النظرية والتطبيق

طاب مسائك. في الآونة الأخيرة ، كنت بحاجة للتعامل مع خدمة تتبع Windows. ظهرت هذه الخدمة في Windows 2000 ، ومع ذلك ، كان هناك عدد قليل جدًا من المقالات حول هذه الخدمة على الإنترنت ، لذلك ظهرت فكرة كتابة هذه المقالة. لذا ، لنبدأ!

اليوم سأحاول التحدث عن:

  1. نظرية خدمة تتبع Windows
  2. إنشاء جلسة ETW الخاصة بك
  3. استخدام واجهة برمجة تطبيقات تتبع الأحداث للعمل مع ETW
  4. استخدام tracerpt و xperf للعمل مع ETW

نظرية خدمة تتبع Windows


تتبع الأحداث لنظام التشغيل Windows (ETW) هي خدمة تسمح لك بتلقي الأحداث من واحد أو أكثر من موفري الأحداث في الوقت الفعلي أو من ملف * .etl لفترة زمنية معينة. غير واضح؟ الآن دعونا نكتشف ذلك!

لفهم كيفية عمل ETW ، تحتاج إلى فهم هيكل هذه

صورة

الخدمة.تتضمن بنية ETW 4 عناصر

  1. مقدمي الحدث
  2. المستهلكين الحدث
  3. وحدات تحكم ETW
  4. جلسات ETW (جلسات تتبع الأحداث)

مبدأ العملية على النحو التالي.

يتم تسجيل عدد من موفري الأحداث في النظام ، أي التطبيقات التي يمكنها مشاركة تجاربهم مع جلسات ETW. يوجد أيضًا في هذا النظام عدد معين من جلسات ETW النشطة التي يمكنها استهلاك الأحداث من مزود واحد أو أكثر وتوفيرها للمستخدم إما في الوقت الفعلي أو كتابة جميع الأحداث من الموردين إلى ملف السجل (* .etl). ويسيطر المتحكمون على هذه الحركة كلها.

والآن سننظر في كل عنصر من عناصر الهندسة المذكورة أعلاه بمزيد من التفصيل لفهم مبدأ العمل أخيرًا!

موفرو الأحداث


موفرو الأحداث عبارة عن تطبيقات تحتوي على أدوات تتبع الأحداث. بعد تسجيل الموفر ، يمكن لوحدة التحكم تمكين أو تعطيل تعقب الأحداث في الموفر. يحدد المزود تفسيره للتشغيل أو الإيقاف. عادةً ما يقوم الموفر الممكّن بإنشاء الأحداث ، ولكن الموفر المعطل لا يقوم بذلك. يتيح لك هذا إضافة تتبع الأحداث إلى تطبيقنا دون الحاجة إلى إنشاء أحداث طوال الوقت.

يمكن لمورد واحد مشاركة أحداثه مع جلسات ETW متعددة في وقت واحد.

يتكون كل حدث من عنصرين: رأس وبيانات! يتضمن رأس الحدث معلومات حول الحدث: معرف الموفر ، معرف الحدث ، الطابع الزمني ، إلخ. يتم تحديد بقية البيانات من قبل مزود محدد: يتلقى ETW أي بيانات ويكتبها إلى المخزن المؤقت ، ويتم تعيين تفسيرها إلى مستهلكي المعلومات.
هناك أربعة أنواع رئيسية من الموفرين: مزودي

MOF (الكلاسيكيين)
موفري WPP
استنادًا إلى
مقدمي البيان الظاهر TraceLogging.

يختلف مزودو الأحداث في أنواع الحقول التي يقومون بتخزينها في حمولات الحدث.

يبدو أن مقدمي الأحداث قد تم ترتيبهم. استمر!

وحدات تحكم


وحدة التحكم هي تطبيق مسؤول عن تشغيل جلسة ETW واحدة أو أكثر. هي وحدة التحكم التي تحدد حجم ملف السجل وموقعه ، وتبدأ وتوقف جلسات تتبع الأحداث (جلسات ETW) ، وتسمح لمقدمي الخدمة بتسجيل الأحداث في الجلسة. كما ذكرنا سابقًا ، فإن وحدة التحكم هي التي تتيح لمقدم الخدمة مشاركة أحداثه!

المستهلكون


المستهلكون عبارة عن تطبيقات تستقبل وتعالج الأحداث من جلسة تتبع واحدة أو أكثر في نفس الوقت. يمكن للمستهلكين تلقي الأحداث المخزنة في ملفات السجل أو من الجلسات التي تقدم الأحداث في الوقت الحقيقي. كما نعلم بالفعل ، يمكن أن يكون لجلسة عمل ETW واحدة العديد من الموردين. السؤال الذي يطرح نفسه: هل سيكون هناك ارتباك؟ كيف ترتبط الأحداث من جلسات ETW المختلفة ببعضها البعض؟ يتم فرز الأحداث حسب وقت حدوثها ، أي يقدم النظام الأحداث بترتيب زمني!

جلسات ETW


تسجل جلسات تتبع الأحداث (جلسات ETW) الأحداث من مزود واحد أو أكثر تسمح به وحدة التحكم. كما أن الجلسة مسؤولة عن إدارة المخازن المؤقتة وطردها.

تتبع الأحداث يدعم ما يصل إلى 64 جلسة تتبع الأحداث التي تعمل في وقت واحد. من بين هذه الجلسات ، هناك جلستان لأغراض خاصة. الجلسات المتبقية متاحة للاستخدام العام. دورتان للأغراض الخاصة:

  • جلسة تسجيل عامة
  • جلسة تسجيل نواة NT

تسجل جلسة تتبع حدث Global Logger الأحداث التي تحدث في بداية عملية تمهيد نظام التشغيل ، مثل تلك التي تم إنشاؤها بواسطة برامج تشغيل الأجهزة.
تسجل جلسة تتبع الأحداث NT Kernel Logger أحداث النظام المحددة مسبقًا التي تم إنشاؤها بواسطة نظام التشغيل ، مثل أحداث الإدخال / الإخراج للقرص أو فشل الصفحة.

لذا ، دعونا الآن نمارس!

إنشاء جلسة ETW الخاصة بك


قبل البدء في العمل ، نحتاج إلى معرفة العديد من الأدوات المساعدة ، وهي:

قائمة بالموفرين المتاحين على نظام تشغيل معين

logman query providers

الحصول على معلومات كاملة عن المزود

wevtutil gp < > /ge /gm

قائمة بجميع جلسات ETW النشطة

xperf -loggers

أيضًا ، لعرض الملفات ، من المستحسن أن يكون لديك Notepad ++.

بعد الاطلاع على قائمة الموفرين على جهاز الكمبيوتر الخاص بك (وهناك أكثر من 1000 على Windows 10) ، سنختار أحدهم لجلستنا:

صورة

اخترت Microsoft-Windows-WinINet (تسجل هذه الخدمة جميع إجراءاتنا عند العمل في متصفح Microsoft Edge).

1. Win + R -> compmgmt.msc
2. "الأداء"
3. "مجموعات جامع البيانات"
4. "جلسات تتبع الأحداث"
5. "جديد"
6. "مجموعة جامع البيانات"
7. حدد اسم جامع البيانات
8. "إنشاء يدويًا (متقدم)" (إضافة يدويًا (للخبرة) ")

صورة
9. إضافة اهتمام لنا مزودي كل جلسة
10. حدد الكلمات الرئيسية التي تهمنا في حقل "الكلمات الرئيسية (أي)" - 0xFFFFFFFFFFFFFFFFFF
11. حدد مستوى التسجيل 0xFF
= صورة

12. حدد المسار الذي سيتم فيه حفظ ملف سجل الجلسة
13. حدد " ابدأ مجموعة تجميع البيانات الآن "(" تشغيل مجموعة جامعي البيانات الآن ")

الآن الجلسة التي قمنا بإنشائها. يحتاج Microsoft Edge إلى بعض العمل للحصول على الجلسة لجمع معلومات عنا!

بعد مرور بعض الوقت ، نذهب إلى المكان الذي حفظنا فيه ملف السجل. نقوم بتنفيذ الأمر التالي هناك.

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

بعد تنفيذ هذا الأمر ، سيتم إنشاء 4 ملفات.

صورة

نحن مهتمون حاليًا في dumpfile.xml. يمكنك فتح هذا الملف إما من خلال notepad ++ ، ويمكنك أيضًا القيام بذلك في Excel.

بعد دراسة هذا الملف بعناية ، يمكنك أن ترى أن هذه الجلسة جمعت تقريبًا جميع المعلومات حول حركتنا على الإنترنت !!! يمكنك قراءة المزيد عنها هنا ، نحن ندرس ETW ونستخرج الأرباح .

حسنا ، ونحن نمضي قدما. لقد أنشأنا للتو جلسة مع مزود حدث واحد. تم استلام بيانات الجلسة من ملف السجل. حان الوقت لتشفير!

استخدام واجهة برمجة تطبيقات تتبع الأحداث للعمل مع ETW


على habr هناك مقال مثير للاهتمام ، تم إنشاء Worst API على الإطلاق .

ستجد في هذه المقالة إجابات على العديد من الأسئلة التي ستواجهها على الأرجح عند كتابة الطلبات!

سنقوم بتشفير C ++.

لنبدأ بالأبسط.

تكوين وبدء جلسة تتبع الأحداث


أولاً ، فكر في الفكرة العامة.

لبدء جلسة التتبع ، يجب عليك:

1) تعيين البنية EVENT_TRACE_PROPERTIES

2) بدء الجلسة باستخدام StartTrace
التالي ، وتمكين موفري الحدث

3) تمكين الموفرين باستخدام EnableTrace | EnableTraceEx | EnableTraceEx2
لإيقاف جلسة التتبع ، يجب عليك:

4) قبل إيقاف جلسة التتبع ، يجب عليك تعطيل الموفرين باستخدام EnableTrace | EnableTraceEx | EnableTraceEx2 ، بتمرير EVENT_CONTROL_CODE_DISABLE_PROVIDER

5) استدعاء وظيفة ControlTrace وتمريرها EVENT_TRACE_CONTROL_STOP

في المثال أدناه ، أقوم بإنشاء جلسة تسمى MyEventTraceSession. يسمى ملف السجل في الدليل الحالي WriteThePuth.etl ،

وموفر الحدث هو Microsoft-Windows-Kernel-Process. يمكنك معرفة GUID الخاص به باستخدام

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

كود مباشرة:

#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;
    }
}

سنحلل البرنامج أعلاه بمزيد من التفصيل.

1) تعيين بنية EVENT_TRACE_PROPERTIES

لتكوين جلسة تتبع الأحداث ، يجب عليك استخدام بنية EVENT_TRACE_PROPERTIES لتحديد خصائص الجلسة. يجب أن تكون الذاكرة التي تقوم بتخصيصها لبنية EVENT_TRACE_PROPERTIES كبيرة بما يكفي لتحتوي أيضًا على أسماء جلسات العمل وملفات السجل التي تتبع البنية الموجودة في الذاكرة.

2) ابدأ الجلسة باستخدام StartTrace

بعد تحديد خصائص الجلسة ، اتصل بوظيفة StartTrace لبدء الجلسة. إذا نجحت الوظيفة ، فستحتوي المعلمة SessionHandle على واصف الجلسة ، وستحتوي الخاصية LoggerNameOffset على إزاحة اسم الجلسة.

3) قم بتشغيل الموفرين باستخدام EnableTrace | EnableTraceEx | EnableTraceEx2

لتمكين الموفرين الذين تريد السماح لهم بتسجيل الأحداث في جلستك ، اتصل بوظيفة EnableTrace لتمكين الموفرين الكلاسيكيين ، ووظيفة EnableTraceEx لتمكين الموفرين المستندين إلى البيان. في حالات أخرى - EnableTraceEx2.

4) قبل إيقاف جلسة التتبع ، يجب عليك تعطيل الموفرين باستخدام EnableTrace | EnableTraceEx | EnableTraceEx2 بتمرير EVENT_CONTROL_CODE_DISABLE_PROVIDER

لإيقاف جلسة التتبع بعد جمع الأحداث ، اتصل بوظيفة ControlTrace وقم بتمرير EVENT_TRACE_CONTROL_STOP كرمز التحكم. لتحديد جلسة للتوقف ، يمكنك تمرير واصف جلسة تتبع الأحداث الذي تم الحصول عليه من استدعاء سابق إلى وظيفة StartTrace ، أو اسم جلسة تم بدؤها سابقًا. تأكد من فصل جميع الموفرين قبل إيقاف الجلسة. إذا أوقفت الجلسة قبل إيقاف تشغيل الموفر لأول مرة ، فسوف تقوم ETW بفصل الموفر ومحاولة الاتصال بوظيفة التحكم في استدعاء الموفر. إذا انتهى التطبيق الذي بدأ الجلسة دون فصل الموفر أو استدعاء وظيفة ControlTrace ، فسيظل الموفر قيد التشغيل.

5) لإيقاف جلسة التتبع ، اتصل بوظيفة ControlTrace وقم بتمريرها EVENT_TRACE_CONTROL_STOP

كما رأينا في المثال أعلاه ، فإن استخدام API لتتبع الأحداث ليس أسهل. بناءً على ما تفعله ، يمكنك الاستمرار في كتابة موفري الأحداث أو كتابة مستهلكي الأحداث. ومع ذلك ، فإن هاتين المهمتين ضخمتان للغاية ولن يتم تناولهما في هذه المقالة! يتم إنشاء تعقيد إضافي بواسطة 4 أنواع من موفري الأحداث ، وبالتالي ، 4 خيارات لكتابة الأحداث و 4 خيارات لاستهلاكها. يتم وصف العمل مع واجهة برمجة تطبيقات تتبع الأحداث بتفصيل كبير وجيد على موقع Microsoft الرسمي باستخدام ميزة تتبع الأحداث

بعد العمل لبعض الوقت مع واجهة برمجة تطبيقات تتبع الأحداث ، كان لدي سؤال: هل هناك أي أدوات مساعدة تبسط حياتي؟

استخدام tracerpt و xperf للعمل مع ETW


في هذا الفصل ، لن أعتبر هذه المرافق من وجهة نظر نظرية.

يمكنك استخدام الأمر Tracerpt لتحليل سجلات تتبع الأحداث ، وملفات السجل التي تم إنشاؤها بواسطة مراقب الأداء ، وموفري تتبع الأحداث في الوقت الفعلي. يقوم بإنشاء ملفات التفريغ ، ملفات التقارير ، ومخططات التقارير. تحتوي هذه الأداة المساعدة على عدد كبير من المعلمات ، ولكن "الحد الأدنى" التالي مناسب لبدء العمل

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

الأداة المساعدة xperf.exe هي وحدة تحكم كاملة. وهو يدعم حجج سطر الأوامر لإدارة موفري ETW والجلسات. يمكن أن يطلب المتحكمون حالة الجلسات النشطة حاليًا ويستقبلون قوائم بجميع المزودين المسجلين في النظام. على سبيل المثال ، للحصول على جميع الجلسات النشطة ، استخدم الأمر التالي:

C:\>xperf -loggers

وللحصول على قائمة بجميع مقدمي الخدمة المسجلين في النظام ، استخدم الأمر:

C:\>xperf -providers

وحدات التحكم لديها عدد قليل من الميزات الرئيسية. يمكنهم تحديث الجلسات ومسح المخازن المؤقتة إلى القرص.

هذا كل شئ حتى الان!

لسوء الحظ ، لم أتناول في هذه المقالة عددًا من المشكلات المثيرة للاهتمام (على سبيل المثال ، استهلاك الأحداث في الوقت الفعلي أو العمل مع جلسات ذات أغراض خاصة).

يمكنك أن تقرأ عنه على المواقع التالية:

تتبع الأحداث - وثائق Microsoft الرسمية.
نحن ندرس ETW ونستخلص مزايا
تتبع الأحداث لنظام Windows على الجانب الشرير. ولكن هذه ليست بالضبط
أسوأ واجهة برمجة تطبيقات تم إنشاؤها على الإطلاق

All Articles