4

您好,有人知道如何读取 .evt /.evtx 文件,这些文件是不使用提供的 api 读取的 Windows 事件日志文件,我想使用FILE I/Oapis in读取它们C/C++

或者如何将这些文件转换为.txt,我知道splunk这样做但不确定他们是如何做到的。

4

1 回答 1

9

我可能会迟到但很好,它可以帮助未来的读者:

要使用标准库读取.evt文件(比如说在 C++ 中),您应该了解ELF_LOGFILE_HEADER 结构EVENTLOGRECORD 结构。此外,这里是事件日志文件格式。

现在一切都变得更简单了,您要做的是:

一、声明结构

  1. 日志头结构

    typedef unsigned long ULONG;
    typedef struct _EVENTLOGHEADER {
      ULONG HeaderSize;
      ULONG Signature;
      ULONG MajorVersion;
      ULONG MinorVersion;
      ULONG StartOffset;
      ULONG EndOffset;
      ULONG CurrentRecordNumber;
      ULONG OldestRecordNumber;
      ULONG MaxSize;
      ULONG Flags;
      ULONG Retention;
      ULONG EndHeaderSize;
    } EVENTLOGHEADER, *PEVENTLOGHEADER;  
    
  2. 日志记录结构

    typedef unsigned long DWORD;
    typedef unsigned short WORD;
    typedef struct _EVENTLOGRECORD {
        DWORD Length;
        DWORD Reserved;
        DWORD RecordNumber;
        DWORD TimeGenerated;
        DWORD TimeWritten;
        DWORD EventID;
        WORD  EventType;
        WORD  NumStrings;
        WORD  EventCategory;
        WORD  ReservedFlags;
        DWORD ClosingRecordNumber;
        DWORD StringOffset;
        DWORD UserSidLength;
        DWORD UserSidOffset;
        DWORD DataLength;
        DWORD DataOffset;
    } EVENTLOGRECORD, *PEVENTLOGRECORD;
    

II 让我们阅读!

首先声明一个std::ifstream变量来打开和读取文件(二进制)

using namespace std;
ifstream file;
file.open(fileName,ios::in|ios::binary);

if(file.is_open()){
    _EVENTLOGHEADER logheader;
    _EVENTLOGRECORD logRecord;

    //Reading the header
    file.read((char*)&logheader,sizeof(_EVENTLOGHEADER));

    int startOfLog;
    //Loop on every record
    for(unsigned int numberFile=0;numberFile < logheader.CurrentRecordNumber -1;numberFile++){
        //Save the position
        startOfLog = file.tellg();
        //Read log record
        file.read((char*)&logRecord,sizeof(_EVENTLOGRECORD));

        /*******************************************************
        Here are the other information (section 'Remarks' on the 'EVENTLOGRECORD structure' link 
        ********************************************************/

        //Reading sourcename
        wchar_t buffData;
        wstring SourceName;
        file.read((char*)&buffData,sizeof(wchar_t));
        while(buffData!=_T('\0')){
            SourceName.push_back(buffData);
            file.read((char*)&buffData,sizeof(wchar_t));
        }

        //Reading computer name
        wstring ComputerName;
        file.read((char*)&buffData,sizeof(wchar_t));
        while(buffData!=_T('\0')){
            ComputerName.push_back(buffData);
            file.read((char*)&buffData,sizeof(wchar_t));
        }

        //Sets the position to the SID offset 
        int readCursor = startOfLog + logRecord.UserSidOffset;
        file.seekg(readCursor);

        char * userSid = NULL;
        if(logRecord.UserSidLength != 0)
        {
            userSid = (PCHAR)malloc(logRecord.UserSidLength);
            file.read(userSid,logRecord.UserSidLength); //Reading the sid
            //Here you can work on the SiD (but you need win32 API).If you need it, I could show you how i deal with this sid 
            free(userSid);
        }

        //Sets the position to the Strings offset
        readCursor = startOfLog + logRecord.StringOffset;
        file.seekg(readCursor);
        wstring buffString;
        vector<wstring> allStrings;
        //Reading all the strings
        for(int i=0; i< logRecord.NumStrings; i++) {
            file.read((char*)&buffData,sizeof(wchar_t));
            while(buffData!=_T('\0')){
                buffString.push_back(buffData);
                file.read((char*)&buffData,sizeof(wchar_t));
            }
            allStrings.push_back(buffString);
            buffString.clear();
        }

        //Sets the position to the Data offset
        readCursor = startOfLog + logRecord.DataOffset;
        file.seekg(readCursor);
        unsigned char *Data = (unsigned char *)malloc(logRecord.DataLength*sizeof(unsigned char));
        file.read((char*)Data,logRecord.DataLength); //Lecture des données

        //Sets the position to the end of log offset
        readCursor = startOfLog + logRecord.Length - sizeof(DWORD) ;
        file.seekg(readCursor);
        DWORD length;
        file.read((char*)&length,sizeof(DWORD));

        //Do what you want with the log record

        //Clean before reading next log
        ComputerName.clear();
        SourceName.clear();
        allStrings.clear();
        free(Data);
    }
}

希望它可以帮助某人,

于 2013-05-24T07:48:06.117 回答