【问题标题】:How to read .evtx file using python?如何使用 python 读取 .evtx 文件?
【发布时间】:2017-08-17 17:20:18
【问题描述】:

各位有谁知道如何读取 C:\Windows\System32\winevt\Logs 中带有 .evtx 扩展名的事件日志文件吗? 我已经尝试使用记事本打开它并使用 python 阅读,但记事本说访问被拒绝... 有谁知道该怎么做?提前谢谢..

【问题讨论】:

  • 有一个模块:pypi.python.org/pypi/python-evtx/0.5.0 不妨试试这个
  • 如果访问被拒绝,您确定您在正确的 priv 级别运行脚本吗?例如,除非您先使用 UAC,否则您的右键单击使用记事本打开会以最低权限运行。尝试以管理员身份运行记事本,然后从文件->打开菜单打开文件。你不应该被拒绝访问。

标签: python logging event-log


【解决方案1】:

.evtx 是 Windows 事件日志文件的扩展名。它包含 Microsoft 设计的特殊二进制格式的数据,因此您不能简单地在文本编辑器中打开它。

这些是读取 .evtx 的开源工具,NXLog EE 也可以读取 .evtx 文件。 (免责声明:我隶属于后者)。

【讨论】:

    【解决方案2】:

    这就是您从事件查看器中读取“转发事件”文件的方式。你需要管理员权限,所以我会以管理员身份运行它,但如果你不这样做,它会提示你输入密码。

    import win32evtlog
    import xml.etree.ElementTree as ET
    import ctypes
    import sys
    
    
    def is_admin():
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False
    
    if is_admin():
    
    
        # open event file
        query_handle = win32evtlog.EvtQuery(
            'C:\Windows\System32\winevt\Logs\ForwardedEvents.evtx',
            win32evtlog.EvtQueryFilePath)
    
        read_count = 0
        a = 1
        while a == 1:
            a += 1
            # read 1 record(s)
            events = win32evtlog.EvtNext(query_handle, 1)
            read_count += len(events)
            # if there is no record break the loop
            if len(events) == 0:
                break
    
            for event in events:
                xml_content = win32evtlog.EvtRender(event, win32evtlog.EvtRenderEventXml)
                # parse xml content
                xml = ET.fromstring(xml_content)
    
    
                # xml namespace, root element has a xmlns definition, so we have to use the namespace
                ns = '{http://schemas.microsoft.com/win/2004/08/events/event}'
    
                substatus = xml[1][9].text
    
                event_id = xml.find(f'.//{ns}EventID').text
                computer = xml.find(f'.//{ns}Computer').text
                channel = xml.find(f'.//{ns}Channel').text
                execution = xml.find(f'.//{ns}Execution')
                process_id = execution.get('ProcessID')
                thread_id = execution.get('ThreadID')
                time_created = xml.find(f'.//{ns}TimeCreated').get('SystemTime')
                #data_name = xml.findall('.//EventData')
                #substatus = data_name.get('Data')
                #print(substatus)
    
                event_data = f'Time: {time_created}, Computer: {computer}, Substatus: {substatus}, Event Id: {event_id}, Channel: {channel}, Process Id: {process_id}, Thread Id: {thread_id}'
                print(event_data)
    
                user_data = xml.find(f'.//{ns}UserData')
                # user_data has possible any data
    
          
    
    else:
        ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
    
    input()
    

    【讨论】:

      【解决方案3】:

      我将接受的答案修改如下,使其可重复使用:

      import xml.etree.ElementTree as Et
      import win32evtlog
      from collections import namedtuple
      
      class EventLogParser:
      def __init__(self, exported_log_file):
          self.exported_log_file = exported_log_file
      
      def get_all_events(self):
          windows_events = []
          query_handle = win32evtlog.EvtQuery(str(self.exported_log_file),
              win32evtlog.EvtQueryFilePath | win32evtlog.EvtQueryReverseDirection)
          while True:
              raw_event_collection = win32evtlog.EvtNext(query_handle, 1)
              if len(raw_event_collection) == 0:
                  break
              for raw_event in raw_event_collection:
                  windows_events.append(self.parse_raw_event(raw_event))
          return windows_events
      
      def parse_raw_event(self, raw_event):
          xml_content = win32evtlog.EvtRender(raw_event, win32evtlog.EvtRenderEventXml)
          root = Et.fromstring(xml_content)
          ns =  "{" + root.tag.split('}')[0].strip('{') + "}"
          system = root.find(f'{ns}System')
          event_id = system.find(f'{ns}EventID').text
          level = system.find(f'{ns}Level').text
          time_created = system.find(f'{ns}TimeCreated').get('SystemTime')
          computer = system.find(f'{ns}Computer').text
          WindowsEvent = namedtuple('WindowsEvent',
              'event_id, level, time_created, computer')
          return WindowsEvent(event_id, level, time_created, computer)
      

      【讨论】:

        【解决方案4】:

        我使用“python-evtx”库,你可以使用这个命令安装它:

        • pip install python-evtx

        就我而言,我对阅读“信息”级别的记录不感兴趣。

        import os
        import codecs
        from lxml import etree
        import Evtx.Evtx as evtx
        
        def evtxFile(absolutePath, filenameWithExt, ext, _fromDate, _toDate):
            print("Reading: " + filenameWithExt)
        
            outText = ""
            channel = ""
        
            #read the windows event viewer log and convert its contents to XML
            with codecs.open(tempFilePath, "a+", "utf-8", "ignore") as tempFile:
                with evtx.Evtx(absolutePath) as log:
                    for record in log.records():
                        xmlLine = record.xml()
                        xmlLine = xmlLine.replace(" xmlns=\"http://schemas.microsoft.com/win/2004/08/events/event\"", "")
                        xmlParse = etree.XML(xmlLine)
                        level = parseXMLtoString(xmlParse, ".//Level/text()")
        
                        if not level == "0" and not level == "4":
                            providerName = parseXMLtoString(xmlParse, ".//Provider/@Name")
                            qualifiers = parseXMLtoString(xmlParse, ".//EventID/@Qualifiers")
                            timestamp = parseXMLtoString(xmlParse, ".//TimeCreated/@SystemTime")
                            eventID = parseXMLtoString(xmlParse, ".//EventID/text()")
                            task = parseXMLtoString(xmlParse, ".//Task/text()")
                            keywords = parseXMLtoString(xmlParse, ".//Keywords/text()")
                            eventRecordID = parseXMLtoString(xmlParse, ".//EventRecordID/text()")
                            channel = parseXMLtoString(xmlParse, ".//Channel/text()")
                            computer = parseXMLtoString(xmlParse, ".//Computer/text()")
                            message = parseXMLtoString(xmlParse, ".//Data/text()")
        
                            if level == "1":
                                level = "Critical"
                            elif level == "2":
                                level = "Error"
                            elif level == "3":
                                level = "Warning"
                                        
                            date = timestamp[0:10]
                            time = timestamp[11:19]
                            time = time.replace(".", "")
        
                            _date = datetime.strptime(date, "%Y-%m-%d").date()
                                                
                            if _fromDate <= _date <= _toDate:
        
                                message = message.replace("<string>", "")
                                message = message.replace("</string>", "")
                                message = message.replace("\r\n", " ")
                                message = message.replace("\n\r", " ")
                                message = message.replace("\n", " ")
                                message = message.replace("\r", " ")
                                            
                                outText = date + " " + time + "|" + level + "|" + message.strip() + "|" + task + "|" + computer + "|" + providerName + "|" + qualifiers + "|" + eventID + "|" + eventRecordID + "|" + keywords + "\n"
        
                                tempFile.writelines(outText)
        
            with codecs.open(tempFilePath, "r", "utf-8", "ignore") as tempFile2:
                myLinesFromDateRange = tempFile2.readlines()
                    
            #delete the temporary file that was created
            os.remove(tempFilePath)          
        
            if len(myLinesFromDateRange) > 0:
                createFolder("\\filtered_data_files\\")
                outFilename = "windows_" + channel.lower() + "_event_viewer_logs" + ext
        
                myLinesFromDateRange.sort()
                #remove duplicate records from the list
                myFinalLinesFromDateRange = list(set(myLinesFromDateRange))
                myFinalLinesFromDateRange.sort()
        
                with codecs.open(os.getcwd() + "\\filtered_data_files\\" + outFilename, "a+", "utf-8", "ignore") as linesFromDateRange:
                    linesFromDateRange.seek(0)
                    if len(linesFromDateRange.read(100)) > 0:
                        linesFromDateRange.writelines("\n")
                    linesFromDateRange.writelines(myFinalLinesFromDateRange)
                del myLinesFromDateRange[:]
                del myFinalLinesFromDateRange[:]
            else:
                print("No data was found within the specified date range.")
        
            print("Closing: " + filenameWithExt)
        

        我希望它对您或将来的其他人有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-21
          • 1970-01-01
          • 2020-07-17
          • 2010-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多