Windows.Applications.OfficeMacros.MacroRaptor

This artifact implements OleTools MacroRaptor capability in VQL.

Use as a Hunt or triage capability.


name: Windows.Applications.OfficeMacros.MacroRaptor
author: Matt Green - @mgreen27
description: |
  This artifact implements OleTools MacroRaptor capability in VQL.
  
  Use as a Hunt or triage capability.

reference:
  - http://www.decalage.info/mraptor
  - https://github.com/decalage2/oletools/wiki/mraptor
  
parameters:
  - name: TargetGlob
    default: "C:\\Users\\**\\*.{doc,dot,docx,docm,dotx,dotm,docb,xls,xlt,xlm,xlsx,xlsm,xltx,xltm,xlsb,ppt,pptx,pptm,potx,potm}"
    description: The directory to search for office documents.
  - name: ShowAllDetections
    type: bool
    description: If selected return both Suspicious and non-suspicious.
  - name: UploadDocument
    type: bool
    description: "Upload documents. WARNING: Advised to not use with ShowAllDetections True as this may upload multiple versions of the same document."
  - name: AutoExecRegex
    default: "\\b(?:Auto(?:Exec|_?Open|_?Close|Exit|New)|Document(?:_?Open|_Close|_?BeforeClose|Change|_New)|NewDocument|Workbook(?:_Open|_Activate|_Close|_BeforeClose)|\\w+_(?:Painted|Painting|GotFocus|LostFocus|MouseHover|Layout|Click|Change|Resize|BeforeNavigate2|BeforeScriptExecute|DocumentComplete|DownloadBegin|DownloadComplete|FileDownload|NavigateComplete2|NavigateError|ProgressChange|PropertyChange|SetSecureLockIcon|StatusTextChange|TitleChange|MouseMove|MouseEnter|MouseLeave|OnConnecting))|Auto_Ope\\b"
  - name: WriteRegex
    default: "\\b(?:FileCopy|CopyFile|Kill|CreateTextFile|VirtualAlloc|RtlMoveMemory|URLDownloadToFileA?|AltStartupPath|WriteProcessMemory|ADODB\\.Stream|WriteText|SaveToFile|SaveAs|SaveAsRTF|FileSaveAs|MkDir|RmDir|SaveSetting|SetAttr)\\b|(?:\\bOpen\\b[^\\n]+\\b(?:Write|Append|Binary|Output|Random)\\b)"
  - name: ExecRegex
    default: "\\b(?:Shell|CreateObject|GetObject|SendKeys|RUN|CALL|MacScript|FollowHyperlink|CreateThread|ShellExecuteA?|ExecuteExcel4Macro|EXEC|REGISTER|SetTimer)\\b|(?:\\bDeclare\\b[^\\n]+\\bLib\\b)"

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

    query: |
      -- firstly match regex for macro code of interest
      LET macros = SELECT * FROM foreach(
            row={
                SELECT OSPath,Name,Size,Mtime,Atime,Ctime,Btime FROM glob(globs=TargetGlob)
            },
            query={
                SELECT 
                    OSPath,Name,Size,
                    dict(Mtime=Mtime,Atime=Atime,Ctime=Ctime,Btime=Btime) as Timestamps,
                    dict(
                        AutoExec = if(condition= Code=~AutoExecRegex,
                                then= True,
                                else= False),
                        Write = if(condition= Code=~WriteRegex,
                                then= True,
                                else= False),
                        Execute = if(condition= Code=~ExecRegex,
                                then= True,
                                else= False)
                            ) as MacroDetection,
                    dict(Type=Type,StreamName=StreamName,ModuleName=ModuleName,Code=Code) as MacroCode
                FROM olevba(file=OSPath)
                WHERE Code =~ AutoExecRegex OR Code =~ WriteRegex OR Code=~ ExecRegex
            })
      
      -- determine if suspicious
      LET results = SELECT 
            OSPath,Name,Size,Timestamps,
            if(condition= MacroDetection.AutoExec AND ( MacroDetection.Write OR MacroDetection.Execute ),
                then = True,
                else= False ) as Suspicious,
            MacroDetection,
            MacroCode
        FROM macros
        WHERE if(condition= ShowAllDetections,
            then= True,
            else= Suspicious)
        
      -- upload hits to server
      LET upload_results = SELECT *, upload(file=OSPath) as Upload
        FROM results

      -- output rows
      SELECT *,
        hash(path=OSPath) as Hash
      FROM if(condition= UploadDocument,
            then= { SELECT * FROM upload_results},
            else= { SELECT * FROM results})