目标要求:对Windows系统日志进行处理,并生成统计文件
1. 如何找到Windows系统日志?
通常情况下,我们都是在Windows系统自带的事件查看器查看系统日志(使用 win + x 可以快速找到事件查看器)。所有系统日志都存在C:\Windows\System32\winevt\Logs
目录中。这里我们采用Setup日志
(即Setup.evtx
),然后将这个文件拷贝到工作目录。
2. 查看日志的主要结构
通过事件查看器,我们可以简单了解每条日志包含的信息。如图是该条日志的常规信息,然后我们切换到详细信息
如图,详细信息分为友好视图、XML视图。可见它包含了System和Userdata两个数据块
切到XML视图,我们发现内部结构是这样的,接下来的工作就是要提取我们需要的字段了
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider
Name="Microsoft-Windows-Servicing" Guid="{bd12f3b8-fc40-4a61-a307-b7a013a069c1}" />
<EventID>2</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>1</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2022-11-19T15:15:05.7275237Z" />
<EventRecordID>323</EventRecordID>
<Correlation />
<Execution ProcessID="3628" ThreadID="3820" />
<Channel>Setup</Channel>
<Computer>DESKTOP-P16J0BP</Computer>
<Security UserID="S-1-5-18" />
</System>
<UserData>
<CbsPackageChangeState
xmlns="http://manifests.microsoft.com/win/2004/08/windows/setup_provider">
<PackageIdentifier>KB5015684</PackageIdentifier>
<IntendedPackageState>5112</IntendedPackageState>
<IntendedPackageStateTextized>Installed</IntendedPackageStateTextized>
<ErrorCode>0x0</ErrorCode>
<Client>UpdateAgentLCU</Client>
</CbsPackageChangeState>
</UserData>
</Event>
3. 正式处理文件
首先,先导入需要的包,这里使用了python-extv
库处理.evtx
文件,用Python
内置的xml
库。使用mmap
申请内存块、contextlib
用于上下文处理,openpyxl
处理excel
文档
import mmap
import contextlib
import openpyxl
from Evtx.Evtx import FileHeader
from Evtx.Views import evtx_file_xml_view
from xml.dom import minidom
然后开始写处理函数func()
。EvtxPath
是要处理的 evtx
文件路径,然后用只读方法打开文件。使用上下文处理器contextlib.closing
管理文件,并使用mmap.mmap
方法将文件映射到内存中。查看python-evtx
的源码,发现Evtx.Views.evtx_file_xml_view
方法是返回两个参数:文档字符串record_str
,地址record
。
def func():
EvtxPath = "E:\desktop\test\Setup.evtx"
with open(EvtxPath, 'r') as f:
with contextlib.closing(
mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)) as buf:
p = FileHeader(buf, 0)
for xml, record in evtx_file_xml_view(p):
xmldoc = minidom.parseString(xml)
root_node = xmldoc.documentElement
def evtx_file_xml_view(file_header):
"""
Generate XML representations of the records in an EVTX file.
Does not include the XML <?xml... header.
Records are ordered by file_header.chunks(), and then by chunk.records()
Args:
chunk (Evtx.FileHeader): the file header to render.
Yields:
tuple[str, Evtx.Record]: the rendered XML document and the raw record.
"""
for chunk in file_header.chunks():
for record in chunk.records():
record_str = evtx_record_xml_view(record)
yield record_str, record
然后使用xml.dom.mindom
方法读取这个xml串,并用documentElement
方法获取xml的根结点
关于xml的操作参考
https://www.runoob.com/dom/prop-document-xmlversion.html
https://blog.csdn.net/m0_37102093/article/details/109622710
然后根据需求,使用getElementsByTagName
方法提取需要的结点即可
4. 补充和拓展
解析完,我们发现竟然没有事件摘要,我查阅了很多资料但没得到解决。如果想要获取事件摘要,可以在Windows事件查看器中将文件导出为XML文件
如何解析XML文件呢?思路和前边一致,我就直接粘贴代码了,如下:
import openpyxl
from xml.dom import minidom
def Func():
EvtxPath = "E:\desktop\Setup.xml"
xmldoc = minidom.parse(EvtxPath)
root_node = xmldoc.documentElement
# 事件
Message_node_list = root_node.getElementsByTagName('Message')
Message_list = []
for Message_node in Message_node_list:
Message_list.append(Message_node.firstChild.nodeValue)
# 时间
TimeCreated_node_list = root_node.getElementsByTagName('TimeCreated')
TimeCreated_list = []
for TimeCreated_node in TimeCreated_node_list:
TimeCreated_list.append(TimeCreated_node.getAttribute('SystemTime'))
# Provider
Provider_node_list = root_node.getElementsByTagName('Provider')
Provider_list = []
for Provider_node in Provider_node_list:
if Provider_node.firstChild is not None:
Provider_list.append(Provider_node.firstChild.nodeValue)
else:
Provider_list.append(Provider_node.firstChild)
# PC name
Computer_node_list = root_node.getElementsByTagName('Computer')
Computer_list = []
for Computer_node in Computer_node_list:
Computer_list.append(Computer_node.firstChild.nodeValue)
# Security user_id
Security_node_list = root_node.getElementsByTagName('Security')
Security_list = []
for Security_node in Security_node_list:
Security_list.append(Security_node.getAttribute('UserID'))
writer = openpyxl.load_workbook('E:\desktop\out2.xlsx')
sheet = writer['Sheet1']
sheet.append(['事件', '时间', '服务提供者', '服务主机', 'Security user_id'])
for i in range(len(Message_list)):
temp = [
Message_list[i], TimeCreated_list[i], Provider_list[i], Computer_list[i],Security_list[i]
]
sheet.append(temp)
writer.save('E:\desktop\out2.xlsx')
Func()
然后查看生成文件: