Cześć
Moim zadaniem jest stworzenie aplikacji pod system Windows wykorzystujący ETW (Event Tracing for Windows). Dokładnie muszę napisać konsumenta zdarzeń, przyjmujący i przetwarzający je w czasie rzeczywistym. Jako dostawcę zdarzeń chcę wykorzystać systemowy ‘Microsoft Windows Security Auditing’.
Stworzyłem prostą aplikację będącą, w nomenklaturze ETW, kontrolerem i konsumentem jednocześnie. Bazowałem na przykładach stąd http://msdn.microsoft.com/en-us/library/windows/desktop/ee441324%28v=vs.85%29.aspx i stąd http://msdn.microsoft.com/en-us/library/windows/desktop/ee441325%28v=vs.85%29.aspx zmieniając zasadniczo tylko flagi odpowiedzialne za włączenie przetwarzania w trybie czasu rzeczywistego.
Z uwagi, że na razie chcę uruchomić cokolwiek, wszystko jest robione w funkcji main, która wygląda tak:
LPTSTR SessionName = L"hahahaaa";
ULONG status = ERROR_SUCCESS;
PEVENT_TRACE_PROPERTIES pSessionProperties = NULL;
EVENT_TRACE_LOGFILE trace;
TRACEHANDLE hTrace = 0;
TRACEHANDLE hSession = 0;
const GUID providerId = { 0x54849625, 0x5478, 0x4994, { 0xA5, 0xBA, 0x3E, 0x3B, 0x03, 0x28, 0xC3, 0x0D } };
//const GUID providerId = { 0xA68CA8B7, 0x004F, 0xD7B6, { 0xA6, 0x98, 0x07, 0xE2, 0xDE, 0x0F, 0x1F, 0x5D } };
HANDLE hToken = NULL;
HANDLE hProcess = NULL;
hProcess = GetCurrentProcess();
if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == FALSE) {
printf("Error: Couldn't open the process token\n");
goto cleanup;
}
if(!SetPrivilege(hToken, SE_SECURITY_NAME, TRUE)) goto cleanup;
if (!pSessionProperties) {
const size_t buffSize = sizeof(EVENT_TRACE_PROPERTIES)+(_tcslen(SessionName) + 1) * sizeof(TCHAR);
pSessionProperties = reinterpret_cast<EVENT_TRACE_PROPERTIES *>(malloc(buffSize));
ZeroMemory(pSessionProperties, buffSize);
pSessionProperties->Wnode.BufferSize = buffSize;
pSessionProperties->Wnode.ClientContext = 1;
pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pSessionProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
}
// Create the trace session.
status = StartTrace(&hSession, SessionName, pSessionProperties);
if (ERROR_SUCCESS != status) {
wprintf(L"StartTrace() failed with %lu\n", status);
goto cleanup;
}
status = EnableTraceEx2(hSession, &providerId, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, NULL);
if (ERROR_SUCCESS != status) {
wprintf(L"EnableTrace() failed with %lu\n", status);
goto cleanup;
}
ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILE));
trace.LogFileName = NULL;
trace.LoggerName = SessionName;
trace.CurrentTime = 0;
trace.BuffersRead = 0;
trace.BufferSize = 0;
trace.Filled = 0;
trace.EventsLost = 0;
trace.Context = NULL;
trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)(ProcessEvent);
hTrace = OpenTrace(&trace);
if (INVALID_PROCESSTRACE_HANDLE == hTrace)
{
wprintf(L"OpenTrace failed with %lu\n", GetLastError());
goto cleanup;
}
status = ProcessTrace(&hTrace, 1, 0, 0);
if (status != ERROR_SUCCESS && status != ERROR_CANCELLED)
{
wprintf(L"ProcessTrace failed with %lu\n", status);
goto cleanup;
}
W punkcie aplikacji gdzie nadchodzące zdarzenia są przetwarzanie przez funkcję ‘ProcessTrace()’ program powinien wypisać na standardowe wyjście metadane każdego odebranego zdarzenia albo czekać na kolejne zdarzenia. Niestety nic a nic się nie dzieje, jedynie znak zachęty ‘zachęcająco’ sobie miga. Wszystkie zdarzenia wygenerowane przeze mnie (np. włączyłem Szczegółowe śledzenie - Inspekcja tworzenia procesu, i uruchomiłem dowolną aplikację) są zapisywane i wyświetlane w Dzienniku Zdarzeń, ale w moim programie niestety nic się nie dzieje.
Pierwszą rzecz na jaką wpadłem to problem z brakiem odpowiednich uprawnień. Używając tego przykładu http://msdn.microsoft.com/en-us/library/windows/desktop/aa446619%28v=vs.85%29.aspx ustawiłem w aplikacji uprawnienie ‘SE_SECURITY_NAME’ no i oczywiście uruchomiłem aplikację z uprawnieniami administratora. Nic to jednak nie dało.
Drugą rzeczą jaką spróbowałem była zmiana nazwy sesji. Pomyślałem, że może być podobnie jak z ‘Windows Kernel Trace’ który może logować zdarzenia jedynie do sesji systemowej o nazwie ‘NT Kernel Logger’. Jedynie co znalazłem w sieci to fakt, że ‘Microsoft Windows Security Auditing’ jest powiązany z sesją systemową ‘EventLog-Security’. Gdy ustawiałem nazwę sesji na taką otrzymywałem błąd ‘Access Denied’. Po przejrzeniu wszystkich dostępnych uprawnień nie znalazłem niczego co w tym kontekście miałoby jeszcze sens i nie za bardzo wiem jakie jeszcze uprawnienie powinienem nadać.
Ostatnią rzeczą jaką spróbowałem było wykorzystanie windowsowego narzędzia ‘logman’ za pomocą którego zbierałem zdarzenia i zapisywałem do pliku. Jednak sytuacja wyglądała podobnie. Kiedy ustawiałem nazwę sesji na ‘EventLog-Security’ otrzymywałem błąd ‘Access Denied’. Z drugiej strony, gdy podałem inną nazwę sesji, jedynie co zapisywało się do pliku było zdarzenie dostarczone przez ‘MSNT_SystemTrace’, który jest klasą abstrakcyjną dla innych zdarzeń i które jest zawsze zapisywanie w pliku *.etl, na jego początku.
Jeżeli zmienię dostawcę na np. ‘Microsoft Windows Kernel General’ (zakomentowany GUID) i wygeneruję dowolne zdarzenie (np. zaktualizuję zegar systemowy) wszystko działa jak należy (zarówno w mojej aplikacji jak i za pomocą ‘logman’).
Pracuję na Windows 7 Professional x64 i Visual Studio Ultimate 2013.
Moje pytanie brzmi: co mam zrobić by móc odbierać zdarzenia od ‘Microsoft Windows Security Auditing’?
Z góry serdecznie dziękuję za wszelką pomoc i sugestie