Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save fryguy04/0d673f64c386df7903e175b11cfe31e5 to your computer and use it in GitHub Desktop.
Save fryguy04/0d673f64c386df7903e175b11cfe31e5 to your computer and use it in GitHub Desktop.
Improved Sysmon Sentinel Kusto parser - Extracts ProcessName, ParentProcessName, MD5, SHA256, IMPHASH for easier searching.
// KQL Sysmon Event Parser - Customized for SnapAttack use
//
// Heavily based on: https://github.com/Azure/Azure-Sentinel/blob/master/Parsers/Sysmon/Sysmon-AllVersions_Parser.txt
// Usage Instruction :
// Paste below query in log analytics, click on Save button and select as Function from drop down by specifying function name and alias (e.g. Sysmon_Normalized).
// Function usually takes 10-15 minutes to activate. You can then use function alias from any other queries (e.g. Sysmon_Normalized | take 10).
// Reference :
// Using functions in Azure monitor log queries : https://docs.microsoft.com/azure/azure-monitor/log-query/functions
// Tech Community Blog on KQL Functions : https://techcommunity.microsoft.com/t5/Azure-Sentinel/Using-KQL-functions-to-speed-up-analysis-in-Azure-Sentinel/ba-p/712381
//
Event
| where Source == "Microsoft-Windows-Sysmon"
| extend RenderedDescription = tostring(split(RenderedDescription, ":")[0])
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key=tostring(['@Name']), Value=['#text']
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
| extend RuleName = column_ifexists("RuleName", ""), TechniqueId = column_ifexists("TechniqueId", ""), TechniqueName = column_ifexists("TechniqueName", "")
| parse RuleName with * 'technique_id=' TechniqueId ',' * 'technique_name=' TechniqueName
| extend ProcessName = parse_path(tostring(Image)).Filename
| extend ParentProcessName = parse_path(tostring(ParentImage)).Filename
| extend Hashes = extract_all(@"(?P<key>\w+)=(?P<value>[a-zA-Z0-9]+)", dynamic(["key","value"]), tostring(Hashes))
| mv-apply Hashes on (
summarize ParsedHashes = make_bag(pack(tostring(Hashes[0]), tostring(Hashes[1])))
)
| evaluate bag_unpack(ParsedHashes)
// SnapAttack - removed below since it errors out if events don't have these columns return > 1 item
// | project TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId,
// Archived, CallTrace, CommandLine, Company, CreationUtcTime, CurrentDirectory, Description, DestinationHostname, DestinationIp, DestinationIsIpv6, DestinationPort, DestinationPortName,
// Details, EventType, FileVersion, GrantedAccess, Hashes, Image, ImageLoaded, Initiated, IntegrityLevel, IsExecutable, LogonGuid, LogonId, NewThreadId, OriginalFileName,
// ParentCommandLine, ParentImage, ParentProcessGuid, ParentProcessId, PipeName, PreviousCreationUtcTime, ProcessGuid, ProcessId, Product, Protocol, QueryName, QueryResults, QueryStatus,
// RuleName, Signature, SignatureStatus, Signed, SourceHostname, SourceImage, SourceIp, SourceIsIpv6, SourcePort, SourcePortName, SourceProcessGuid, SourceProcessGUID, SourceProcessId,
// SourceThreadId, StartAddress, StartFunction, StartModule, TargetFilename, TargetImage, TargetObject, TargetProcessGuid, TargetProcessGUID, TargetProcessId, TerminalSessionId, User,
// UtcTime, TechniqueId, TechniqueName
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment