阅读.evt /.直接使用Evtx文件

Reading .evt/.evtx files directly

本文关键字:Evtx 文件 evt 阅读      更新时间:2023-10-16

你好,有人知道怎么读。evt/吗?这是Windows事件日志文件读取不使用提供的api,我想在C/C++中使用FILE I/O api读取它们。

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

我可能迟到了,但是,它可以帮助未来的读者,所以:

读取。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;
    

让我们一起读!

首先声明一个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('')){
            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('')){
            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('')){
                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);
    }
}

希望它能帮助别人,