Backing up event logs in their normal binary format

Some time ago I was looking for a way to make backups of the eventlogs of our server, preferably without me ever having to do anything anymore J


This was not success. There are a couple of tools to make text exports from eventlogs. These have the disadvantage that they make the logs very large and unsuitable for looking at with the even viewer. As an added bonus, these are slow too (since every item has to be read individually).


EventQuery.vbs is one of these tools and it is so dog slow that it is almost a crime that it has been included with Windows. Ever wanted to bring a domain controller slow to a crawl? Simple: Use EventQuery.vbs to export the security event log. That’ll do it.


Anyway, I checked with my fellow MVPs, and there is no built-in (or free) tool to save event logs as binary event log files, so I gave up.


But then I accidentally discovered that there is a win32 API that exposes the event log functionality. And as luck would have it, I am a programmer and thus perfectly suited to make such a thing myself. It would have been trivial to make it at work, but I decided to do this at home so that I could share the code.


It is of course perfectly possible that such a free tool exists and I simply didn’t find it.


The code


The code is simple, though the line count was increased by the desire to implement error handling.


int _tmain(int argc, _TCHAR* argv[])
{
  _TCHAR* computerName = NULL;
  _TCHAR* logName = NULL;
  _TCHAR* file = NULL;

  //populate the variables, based on the input arguments
  if(argc == 3)
  {
    computerName = NULL;
    logName = argv[1];
    file = argv[2];
  }
  else if(argc == 4)
  {
    computerName = argv[1];
    logName = argv[2];
    file = argv[3];
  }
  else
  {
    Usage();
    return -1;
  }

  //Open the eventlog
  HANDLE hEventLog = OpenEventLog(computerName, logName);
  if(NULL == hEventLog)
  {
    _tprintf_s(TEXT(“Could not open eventlog %s on computer %s\n”),
      logName, computerName);
    PrintError();
    return -1;
  }

  //backup the event log to file
  if(FALSE == BackupEventLog(hEventLog, file))
  {
    _tprintf_s(TEXT(“Could not save eventlog to file %s\n”), file);
    PrintError();
    CloseEventLog(hEventLog);
    return -1;
  }

  CloseEventLog(hEventLog);
  return 0;
}


There is little to tell about the code. It can be invoked with either 2 or 3 command line arguments:


  • The name of the computer of which the logs have to be backed up. (optional)
  • The name of the event lot to back up
  • The path of the file to which the event log needs to be saved.

The application opens the event log, and then makes the backup and closes the eventlog. If something goes wrong, the error code and error message are printed to the command line.


I thought about making the error handing a little more elegant (so that PrintError and CloseEventlog were not used multiple times in the code) but with only 2 function calls, the amount of error handling code would not diminish or be any better.


I left the PrintError function out of this blog because it doesn’t do anything exciting. It retrieves the error code and prints out the corresponding error message.


What you need to know before using this tool


I’ve been using this tool for a week now, and it is working splendidly, but there are a couple of things that aren’t mentioned in the MSDN documentation of the API.


The first is that the supplied path is absolute for the computer of which you are making an even log backup. So if the path is D:\app.evt, it will make the backup to D:\app.evt on the remote computer.


The second thing you need to know is that providing a UNC name for the target file doesn’t really improve things all that much. Because what is happening under the hood is that it is not you who is making the backup.


The event log service is in charge of the event log files, and you are asking it to make a backup. And that is where it all goes pear shaped. The event log service runs with  LOCAL_SYSTEM credentials. This means that by default, it has no credentials that are valid on a remote computer. So you cannot make backup files in network locations, because the event log service of the remote computer has no privileges to access the location.


There are 2 exceptions to this rule. 1) the remote location is on the remote computer itself. 2) the remote computer is a backup domain controller.


It is a little known fact (I didn’t know it either) that LOCAL_SYSTEM on a domain controller is a domain administrative account that can pretty much do anything and everything on any domain computer, including the things that even a domain admin cannot.


Conclusion


I needed a convenient tool for making backups of event log files, and now I have one. Both the source and the binary are included as attachments. The source is available under the MIT license, and the exes are available for free to do with them what you want, as long as it is understood that whatever you do with them is your responsibility, not mine.


The eventtool_clr exe is something I made to create and delete event logs. I don’t think I blogged about it yet, but what it does is so simple it’s hardly worth mentioning. Have a look at the sources for more info.


The binary is for those who just want to use it and don’t care. The source is for those who’d rather not run an untrusted binary from some guy on the internet on their internal servers J The sources are simple enough to audit and compile.


On a side note, The API to backup event logs is not exposed on the .NET api for event logs. I don’t know exactly why, but I suspect that it is because of the problems I mentioned. The API is confusing enough that it is really not fit for generic use. After all, you can’t backup to remote systems, and the path is absolute for the remote computer.


I also didn’t want a .NET program, because for this type of thing, nothing beats the convenience and performance of a compiled binary that needs no runtime DLLs or external frameworks.


 

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>