Windows.System.AutoLoggerDiagtrackListener

AutoLogger-Diagtrack-Listener.etl is a potential source of evidence of execution and other system diagnostic data.

If AutoLogger-Diagtrack-Listener.etl exists, we use the built-in tracerpt to parse and extract each XML record as a row.

NOTE: A good workflow is running Windows.Search.FileFinder or Yara.Glob targeting strings of interest, then running AutoLoggerDiagtrackListener to parse hits.

ETL Globs:
C:/ProgramData/Microsoft/Diagnosis/ETLLogs/**/*.etl
C:/Windows/System32/LogFiles/**/*.etl
C:/Windows/System32/WDI/**/*.etl


name: Windows.System.AutoLoggerDiagtrackListener
author: Matt Green - @mgreen27
description: |
   AutoLogger-Diagtrack-Listener.etl is a potential source of evidence of 
   execution and other system diagnostic data.
   
   If AutoLogger-Diagtrack-Listener.etl exists, we use the built-in tracerpt to 
   parse and extract each XML record as a row.
   
   NOTE: A good workflow is running Windows.Search.FileFinder or Yara.Glob 
   targeting strings of interest, then running AutoLoggerDiagtrackListener to 
   parse hits.
   
   ETL Globs:    
      `C:/ProgramData/Microsoft/Diagnosis/ETLLogs/**/*.etl`   
      `C:/Windows/System32/LogFiles/**/*.etl`   
      `C:/Windows/System32/WDI/**/*.etl`   

reference:
    - https://www.fortinet.com/blog/threat-research/uncovering-hidden-forensic-evidence-in-windows-mystery-of-autologger
    
type: CLIENT

parameters:
   - name: TargetGlob
     default: C:\\ProgramData\\Microsoft\\Diagnosis\\ETLLogs\\AutoLogger\\AutoLogger-Diagtrack-Listener.etl
   - name: EventNameRegex
     default: .
     description: Regex to filter on EventName - E.g ProcessStarted
   - name: EventDataRegex
     default: .
     description: Regex to filter rows returned on EventData

required_permissions:
    - EXECVE 
    - FILESYSTEM_WRITE 
sources:
  - precondition:
      SELECT OS From info() where OS = 'windows'

    query: |
       LET out_folder <= tempdir(remove_last=true)
       
       LET target_files = SELECT
           OSPath,
           Size,
           Mtime,
           Btime,
           path_join(components=[out_folder, str(str=count()) + "parsed_etl.xml"],
                     path_type='windows') AS ParsedOutput
         FROM glob(globs=TargetGlob)
       
       LET parse_etl(path, out) = SELECT *
         FROM execve(argv=['cmd.exe', '/c', 'tracerpt', path, '-o', out, '-y'])
       
       LET run_parser <= SELECT *
         FROM foreach(row=target_files,
                      query={
           SELECT OSPath,
                  ParsedOutput,
                  *
           FROM parse_etl(path=OSPath, out=ParsedOutput)
           WHERE Stdout =~ 'The command completed successfully.'
         })
       
       LET event_records = SELECT *
         FROM foreach(row=run_parser,
                      query={
           SELECT parse_xml(accessor='data', file=Record) AS Parsed,
                  OSPath
           FROM parse_records_with_regex(file=ParsedOutput,
                                         regex='(?s)(?P<Record><Event .*?</Event>)')
         })
       
       SELECT
           Parsed.Event.System.TimeCreated.AttrSystemTime AS EventTime,
           Parsed.Event.System.Provider.AttrName AS Provider,
           Parsed.Event.RenderingInfo.Task || Parsed.Event.RenderingInfo.Opcode AS EventName,
           Parsed.Event.System.Execution.AttrProcessID AS SourcePid,
           Parsed.Event.System.EventID AS EventID,
           if(
             condition=Parsed.Event.EventData.Data,
             then=to_dict(
               item={
           SELECT
           AttrName AS _key,
           `#text` AS _value
           FROM Parsed.Event.EventData.Data
         }),
             else=Parsed.Event.EventData) AS EventData,
           OSPath
       FROM event_records
       WHERE EventName =~ EventNameRegex
        AND EventData =~ EventDataRegex