Windows.System.WindowsErrorReporting

Parses several Windows Error Reporting (WER) files that contain information about crashed programs.

This can include:

  • evidence historical malware execution that have crashed,
  • unstable executables after being injected into, and
  • loaded DLLs by other executables (eg rundll32.exe and regsvr32.exe)

After Windows 10, Report.wer files in the ProgramData directory also contain a SHA1 hash (similar to Amcache) which can assist investigators tracking down processes that have since been deleted.


name: Windows.System.WindowsErrorReporting
author: Zach Stanford - @svch0st
description: |
   Parses several Windows Error Reporting (WER) files that contain information about crashed programs. 
   
   This can include:
   
    * evidence historical malware execution that have crashed,
    * unstable executables after being injected into, and 
    * loaded DLLs by other executables (eg rundll32.exe and regsvr32.exe)

   After Windows 10, Report.wer files in the ProgramData directory also contain a SHA1 hash (similar to Amcache) which can assist investigators tracking down processes that have since been deleted.

reference:   
    - http://0xdabbad00.com/wp-content/uploads/2014/01/notes_on_wer.pdf
    - https://medium.com/dfir-dudes/amcache-is-not-alone-using-wer-files-to-hunt-evil-86bdfdb216d7

type: CLIENT

sources:
  - name: AppCrashReport
    query: |

        LET files = SELECT FullPath FROM glob(globs=["C:/Users/*/AppData/Local/Microsoft/Windows/WER/*/*/Report.wer",
                                                     "C:/ProgramData/Microsoft/Windows/WER/*/*/Report.wer"])
        
        LET parsed_reports = SELECT * FROM foreach(row=files,
                                                   query={
                                                      SELECT FullPath,
                                                             to_dict(item={
                                                                        SELECT _key,_value 
                                                                        FROM parse_records_with_regex(file=utf16(string=read_file(filename=FullPath)),
                                                                                                    accessor="data",
                                                                                                    regex="(?P<_key>.*)=(?P<_value>.*)\r\n")
                                                                        }
                                                                    ) as Report
                                                      FROM scope()
                                                  })
      
        SELECT timestamp(winfiletime=int(int=Report.EventTime)) as timestamp,
                Report.EventType,
                Report.FriendlyEventName,
                Report.AppName,
                Report.AppPath,
                Report.ApplicationIdentity,
                if(condition=Report.TargetAppId=~'^W', -- Appears non-microsoft apps that have a hash only start with "W".
                    then=strip(string=split(sep='!',string=Report.TargetAppId)[1],prefix='0000'), -- Prefix of 0000 similar th hash format in Amcache
                    else="No hash information") as SHA1,
                Report.OriginalFilename,        
                Report,
                FullPath as ReportFileName
        FROM parsed_reports
        
  - name: WERInternalMetadata
    query: |
    
        LET files = SELECT FullPath FROM glob(globs=["C:/Users/*/AppData/Local/Microsoft/Windows/WER/*/*/*InternalMetadata.xml",
                                                     "C:/ProgramData/Microsoft/Windows/WER/*/*/*InternalMetadata.xml"])
        
        
        LET parsed_reports = SELECT * FROM foreach(row=files,
                                                   query={
                                                      SELECT FullPath, parse_xml(
                                                               accessor='data',
                                                               file=regex_replace(
                                                                    source=utf16(string=Data),
                                                                    re='<[?].+?>',
                                                                    replace='')) AS XML
                                                      FROM read_file(filenames=FullPath)
                                                  })
      
        SELECT  XML.WERReportMetadata.ReportInformation.CreationTime as timestamp,
                XML.WERReportMetadata.ProcessInformation.ImageName as ImageName,
                XML.WERReportMetadata.ProcessInformation.Pid as Pid,
                XML.WERReportMetadata.ProcessInformation.ParentProcess.ProcessInformation.ImageName as ParentImageName,
                XML.WERReportMetadata.ProcessInformation.ParentProcess.ProcessInformation.Pid As ParentPid, 
                XML.WERReportMetadata.ProblemSignatures.EventType as EventType,
                XML.WERReportMetadata.ProblemSignatures.Parameter0 as Parameter0,
                XML,
                FullPath
        FROM parsed_reports

  - name: WERProcessTree
    query: |
    
        LET files = SELECT FullPath FROM glob(globs=["C:/Users/*/AppData/Local/Microsoft/Windows/WER/*/*/*.csv",
                                                     "C:/ProgramData/Microsoft/Windows/WER/*/*/*.csv"])
        
        LET parsed_reports = SELECT * FROM foreach(row=files,
                                                   query={
                                                      SELECT *
                                                      FROM parse_csv(filename=utf16(string=read_file(filename=FullPath)),accessor="data")
                                                  })
      
        SELECT *
        FROM parsed_reports