Last active
July 18, 2023 22:52
-
-
Save gormaniac/67ddddf4df879b171f082383cd0dc780 to your computer and use it in GitHub Desktop.
Yield results of a storm query that are passed through an arbitrary query filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Just the example code, without comments. | |
$filter="-#test.tag" | |
$start="{ it:app:yara:rule=$rule | " | |
$end=" return($node) }" | |
$instruction=$lib.str.concat($start, $filter, $end) | |
$rules=$lib.list() | |
it:app:yara:rule:enabled=true | | |
$rules.append($node.value()) | | |
spin | | |
fini { | |
for $rule in $rules { | |
yield $lib.storm.eval($instruction) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This example works on it:app:yara:rule nodes. It will need some tweaks to work with other node types. | |
// | |
// The general principal of execution is: | |
// 1. Build a subquery that will be executed for each node that the initial query lifts via an "eval" call | |
// - This subquery expects to have a variable available to its runtime that provides a method to lift the necessary node | |
// - In our example, this variable is "$rule" and it points to a GUID for each it:app:yara:rule lifted by our initial query | |
// 2. Create a list to store all GUIDs (or $node.values) of each node returned by our initial query. | |
// 3. Execute our initial query to lift all the nodes we care about into the pipeline. | |
// 4. Pipe these nodes to a Storm expression that adds the return of "$node.value()" for each node in the pipeline to our GUID list from earlier. | |
// 5. Pipe again to a "spin" command to drop all of the nodes lifted by our initial query. | |
// 6. Declare a "fini" block that will run once all nodes are through the initial pipeline as described up to this step. | |
// This block loops over all GUIDs we saved earlier and passes each GUID to the subquery we created in Step 1. | |
// | |
// The rules for the subquery are quite strict. It must return only 0 or 1 nodes, it cannot return more. This is a limitation | |
// of the "eval" call this code relies on. This is why we have to wait until all nodes are lifted and their values are stored | |
// until we re yield the nodes individually. | |
// Change this var to the user supplied filter. It can be any arbitrary Storm query that only expects to yield 0-1 nodes. | |
$filter="-#test.tag" | |
// This is the first part of your query that is inserted before the filter. | |
$start="{ it:app:yara:rule=$rule | " | |
// This is the part of the query after the filter. Y | |
$end=" return($node) }" | |
// This is the full instruction with start filter and end joined together. You can dynamically build this any other way as well. | |
$instruction=$lib.str.concat($start, $filter, $end) | |
// Stores the GUIDs of all it:app:yara:rules returned by our initial query | |
$rules=$lib.list() | |
// Run the initial query | |
it:app:yara:rule:enabled=true | | |
// Append the GUID to our list | |
$rules.append($node.value()) | | |
// Spin to drop all the nodes lifted by our original query | |
spin | | |
// | |
fini { | |
for $rule in $rules { | |
yield $lib.storm.eval($instruction) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A solution was shared with me that will actually perform the filter of the initial query lift as each node is lifted: