Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading .evt/.evtx files directly [closed]

Hello does anybody know how to read .evt /.evtx which are Windows Event log files to read not using provided api's , I want to read them using FILE I/O apis in C/C++.

Or how to convert those files into .txt , I know splunk does this but not sure how they are doing this.

like image 829
Avinash Avatar asked Jan 18 '23 22:01

Avinash


1 Answers

I might be late but well, it could help a future reader so :

To read an .evt file with standard lib (let's say in C++), you should be aware of ELF_LOGFILE_HEADER structure and EVENTLOGRECORD structure. In addition, here is the event log file format.

Now everything is simpler, what you have to do is :

I. Declare structures

  1. Log Header structure

    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. Log Record structure

    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 Let's read !

First declare a std::ifstream variable to open and read the file (binary)

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

Wish it could help someone,

like image 118
Bastien Avatar answered Feb 01 '23 18:02

Bastien