Reputation: 105
I created this saved function in MDE Advanced Hunting (saved as TableToMarkdown
) that is intended to convert ingested query results into markdown language:
let TableToMarkdown = (T:(*)) {
let schema = T | getschema;
let headers = schema | project ColumnName | summarize make_list(ColumnName) | extend String = strcat('| ', strcat_array(list_ColumnName, ' | '), ' |') | project String, Order=1;
let upperDivider = schema | project ColumnName, Sep = '---' | summarize Cols=make_list(Sep) | extend String = strcat('| ', strcat_array(Cols, ' | '), ' |') | project String, Order=2;
let data = T | extend Cols=pack_array(*) | extend String = strcat('| ', strcat_array(Cols, ' | '), ' |') | project String, Order=3;
headers
| union upperDivider
| union data
| order by Order asc
| summarize Rows=make_list(String)
| project array_strcat(Rows, '\r\n')
}
Sample output:
| Timestamp | DeviceName | ActionType | AdditionalFields |
| --- | --- | --- | --- | --- |
| 2024-07-22T01:18:08.0515724Z | MyHostName | UsbDriveMounted | {"DriveLetter":"D:","BusType":7,"ProductName":"CDDVDW GP70N ","ProductRevision":"RR01","SerialNumber":"ABCDEFG123","Manufacturer":"hp","Volume":"\\\\?\\Volume{270-02-11b-92-863}","LoggedOnUsers":["USERNAME"]} |
| 2024-07-22T13:03:57.4174787Z | MyHostName | UsbDriveMounted | {"DriveLetter":"E:","BusType":7,"ProductName":"DVDRAM GP65NB60 ","ProductRevision":"PF00","SerialNumber":"ABCDEFG124","Manufacturer":"HL-DT-ST","Volume":"\\\\?\\Volume{2a0-3d-df3-11-3f4}","LoggedOnUsers":["USERNAME"]} |
The intent is to use it by piping query results into the function, like so:
let Sus_HostName = 'MyHostName';
DeviceEvents
| where DeviceName has Sus_HostName
| where ActionType contains "USB"
| invoke TableToMarkdown()
However, I keep running into this error whenever I run that query, or add | invoke TableToMarkdown()
to any query:
Syntax error
Error message
Expected: ;How to resolve
Fix syntax errors in your queryToken
}Line
1Position
2
The only way I can get the function to work is to store the query as a variable and include the entire function in the query, like so:
let Sus_HostName = 'MyHostName';
let t = DeviceEvents
| where DeviceName has Sus_HostName
| where ActionType contains "USB";
let schema = t | getschema;
let headers = schema | project ColumnName | summarize make_list(ColumnName) | extend String = strcat('| ', strcat_array(list_ColumnName, ' | '), ' |') | project String, Order=1;
let upperDivider = schema | project ColumnName, Sep = '---' | summarize Cols=make_list(Sep) | extend String = strcat('| ', strcat_array(Cols, ' | '), ' |') | project String, Order=2;
let data = t | extend Cols=pack_array(*) | extend String = strcat('| ', strcat_array(Cols, ' | '), ' |') | project String, Order=3;
headers
| union upperDivider
| union data
| order by Order asc
| summarize Rows=make_list(String)
| project array_strcat(Rows, '\r\n')
I'm kinda new to Defender XDR so this is making my head spin. What am I doing wrong or not understanding? For simplicity's sake, I would like to be able to just add | invoke TableToMarkdown()
or something similar to the ends of my queries if at all possible.
Upvotes: 0
Views: 59