1 问题描述
Windows操作系统日志在工控机的故障排查中起着重要的作用,联锁既有项目的很多车站工控机仍然采用的XP甚至2000系统。由于在NT/Win2000/XP/Server 2003版本的操作系统中,操作系统日志是.evt格式;在Vista/Win7/Win8//Win10/Server 2008/Server 2012等版本的操作系统中,操作系统日志升级为.evtx格式,两种格式并不通用。所以,当现场拷贝回来.evt格式的操作系统日志时,除非有对应的虚拟机,否则在WIN7/10中打开.evt格式的日志时,日志的时间无法被正确解析。
在众多的记录中如果没有时间,我们将无法进一步定位故障。当然你可以让考日志的人拷贝的时候就转存为TXT格式日志,但是如果日志仅有.evt格式时,我们尝试采用如下几种方法来解决这个问题。
2 Log Parser
Log Parser是微软出品的、功能强大、用途广泛的日志分析工具,它可以分析基于文本的数据(如日志文件、XML文件、CSV文件),以及Windows操作系统的关键数据源(如事件日志、注册表、文件系统和 Active Directory®)。下载地址:
Download Log Parser 2.2 from Official Microsoft Download Center
具体用法可以搜索相关文档。
2.1 WIN7系统中的使用
Log Parser安装后,可以在命令行进入默认的安装地址,使用如下命令将操作系统日志转存为CSV格式文件:
如下命令可以将本机路径下的Application.evtx,System.evtx等文件进行转存
LogParser -o:CSV "SELECT * INTO D:\System.csv FROM System"
也可以使用如下命令对离线文件进行转存:
LogParser -i:EVT -o:CSV "SELECT * INTO D:\SYS.csv FROM D:\SYS.evtx"
但是当你对.evt格式的文件进行转存的时候,会给出“事件日志文件损坏”的报错信息:
LogParser -i:EVT -o:CSV "SELECT * INTO D:\xt.csv FROM D:\xt.evt"
2.2 WINXP系统中的使用
Log Parser安装后,采用相同的命令对.evt格式的文件进行转存,可以正常完成。
不过,XP的系统都有了,可以直接使用系统的事件查看器查看.evt格式的日志,再使用Log Parser的必要性也不高了,所以前面遇到的问题还是无法解决。
3 Python的pywin32库和Evtx库
3.1 pywin32库
pywin32库的win32evtlog模块提供的OpenBackupEventLog函数可以读取离线的日志文件。通过测试发现该方法仍然只能打开.evtx文件,.evt文件打开会报错:
import win32evtlog
path = r'D:\xt.evt'
win32evtlog.OpenBackupEventLog(None, f'{path}')
报错信息如下:
3.2 Evtx库
Evtx库只能解析.evtx格式的文件,如果需要对WIN7/WIN10等本地操作系统日志进行监控时,使用该库是一个不错的选择,详细介绍见主页(https://github.com/williballenthin/python-evtx)。但是这个库无法解析.evt文件。
4 EVT文件解析
当前面的方法都没办法解决我们的问题时,我们可以尝试对.evt文件的二进制格式直接进行解析。.evt文件格式描述可以参考如下文档:
一个evt文件主要包括三部分,分别是:
- 文件头
- 事件记录
- 文件尾
4.1 文件头
文件头的详细格式参考前面网页文档的2. File header部分(也可以参考windows主页的介绍:https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb309024(v=vs.85)),其中需要关注的两个点是:
- 文件头部长度固定:48 bytes
- 文件头部标志位固定:0x654c664c
4.2 文件尾
文件尾的详细格式参考前面网页文档的4. End of file record部分(也可以参考windows主页的介绍:https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb309022(v=vs.85)),其中需要关注的几个点是:
- 文件尾部长度固定:40 bytes
- 文件尾部标志位固定:有四个,分别是:0x11111111,0x22222222,0x33333333,0x44444444
4.3 事件记录
每条事件记录的详细格式参考前面网页文档的3. Event record部分(也可以参考windows主页的介绍:https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-eventlogrecord)。
对于每条事件记录,可以参考XP系统事件查看器中的单条事件的各个属性进行提取。
其中各个字段的含义如下:
- Creation date and time:长度 4 bytes,UTC格式。这个时间是事件的发生时间,还有一个Last written date and time是这条事件记录到日志文件的时间。一般情况下两个时间是相同的。
- Source name: 长度不固定,以0x0000结尾,按照大端在后格式编码的一组字符。
- Event category:长度 2 bytes,主要用在Security event log
- Event type:长度 2 bytes,事件的级别,分别是:错误,警告,信息,审核成功,审核失败。
- Event identifier:长度 4 bytes,其中2 bytes是具体的ID值。可以通过该ID号进一步确认该事件产生的原因,比如经常看到的6005,6006,6009。
- User SID:长度不固定,当User identifier (SID) size字段大于0的时候,该字段才存在。该字段是用户的安全标识符,是标识用户、组和计算机帐户的唯一的号码。详细格式解析参考网页:https://github.com/libyal/libfwnt/wiki/Security-Descriptor
- Computer name: 长度不固定,以0x0000结尾,按照大端在后格式编码的一组字符。
- Event strings:长度不固定,当Number of strings字段大于0的时候存在,可以通过Event strings offset字段定位起始位置。该字段中可能存在多个Event string,每个Event string都以0x0000结尾,按照大端在后格式编码的一组字符。这些字段是组成事件消息描述内容的一部分,如果要获取详细的消息内容需要查看注册表的相关属性中指定的消息文件中。
- Event data:长度不固定,当Event data size字段大于0的时候存在,可以通过Event data offset字段定位起始位置。该字段信息是特定事件的详细信息记录。操作系统的事件查看器并不解析此数据,但是可以根据不同Event ID存在不同的解析格式。(https://learn.microsoft.com/zh-cn/windows/win32/api/winnt/ns-winnt-eventlogrecord)
除以上字段外还有其他有用的字段如下:
- 每条事件记录的标志位固定:0x654c664c
- 每条事件记录的序号字段:Record number字段(长度 4 bytes)
- 每条时间记录的长度字段:Size字段(长度 4 bytes),同时出现在每条事件记录信息的开始4 bytes和结束的4 bytes。