diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..7bbc60b --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include src/stormlibpp/*/storm/ *.storm README.md \ No newline at end of file diff --git a/Makefile b/Makefile index 236ca93..1408e27 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ change-version: # Change the version of this project (requires VERSION=#.#.#) .PHONY: build build: # Build the package tarball and wheel pipenv run python3 -m build . + pipenv run python3 scripts/build_stix_conf.py .PHONY: setup setup: # Setup this project's pipenv environment diff --git a/data/stix_import_conf.json b/data/stix_import_conf.json new file mode 100644 index 0000000..0ed71bb --- /dev/null +++ b/data/stix_import_conf.json @@ -0,0 +1,167 @@ +{ + "addbundle": true, + "bundle": { + "storm": "it:sec:stix:bundle:id=$bundle.id\nreturn($node)\n[ it:sec:stix:bundle=* :id=$bundle.id ]\n$node.data.set(stix:bundle, $object)\nreturn($node)" + }, + "objects": { + "artifact": { + "storm": "// TODO - Figure out what these look like." + }, + "attack-pattern": { + "storm": "// TODO - Figure out what these look like." + }, + "autonomous-system": { + "storm": "// TODO - Make sure value is the right key for this\n[inet:as=$object.value]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "campaign": { + "storm": "[ ou:campaign=(stix, campaign, $object.id)\n :name?=$object.name\n :desc?=$object.description\n .seen?=$object.last_seen\n .seen?=$object.first_seen\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "course-of-action": { + "storm": "[ risk:mitigation=(stix, course-of-action, $object.id)\n :name?=$object.name\n :desc?=$object.description\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "directory": { + "storm": "// TODO - Figure out what these look like." + }, + "domain-name": { + "storm": "// TODO - Make sure value is the right key for this\n[inet:fqdn=$object.value]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "email-addr": { + "storm": "// TODO - Make sure value is the right key for this\n[inet:email=$object.value]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "email-message": { + "storm": "// TODO - Figure out what these look like." + }, + "file": { + "storm": "if ($object.hashes != $lib.null) {\n ($ok, $hash) = $lib.trycast(file:bytes, $object.hashes.\"SHA-256\")\n if $ok {\n $guid = `sha256:{$hash}`\n } else {\n $guid = `guid:{$lib.guid(stix, file, $object.id)}`\n }\n [\n file:bytes=$guid\n :size?=$object.size\n :name?=$object.name\n :md5?=$object.hashes.\"MD5\"\n :sha1?=$object.hashes.\"SHA-1\"\n :sha256?=$object.hashes.\"SHA-256\"\n :sha512?=$object.hashes.\"SHA-512\"\n ]\n // TODO - Do something with windows-pebinary-ext extension\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n $node.data.set(stix:object, $object)\n return($node)\n}" + }, + "grouping": { + "storm": "// TODO - Figure out what these look like." + }, + "identity": { + "storm": "switch $object.identity_class {\n group: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]}\n organization: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]}\n individual: {[ ps:contact=(stix, identity, $object.id) :name?=$object.name ]}\n system: {[ it:host=(stix, identity, $object.id) :name?=$object.name ]}\n}\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "incident": { + "storm": "// TODO - Figure out what these look like." + }, + "indicator": { + "storm": "$guid = $lib.guid(stix, indicator, $object.id)\nswitch $object.pattern_type {\n\n yara: {[ it:app:yara:rule=$guid\n :name?=$object.name\n :text?=$object.pattern\n ]}\n\n snort: {[ it:app:snort:rule=$guid\n :name?=$object.name\n :text?=$object.pattern\n ]}\n\n *: {[ it:sec:stix:indicator=$guid\n :name?=$object.name\n :pattern?=$object.pattern\n :created?=$object.created\n :updated?=$object.modified]\n | scrape --refs :pattern\n }\n}\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "infrastructure": { + "storm": "// TODO - Figure out what these look like." + }, + "intrusion-set": { + "storm": "($ok, $name) = $lib.trycast(ou:name, $object.name)\nif $ok {\n\n ou:name=$name -> ou:org\n { for $alias in $object.aliases { [ :names?+=$alias ] } }\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n return($node)\n\n [ ou:org=* :name=$name ]\n { for $alias in $object.aliases { [ :names?+=$alias ] } }\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n $node.data.set(stix:object, $object)\n return($node)\n}" + }, + "ipv4-addr": { + "storm": "[inet:ipv4=$object.value]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "ipv6-addr": { + "storm": "[inet:ipv6=$object.value]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "location": { + "storm": "// TODO - Figure out what these look like." + }, + "mac-addr": { + "storm": "// TODO - Figure out what these look like." + }, + "malware-analysis": { + "storm": "[\n it:av:scan:result=$lib.guid(stix, \"malware-analysis\", $object.id)\n :verdict=$object.result\n :signame=$object.result_name\n :scanner:name=$object.product\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "malware": { + "storm": "($ok, $name) = $lib.trycast(it:prod:softname, $object.name)\nif $ok {\n it:prod:softname=$name -> it:prod:soft\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n return($node)\n [ it:prod:soft=* :name=$name ]\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n $node.data.set(stix:object, $object)\n return($node)\n} else { // Sometimes malware objects don't have a name, let's save the description as a meta:note instead.\n [\n meta:note=(stix, note, $object.id)\n :type=stix.malware\n :text=$object.description\n :created=$object.created\n :updated=$object.modified\n ]\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n $node.data.set(stix:object, $object)\n return($node)\n}" + }, + "mutex": { + "storm": "// TODO - Figure out what these look like." + }, + "network-traffic": { + "storm": "// TODO - Figure out what these look like." + }, + "note": { + "storm": "[\n meta:note=(stix, note, $object.id)\n :type=stix.note\n :text=$object.content\n :created=$object.created\n :updated=$object.modified\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\nreturn($node)" + }, + "observed-data": { + "storm": "// TODO - Figure out what these look like." + }, + "opinion": { + "storm": "// TODO - Figure out if content is the right key here.\n[\n meta:note=(stix, note, $object.id)\n :type=stix.opinion\n :text=$object.content\n :created=$object.created\n :updated=$object.modified\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\nreturn($node)" + }, + "process": { + "storm": "// TODO - Figure out what these look like." + }, + "relationship": { + "storm": "// TODO - Figure out what these look like." + }, + "report": { + "storm": "[ media:news=(stix, report, $object.id)\n :title?=$object.name\n :summary?=$object.description\n :published?=$object.published\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "sighting": { + "storm": "// TODO - Figure out what these look like." + }, + "software": { + "storm": "// TODO - Figure out what these look like." + }, + "threat-actor": { + "storm": "[ ps:contact=(stix, threat-actor, $object.id)\n :name?=$object.name\n :desc?=$object.description\n :names?=$object.aliases\n]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "tool": { + "storm": "($ok, $name) = $lib.trycast(it:prod:softname, $object.name)\nif $ok {\n it:prod:softname=$name -> it:prod:soft\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n return($node)\n [ it:prod:soft=* :name=$name ]\n [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n return($node)\n}" + }, + "url": { + "storm": "// TODO - Make sure value is the right key for this\n[inet:url=`{$object.value}`]\n[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ]\n$node.data.set(stix:object, $object)\nreturn($node)" + }, + "user-account": { + "storm": "" + }, + "vulnerability": { + "storm": "// TODO - Figure out what these look like." + }, + "windows-registry-key": { + "storm": "// TODO - Figure out what these look like." + }, + "x509-certificate": { + "storm": "// TODO - Figure out what these look like." + } + }, + "relationships": [ + { + "type": [ + "campaign", + "attributed-to", + "intrusion-set" + ], + "storm": "$n1node.props.org = $n2node" + }, + { + "type": [ + "intrusion-set", + "attributed-to", + "threat-actor" + ], + "storm": "$n2node.props.org = $n1node" + }, + { + "type": [ + null, + "uses", + null + ], + "storm": "yield $n1node [ +(uses)> { yield $n2node } ]" + }, + { + "type": [ + null, + "indicates", + null + ], + "storm": "yield $n1node [ +(indicates)> { yield $n2node } ]" + }, + { + "type": [ + "threat-actor", + "attributed-to", + "identity" + ], + "storm": "" + } + ] +} \ No newline at end of file diff --git a/scripts/build_stix_conf.py b/scripts/build_stix_conf.py new file mode 100644 index 0000000..0e3bf32 --- /dev/null +++ b/scripts/build_stix_conf.py @@ -0,0 +1,8 @@ +"""Build a default stix bundle Storm import config and save it to ``data/stix_import_conf.json``.""" + +import stormlibpp.stix + + +bc = stormlibpp.stix.BundleConf() +bc.load() +bc.save(out="data/stix_import_conf.json") diff --git a/src/stormlibpp/errors.py b/src/stormlibpp/errors.py index e4d7cb4..f3e033a 100644 --- a/src/stormlibpp/errors.py +++ b/src/stormlibpp/errors.py @@ -49,3 +49,14 @@ class HttpCortexNotImplementedError(s_exc.SynErr, NotImplementedError): class HttpCortexJsonError(HttpCortexError): """Unable to parse JSON response from Synapse with HttpCortex.""" + +class BundleConfError(RuntimeError): + """An error raised by BundleConf.""" + + +class BundleConfSaveError(BundleConfError): + """Raise when a BundleConf can't be saved.""" + + +class BundleConfLoadStormError(BundleConfError): + """Raise when a BundleConf can't load a Storm file.""" diff --git a/src/stormlibpp/stix/__init__.py b/src/stormlibpp/stix/__init__.py new file mode 100644 index 0000000..a09749b --- /dev/null +++ b/src/stormlibpp/stix/__init__.py @@ -0,0 +1,107 @@ +"""Code to aid in building objects for the ``$lib.stix`` Storm library.""" + +import json +import pathlib + +from . import storm_mapping +from .. import errors +from .. import utils + + +BLANK_CONF = { + "addbundle": True, + "bundle": {}, + "objects": {}, + "relationships": [], +} +"""A blank ``$lib.stix.import.config()``.""" + + +class BundleConf: + """Create a ``$lib.stix.import.config()`` compatible config from storm files. + + Parameters + ---------- + storm_path : str, optional + The path the to folder containing Storm code, by default "storm". + default : bool, optional + Whether to build the default import config dict packaged with stormlibpp. + Ignores the ``storm_path`` object if True. By default True. + out : str, optional + The path to save output in, by default "bundle_conf.json". + map : dict, optional + A custom mapping of ``$lib.stix.import.config()`` to Storm files. By + default ``storm_mapping.MAP``. See ``storm_mapping.MAP`` docstrings for details. + """ + + def __init__( + self, + storm_path: str = "storm", + default: bool = True, + out: str = "bundle_conf.json", + map: dict = storm_mapping.MAP, + ) -> None: + self.default = default + + if self.default: + self.path = (pathlib.Path(__file__).parent / "storm").expanduser().resolve() + else: + self.path = pathlib.Path(storm_path).expanduser().resolve() + + self.out = pathlib.Path(out).expanduser().resolve() + + self.map = map + + self.bundle_conf = BLANK_CONF + + def __repr__(self): + return ( + "BundleConf(storm_path='{p}', out='{o}', default={d}, map={m})" + ).format( + p=self.path, + o=self.out, + d=self.default, + m="{Default Map}" if self.map == storm_mapping.MAP else "{Custom Map}" + ) + + def __str__(self) -> str: + return json.dumps(self.bundle_conf) + + def _load_storm(self, key: str, rel_path: str): + path = str(self.path / key / rel_path) + + try: + with open(path, "r") as fd: + storm = fd.read() + utils.chk_storm_syntax(storm) + except OSError as err: + raise errors.BundleConfLoadStormError( + f"Unable to load the Storm code from {path}: {err}" + ) from err + except errors.StormSyntaxError as err: + raise errors.BundleConfLoadStormError( + f"Storm syntax error in {path}: {err}" + ) from err + + return storm + + def load(self): + for key, val in self.map.items(): + if key == "bundle": + self.bundle_conf[key].update({"storm": self._load_storm(key, val)}) + elif key == "relationships": + for item in val: + self.bundle_conf[key].append({"type": item["type"], "storm": self._load_storm(key, item["storm"])}) + elif key == "objects": + for item in val: + self.bundle_conf[key].update({item: {"storm": self._load_storm(key, val[item])}}) + + def save(self, out: str | pathlib.Path = ""): + path = out if out else self.out + try: + with open(path, "w") as fd: + json.dump(self.bundle_conf, fd, indent=2) + except (TypeError, OSError) as err: + raise errors.BundleConfSaveError( + f"Unable to save the Storm Stix bundle config to {path}: {err}" + ) from err diff --git a/src/stormlibpp/stix/storm/README.md b/src/stormlibpp/stix/storm/README.md new file mode 100644 index 0000000..57a0ede --- /dev/null +++ b/src/stormlibpp/stix/storm/README.md @@ -0,0 +1,62 @@ +# Storm Stix Conversion Code + +Storm code included in a custom `$lib.stix.import.config` dict that is generated by `stormlibpp.stix`. The intent is to create an object for as many objects that Stix supports as possible. + +## License Notice + +Currently, some files in this folder (listed below) are derivatives of the `synapse.lib.stormlib.stix` module - specifically, [this code](https://github.com/vertexproject/synapse/blob/2a2fd0549956c3754e88128a215e3910eb68176e/synapse/lib/stormlib/stix.py#L679). These files are covered by this [license](https://github.com/vertexproject/synapse/blob/2a2fd0549956c3754e88128a215e3910eb68176e/LICENSE). + +- `bundle/bundle.storm` +- `objects/campaign.storm` +- `objects/course-of-action.storm` +- `objects/identity.storm` +- `objects/indicator.storm` +- `objects/intrusion-set.storm` +- `objects/malware.storm` +- `objects/report.storm` +- `objects/threat-actor.storm` +- `objects/tool.storm` +- `relationships/camp_to_intset.storm` +- `relationships/indicates.storm` +- `relationships/intset_to_ta.storm` +- `relationships/ta_to_id.storm` +- `relationships/uses.storm` + +CHANGES: +- `bundle/bundle.storm` + - None +- `objects/campaign.storm` + - Refs edge to the stix bundle +- `objects/course-of-action.storm` + - Refs edge to the stix bundle +- `objects/identity.storm` + - Refs edge to the stix bundle + - Include the stix object in nodedata - with the bundle ID +- `objects/indicator.storm` + - Refs edge to the stix bundle +- `objects/intrusion-set.storm` + - Refs edge to the stix bundle + - Include the stix object in nodedata - with the bundle ID +- `objects/malware.storm` + - Refs edge to the stix bundle + - Include the stix object in nodedata for new nodes only - with the bundle ID + - Save malware objects without a name as meta:note nodes +- `objects/report.storm` + - Refs edge to the stix bundle + - Include the bundle ID in stix object nodedata +- `objects/threat-actor.storm` + - Refs edge to the stix bundle + - Include the bundle ID in stix object nodedata +- `objects/tool.storm` + - Refs edge to the stix bundle + - Include the stix object in nodedata for new nodes only - with the bundle ID +- `relationships/camp_to_intset.storm` + - None +- `relationships/indicates.storm` + - None +- `relationships/intset_to_ta.storm` + - None +- `relationships/ta_to_id.storm` + - None +- `relationships/uses.storm` + - None \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/bundle/bundle.storm b/src/stormlibpp/stix/storm/bundle/bundle.storm new file mode 100644 index 0000000..956bd61 --- /dev/null +++ b/src/stormlibpp/stix/storm/bundle/bundle.storm @@ -0,0 +1,5 @@ +it:sec:stix:bundle:id=$bundle.id +return($node) +[ it:sec:stix:bundle=* :id=$bundle.id ] +$node.data.set(stix:bundle, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/artifact.storm b/src/stormlibpp/stix/storm/objects/artifact.storm new file mode 100644 index 0000000..2904452 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/artifact.storm @@ -0,0 +1,72 @@ +// TODO - Figure out a way to support encryption - might require a Storm Service. +function get_file(url) { + $resp = $lib.inet.http.get($url) + if ($resp.code != 200) { + $lib.print(`Error requesting the STIX import config from "{$url}"\nHTTP Status Code: {$resp.code}\nErr: {$resp.err}`) + return($lib.null) + } else { + return($resp.body) + } +} + +function validate_file_hash(hashes, byts) { + for ($algo, $hash) in $hashes { + switch $algo { + "MD5": { if $hash = $lib.crypto.hashes.md5($byts) {return($lib.true)} } + "SHA-1": { if $hash = $lib.crypto.hashes.sha1($byts) {return($lib.true)} } + "SHA-256": { if $hash = $lib.crypto.hashes.sha256($byts) {return($lib.true)} } + "SHA-512": { if $hash = $lib.crypto.hashes.sha512($byts) {return($lib.true)} } + } + } + return($lib.false) +} + +function axon_available() { + $data = $lib.axon.metrics() + if $data { + return($lib.true) + } + return($lib.false) +} + +if $object.payload_bin { + $bin = $lib.base64.decode($object.payload_bin) +} else { + $bin = $get_file($object.url) + // TODO - Can we return messages, or raise errors? + if (not $bin) { return() } + if $object.hashes { + if (not $validate_file_hash($object.hashes, $bin)) { + return() + } + } +} + +// TODO - Figure out a way to support encryption - might require a Storm Service. + +$sha256 = $lib.crypto.hashes.sha256($bin) +$size = $lib.null +if $axon_available() { + try: + ($size, $_) = $lib.axon.put($bin) + catch * as err { + $lib.print(`Unable to upload {$sha256} to the Axon.`) + } +} + +file:bytes:sha256=$sha256 +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) + +[ + file:bytes=`sha256:{$sha256}` + :size?=$size + :md5?=$lib.crypto.hashes.md5($bin) + :sha1?=$lib.crypto.hashes.sha1($bin) + :sha256?=$lib.crypto.hashes.sha256($bin) + :sha512?=$lib.crypto.hashes.sha512($bin) +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) diff --git a/src/stormlibpp/stix/storm/objects/attack-pattern.storm b/src/stormlibpp/stix/storm/objects/attack-pattern.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/attack-pattern.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/autonomous-system.storm b/src/stormlibpp/stix/storm/objects/autonomous-system.storm new file mode 100644 index 0000000..ff45c8b --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/autonomous-system.storm @@ -0,0 +1,7 @@ +[ + inet:as=$object.number + :name?=$object.name +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/campaign.storm b/src/stormlibpp/stix/storm/objects/campaign.storm new file mode 100644 index 0000000..4e33ef6 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/campaign.storm @@ -0,0 +1,9 @@ +[ ou:campaign=(stix, campaign, $object.id) + :name?=$object.name + :desc?=$object.description + .seen?=$object.last_seen + .seen?=$object.first_seen +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/course-of-action.storm b/src/stormlibpp/stix/storm/objects/course-of-action.storm new file mode 100644 index 0000000..d470e5d --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/course-of-action.storm @@ -0,0 +1,7 @@ +[ risk:mitigation=(stix, course-of-action, $object.id) + :name?=$object.name + :desc?=$object.description +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/directory.storm b/src/stormlibpp/stix/storm/objects/directory.storm new file mode 100644 index 0000000..d9735b3 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/directory.storm @@ -0,0 +1,10 @@ +// TODO - Figure out what these look like. +[ it:fs:file=(stix, directory, $object.id) + :path=$object.path + :ctime?=$object.ctime + :mtime?=$object.mtime + :atime?=$object.atime +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/domain-name.storm b/src/stormlibpp/stix/storm/objects/domain-name.storm new file mode 100644 index 0000000..cd60381 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/domain-name.storm @@ -0,0 +1,38 @@ +function id_from_bundle(bun, obj_id) { + for $obj in $bun { + if ($obj.id = $obj_id) { + return ($obj) + } + } +} + +function find_resolves(refs) { + for $ref in $refs { + $resolves_obj = $id_from_bundle($bundle, $ref) + ($ok, $val) = $lib.trycast(inet:ipv4, $resolves_obj.value) + if $ok { + [(inet:dns:a=($object.value, $val))] + } + ($ok, $val) = $lib.trycast(inet:ipv6, $resolves_obj.value) + if $ok { + [(inet:dns:aaaa=($object.value, $val))] + } + ($ok, $val) = $lib.trycast(inet:fqdn, $resolves_obj.value) + if $ok { + [(inet:dns:cname=($object.value, $val))] + } + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + | spin | + } + fini { return() } +} + +[inet:fqdn=$object.value] + +if $object.resolves_to_refs { + $find_resolves($object.resolves_to_refs) +} + +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/email-addr.storm b/src/stormlibpp/stix/storm/objects/email-addr.storm new file mode 100644 index 0000000..d163727 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/email-addr.storm @@ -0,0 +1,15 @@ +function addUser(n) { + [ inet:user?=$object.display_name ] + [ <(refs)+ {yield $n} ] + return() +} + +[inet:email=$object.value] + +if $object.display_name { + $addUser($node) +} + +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/email-message.storm b/src/stormlibpp/stix/storm/objects/email-message.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/email-message.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/file.storm b/src/stormlibpp/stix/storm/objects/file.storm new file mode 100644 index 0000000..0e4670a --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/file.storm @@ -0,0 +1,26 @@ +if ($object.hashes != $lib.null) { + ($ok, $hash) = $lib.trycast(file:bytes, $object.hashes."SHA-256") + if $ok { + $guid = `sha256:{$hash}` + } else { + $guid = `guid:{$lib.guid(stix, file, $object.id)}` + } + [ + file:bytes=$guid + :size?=$object.size + :name?=$object.name + :mime?=$object.mime_type + :md5?=$object.hashes."MD5" + :sha1?=$object.hashes."SHA-1" + :sha256?=$object.hashes."SHA-256" + :sha512?=$object.hashes."SHA-512" + ] + + if (($object.parent_directory_ref != $lib.null) and ($object.name != $lib.null)) { + {[( file:filepath=((file, $guid), (path, `{$object.parent_directory_ref/$object.name}`)) )]} + } + // TODO - Do something with windows-pebinary-ext extension + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/grouping.storm b/src/stormlibpp/stix/storm/objects/grouping.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/grouping.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/identity.storm b/src/stormlibpp/stix/storm/objects/identity.storm new file mode 100644 index 0000000..5bee959 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/identity.storm @@ -0,0 +1,9 @@ +switch $object.identity_class { + group: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]} + organization: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]} + individual: {[ ps:contact=(stix, identity, $object.id) :name?=$object.name ]} + system: {[ it:host=(stix, identity, $object.id) :name?=$object.name ]} +} +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/incident.storm b/src/stormlibpp/stix/storm/objects/incident.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/incident.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/indicator.storm b/src/stormlibpp/stix/storm/objects/indicator.storm new file mode 100644 index 0000000..a19f71b --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/indicator.storm @@ -0,0 +1,24 @@ +$guid = $lib.guid(stix, indicator, $object.id) +switch $object.pattern_type { + + yara: {[ it:app:yara:rule=$guid + :name?=$object.name + :text?=$object.pattern + ]} + + snort: {[ it:app:snort:rule=$guid + :name?=$object.name + :text?=$object.pattern + ]} + + *: {[ it:sec:stix:indicator=$guid + :name?=$object.name + :pattern?=$object.pattern + :created?=$object.created + :updated?=$object.modified] + | scrape --refs :pattern + } +} +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/infrastructure.storm b/src/stormlibpp/stix/storm/objects/infrastructure.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/infrastructure.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/intrusion-set.storm b/src/stormlibpp/stix/storm/objects/intrusion-set.storm new file mode 100644 index 0000000..cbea130 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/intrusion-set.storm @@ -0,0 +1,15 @@ +($ok, $name) = $lib.trycast(ou:name, $object.name) +if $ok { + + ou:name=$name -> ou:org + { for $alias in $object.aliases { [ :names?+=$alias ] } } + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) + + [ ou:org=* :name=$name ] + { for $alias in $object.aliases { [ :names?+=$alias ] } } + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/ipv4-addr.storm b/src/stormlibpp/stix/storm/objects/ipv4-addr.storm new file mode 100644 index 0000000..a89e2e4 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/ipv4-addr.storm @@ -0,0 +1,4 @@ +[inet:ipv4=$object.value] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/ipv6-addr.storm b/src/stormlibpp/stix/storm/objects/ipv6-addr.storm new file mode 100644 index 0000000..b8dac0c --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/ipv6-addr.storm @@ -0,0 +1,4 @@ +[inet:ipv6=$object.value] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/location.storm b/src/stormlibpp/stix/storm/objects/location.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/location.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/mac-addr.storm b/src/stormlibpp/stix/storm/objects/mac-addr.storm new file mode 100644 index 0000000..79a7c21 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/mac-addr.storm @@ -0,0 +1,4 @@ +[inet:mac=$object.value] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/malware-analysis.storm b/src/stormlibpp/stix/storm/objects/malware-analysis.storm new file mode 100644 index 0000000..af1eaca --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/malware-analysis.storm @@ -0,0 +1,9 @@ +[ + it:av:scan:result=$lib.guid(stix, "malware-analysis", $object.id) + :verdict=$object.result + :signame=$object.result_name + :scanner:name=$object.product +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/malware.storm b/src/stormlibpp/stix/storm/objects/malware.storm new file mode 100644 index 0000000..c25c5e3 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/malware.storm @@ -0,0 +1,21 @@ +($ok, $name) = $lib.trycast(it:prod:softname, $object.name) +if $ok { + it:prod:softname=$name -> it:prod:soft + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + return($node) + [ it:prod:soft=* :name=$name ] + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} else { // Sometimes malware objects don't have a name, let's save the description as a meta:note instead. + [ + meta:note=(stix, note, $object.id) + :type=stix.malware + :text=$object.description + :created=$object.created + :updated=$object.modified + ] + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/mutex.storm b/src/stormlibpp/stix/storm/objects/mutex.storm new file mode 100644 index 0000000..29babfc --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/mutex.storm @@ -0,0 +1,4 @@ +[ it:dev:mutex=$object.name ] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/network-traffic.storm b/src/stormlibpp/stix/storm/objects/network-traffic.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/network-traffic.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/note.storm b/src/stormlibpp/stix/storm/objects/note.storm new file mode 100644 index 0000000..8734ef3 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/note.storm @@ -0,0 +1,10 @@ +[ + meta:note=(stix, note, $object.id) + :type=stix.note + :text=$object.content + :created=$object.created + :updated=$object.modified +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/observed-data.storm b/src/stormlibpp/stix/storm/objects/observed-data.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/observed-data.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/opinion.storm b/src/stormlibpp/stix/storm/objects/opinion.storm new file mode 100644 index 0000000..69db80c --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/opinion.storm @@ -0,0 +1,11 @@ +// TODO - Figure out if content is the right key here. +[ + meta:note=(stix, note, $object.id) + :type=stix.opinion + :text=$object.content + :created=$object.created + :updated=$object.modified +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/process.storm b/src/stormlibpp/stix/storm/objects/process.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/process.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/relationship.storm b/src/stormlibpp/stix/storm/objects/relationship.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/relationship.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/report.storm b/src/stormlibpp/stix/storm/objects/report.storm new file mode 100644 index 0000000..0e7046b --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/report.storm @@ -0,0 +1,8 @@ +[ media:news=(stix, report, $object.id) + :title?=$object.name + :summary?=$object.description + :published?=$object.published +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/sighting.storm b/src/stormlibpp/stix/storm/objects/sighting.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/sighting.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/software.storm b/src/stormlibpp/stix/storm/objects/software.storm new file mode 100644 index 0000000..4954b14 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/software.storm @@ -0,0 +1,15 @@ +($ok, $name) = $lib.trycast(it:prod:softname, $object.name) +if $ok { + it:prod:softname=$name -> it:prod:soft + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + return($node) + [ + it:prod:soft=* + :name=$name + :cpe?=$object.cpe + ] + // TODO - Resolve software vendor + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/threat-actor.storm b/src/stormlibpp/stix/storm/objects/threat-actor.storm new file mode 100644 index 0000000..674b0be --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/threat-actor.storm @@ -0,0 +1,8 @@ +[ ps:contact=(stix, threat-actor, $object.id) + :name?=$object.name + :desc?=$object.description + :names?=$object.aliases +] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/tool.storm b/src/stormlibpp/stix/storm/objects/tool.storm new file mode 100644 index 0000000..27d0edf --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/tool.storm @@ -0,0 +1,11 @@ +($ok, $name) = $lib.trycast(it:prod:softname, $object.name) +if $ok { + it:prod:softname=$name -> it:prod:soft + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) + [ it:prod:soft=* :name=$name ] + [ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] + $node.data.set(`stix:object:bundle:{$bundle.id}`, $object) + return($node) +} \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/url.storm b/src/stormlibpp/stix/storm/objects/url.storm new file mode 100644 index 0000000..b8835fb --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/url.storm @@ -0,0 +1,4 @@ +[inet:url=$object.value] +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/user-account.storm b/src/stormlibpp/stix/storm/objects/user-account.storm new file mode 100644 index 0000000..a41482e --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/user-account.storm @@ -0,0 +1,46 @@ +if (($object.account_type != $lib.null) and ($object.account_login != $lib.null)) { + if ($object.account_type in ("posix", "windows-local", "windows-domain")) { + [ + it:account=(stix, "user-account", $object.id) + :user?=$object.account_login + ] + if ($object.account_type = "posix") { + [ :posix:uid?=$object.user_id ] + } else { + [ :windows:sid?=$object.user_id ] + } + } elif (($object.account_type in (facebook, skype, twitter)){ + switch $object.account_type { + facebook: {[inet:web:account=`facebook.com/{$object.account_login}`]} + skype: {[inet:web:account=`skype.com/{$object.account_login}`]} + twitter: {[inet:web:account=`twitter.com/{$object.account_login}`]} + } + } else { + [ + auth:creds=(stix, "user-account", $object.id) + :user=$object.account_login + :passwd?=$object.credential + ] + } +} + +if (($node != $lib.null) and ($node.form != auth:creds)) { + $acct = $node + { + [ + auth:creds=(stix, "user-account", $object.id)\ + :user=$object.account_login + :passwd?=$object.credential + ] + -inet:web:account + -it:account + if ($object.account_type in ("posix", "windows-local", "windows-domain")) { + [:account={yield $acct}] + } else { + [:web:acct={yield $acct}] + } + } +} +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/vulnerability.storm b/src/stormlibpp/stix/storm/objects/vulnerability.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/vulnerability.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/windows-registry-key.storm b/src/stormlibpp/stix/storm/objects/windows-registry-key.storm new file mode 100644 index 0000000..02d3cfa --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/windows-registry-key.storm @@ -0,0 +1 @@ +// TODO - Figure out what these look like. \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/objects/x509-certificate.storm b/src/stormlibpp/stix/storm/objects/x509-certificate.storm new file mode 100644 index 0000000..1c0a4a3 --- /dev/null +++ b/src/stormlibpp/stix/storm/objects/x509-certificate.storm @@ -0,0 +1,55 @@ +function resolve_file_bytes(hashes) { + if (hashes."MD5" != $lib.null) { + file:bytes:md5=hashes."MD5" + } + elif (hashes."SHA-1" != $lib.null) { + file:bytes:sha1=hashes."SHA-1" + } + elif (hashes."SHA-256" != $lib.null) { + file:bytes:sha256=hashes."SHA-256" + } + elif (hashes."SHA-512" != $lib.null) { + file:bytes:sha512=hashes."SHA-512" + } + return($node) +} + +function gen_cert() { + if ($object.hashes != $lib.null) { + crypto:x509:cert:file={yield $resolve_file_bytes($object.hashes)} + return($node) + file:bytes:md5?=$object.hashes."MD5" + file:bytes:sha1?=$object.hashes."SHA-1" + file:bytes:sha256?=$object.hashes."SHA-256" + return($node) + } + if ($object.serial_number != $lib.null) { + crypto:x509:cert:serial=$object.serial_number + return($node) + } + [crypto:x509:cert=(stix, "x509-certificate", $object.id)] + return($node) +} + + +yield $gen_cert() +[ + :serial?=$object.serial + :file?={yield $resolve_file_bytes($object.hashes)} + :version?=$object.version + :algo?=$object.signature_algorithm + :issuer?=$object.issuer + :subject?=$object.subject + :validity:notbefore?=$object.validity_not_before + :validity:notafter?=$object.validity_not_after +] + +if ($object.hashes != $lib.null) { + :md5?=$object.hashes."MD5" + :sha1?=$object.hashes."SHA-1" + :sha256?=$object.hashes."SHA-256" +} + +[ <(refs)+ { it:sec:stix:bundle:id=$bundle.id } ] +$node.data.set(`stix:object:bundle:{$bundle.id}`, $object) +return($node) \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/relationships/camp_to_intset.storm b/src/stormlibpp/stix/storm/relationships/camp_to_intset.storm new file mode 100644 index 0000000..4d524aa --- /dev/null +++ b/src/stormlibpp/stix/storm/relationships/camp_to_intset.storm @@ -0,0 +1 @@ +$n1node.props.org = $n2node \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/relationships/indicates.storm b/src/stormlibpp/stix/storm/relationships/indicates.storm new file mode 100644 index 0000000..fbcee68 --- /dev/null +++ b/src/stormlibpp/stix/storm/relationships/indicates.storm @@ -0,0 +1 @@ +yield $n1node [ +(indicates)> { yield $n2node } ] \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/relationships/intset_to_ta.storm b/src/stormlibpp/stix/storm/relationships/intset_to_ta.storm new file mode 100644 index 0000000..cc57796 --- /dev/null +++ b/src/stormlibpp/stix/storm/relationships/intset_to_ta.storm @@ -0,0 +1 @@ +$n2node.props.org = $n1node \ No newline at end of file diff --git a/src/stormlibpp/stix/storm/relationships/ta_to_id.storm b/src/stormlibpp/stix/storm/relationships/ta_to_id.storm new file mode 100644 index 0000000..e69de29 diff --git a/src/stormlibpp/stix/storm/relationships/uses.storm b/src/stormlibpp/stix/storm/relationships/uses.storm new file mode 100644 index 0000000..a6393f7 --- /dev/null +++ b/src/stormlibpp/stix/storm/relationships/uses.storm @@ -0,0 +1 @@ +yield $n1node [ +(uses)> { yield $n2node } ] \ No newline at end of file diff --git a/src/stormlibpp/stix/storm_mapping.py b/src/stormlibpp/stix/storm_mapping.py new file mode 100644 index 0000000..f4c65e4 --- /dev/null +++ b/src/stormlibpp/stix/storm_mapping.py @@ -0,0 +1,138 @@ +"""Stores the default file mapping used in ``stormlibpp.stix.BundleConf``.""" + +MAP = { + "bundle": "bundle.storm", + "objects": { + "artifact": "artifact.storm", + "attack-pattern": "attack-pattern.storm", + "autonomous-system": "autonomous-system.storm", + "campaign": "campaign.storm", + "course-of-action": "course-of-action.storm", + "directory": "directory.storm", + "domain-name": "domain-name.storm", + "email-addr": "email-addr.storm", + "email-message": "email-message.storm", + "file": "file.storm", + "grouping": "grouping.storm", + "identity": "identity.storm", + "incident": "incident.storm", + "indicator": "indicator.storm", + "infrastructure": "infrastructure.storm", + "intrusion-set": "intrusion-set.storm", + "ipv4-addr": "ipv4-addr.storm", + "ipv6-addr": "ipv6-addr.storm", + "location": "location.storm", + "mac-addr": "mac-addr.storm", + "malware-analysis": "malware-analysis.storm", + "malware": "malware.storm", + "mutex": "mutex.storm", + "network-traffic": "network-traffic.storm", + "note": "note.storm", + "observed-data": "observed-data.storm", + "opinion": "opinion.storm", + "process": "process.storm", + "relationship": "relationship.storm", + "report": "report.storm", + "sighting": "sighting.storm", + "software": "software.storm", + "threat-actor": "threat-actor.storm", + "tool": "tool.storm", + "url": "url.storm", + "user-account": "user-account.storm", + "vulnerability": "vulnerability.storm", + "windows-registry-key": "windows-registry-key.storm", + "x509-certificate": "x509-certificate.storm", + }, + "relationships": [ + { + "type": ["campaign", "attributed-to", "intrusion-set"], + "storm": "camp_to_intset.storm", + }, + { + "type": ["intrusion-set", "attributed-to", "threat-actor"], + "storm": "intset_to_ta.storm", + }, + { + "type": [None, "uses", None], + "storm": "uses.storm", + }, + { + "type": [None, "indicates", None], + "storm": "indicates.storm", + }, + { + "type": ["threat-actor", "attributed-to", "identity"], + "storm": "ta_to_id.storm", + }, + ], +} +"""A mapping of items in a ``$lib.stix.import.config()`` to Storm file names. + +The name of each top-level key is a folder in a parent directory passed to +``BundleConf`` as ``storm_path``. These keys also match the top-level keys +of a ``$lib.stix.import.config()``. + +``BundleConf`` uses this mapping to create a valid ``$lib.stix.import.config()``, +loading Storm code from the files designated files. + +The ``bundle`` should only ever point to a single Storm file. + +Each sub-key of ``objects`` is the name of a Stix object, and points to a single +file that has Storm code to create a node from that Stix object. + +The ``relationships`` values are almost exactly the same as those found in a +``$lib.stix.import.config()``. Except that the ``storm`` key points to a file +with Storm code. + +The default mapping represents a file structure like this:: + + storm/ + ├── bundle + │ └── bundle.storm + ├── objects + │ ├── artifact.storm + │ ├── attack-pattern.storm + │ ├── autonomous-system.storm + │ ├── campaign.storm + │ ├── course-of-action.storm + │ ├── directory.storm + │ ├── domain-name.storm + │ ├── email-addr.storm + │ ├── email-message.storm + │ ├── file.storm + │ ├── grouping.storm + │ ├── identity.storm + │ ├── incident.storm + │ ├── indicator.storm + │ ├── infrastructure.storm + │ ├── intrusion-set.storm + │ ├── ipv4-addr.storm + │ ├── ipv6-addr.storm + │ ├── location.storm + │ ├── mac-addr.storm + │ ├── malware-analysis.storm + │ ├── malware.storm + │ ├── mutex.storm + │ ├── network-traffic.storm + │ ├── note.storm + │ ├── observed-data.storm + │ ├── opinion.storm + │ ├── process.storm + │ ├── relationship.storm + │ ├── report.storm + │ ├── sighting.storm + │ ├── software.storm + │ ├── threat-actor.storm + │ ├── tool.storm + │ ├── url.storm + │ ├── user-account.storm + │ ├── vulnerability.storm + │ ├── windows-registry-key.storm + │ └── x509-certificate.storm + └── relationships + ├── camp_to_intset.storm + ├── indicates.storm + ├── intset_to_ta.storm + ├── ta_to_id.storm + └── uses.storm +""" \ No newline at end of file diff --git a/tests/data/cisa_stix_bun.json b/tests/data/cisa_stix_bun.json new file mode 100644 index 0000000..fea49f4 --- /dev/null +++ b/tests/data/cisa_stix_bun.json @@ -0,0 +1,1075 @@ +{ + "type": "bundle", + "id": "bundle--3147edae-b574-4717-9809-4022e5236b1a", + "objects": [ + { + "type": "marking-definition", + "spec_version": "2.1", + "id": "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771", + "created": "2023-08-11T15:46:15.983Z", + "extensions": { + "extension-definition--3a65884d-005a-4290-8335-cb2d778a83ce": { + "access_privilege": [ + { + "privilege_action": "CISAUSES", + "privilege_scope": { + "entity": [ + "ALL" + ], + "permitted_nationalities": [ + "ALL" + ], + "permitted_organizations": [ + "ALL" + ], + "shareability": [ + "ALL" + ] + }, + "rule_effect": "permit" + } + ], + "authority_reference": [ + "urn:isa:authority:ais" + ], + "control_set": { + "classification": "U", + "formal_determination": [ + "INFORMATION-DIRECTLY-RELATED-TO-CYBERSECURITY-THREAT", + "PUBREL" + ] + }, + "create_date_time": "2023-08-11T15:46:15.983Z", + "extension_type": "property-extension", + "further_sharing": [ + { + "sharing_scope": [ + "USA.USG" + ], + "rule_effect": "permit" + } + ], + "identifier": "isa:guide.19001.GEMINI-a9bdb603-7f4f-44c6-acb0-d47f614e64b2", + "policy_reference": "urn:isa:policy:acs:ns:v3.0?privdefault=deny&sharedefault=deny", + "responsible_entity_custodian": "USA.DHS.CISA.CSD.TH.CMA", + "responsible_entity_originator": "USA.DHS.CISA.CSD.TH.CMA" + } + } + }, + { + "type": "identity", + "spec_version": "2.1", + "id": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created_by_ref": "identity--42ac3c92-60d2-418f-ba8e-838944e6110b", + "created": "2023-04-12T17:53:09.646Z", + "modified": "2023-04-12T17:53:09.646Z", + "name": "GeminiProduction_CMA", + "description": "Cybersecurity and Infrastructure Security Agency Production Identity. Code and Media Analysis.", + "identity_class": "system", + "confidence": 100, + "lang": "en", + "object_marking_refs": [ + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ] + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f", + "hashes": { + "MD5": "fd41134e8ead1c18ccad27c62a260aa6", + "SHA-1": "04423659f175a6878b26ac7d6b6e47c6fd9194d1", + "SHA-256": "edc0c63065e88ec96197c8d7a40662a15a812a9583dc6c82b18ecd7e43b13b70", + "SHA-512": "df55591e730884470afba688e17c83fafb157ecf94c9f10a20e21f229434ea58b59f8eb771f8f9e29993f43f4969fe66dd913128822b534c9b1a677453dbb93c", + "SSDEEP": "49152:99z0w/qP1dKPzeietmd64H9QaIG0aYkn0GzkWVISaJUET6qyxASuOszP7hn+S6wB:v0R9dKSiekd68ZIQ0obVI9UG6qyuhF6" + }, + "size": 2840064, + "name": "BrightmetricAgent.exe", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ] + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--c577e744-04a1-49d3-b636-4ff7d836bb6b", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "adaware", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.05F91E9C", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--57df436c-ff51-45e7-9455-2dcf69685336", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "antiy", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "GrayWare/Win32.Kryptik.ffp", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--92c4b747-2167-4c2f-a023-1f7a46868668", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "bitdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.05F91E9C", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--4ed8abe7-b4cd-4523-a0e3-433a90d94e3d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "eset", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "a variant of WinGo/HackTool.Agent.Y trojan", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--4d173e26-37d0-4c55-94ce-1dd701d5957d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "emsisoft", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.05F91E9C (B)", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--efd0ed4a-c9fe-47c9-9c2b-aa676e676ae0", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "ikarus", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Trojan.WinGo.Rozena", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--28c48841-d813-4522-baa8-4021ebe3dacc", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "microsoftdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Malware", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--9e9777f4-44db-4db2-8a64-11fa9670f67f", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "sophos", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "App/FRProxy-F", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--967dd29b-dc96-43e2-9869-2ff448474a9e", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "varist", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "W64/Agent.FXW.gen!Eldorado", + "result": "unknown", + "sample_ref": "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + }, + { + "type": "malware", + "spec_version": "2.1", + "id": "malware--664d9112-90fe-4d52-b07b-105daad69618", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "description": "This artifact is a cross platform full featured FRP that is written in GO language (Golang) and packed using Ultimate Packer for Executables (UPX). This utility can be used to locate servers behind a network firewall or obscured through NAT. It includes the KCP (no acronym) network protocol that allows for error-checked and anonymous delivery of data streams using the User Datagram Protocol (UDP) with packet level encryption support.\r\n\r\nThe program contains two different multiplexer libraries that can bi-directionally stream data over a NAT\u2019d network. It also contains a command line interface (CLI) library that can leverage command shells such as PowerShell, Windows Management Instrumentation (WMI), and Z Shell (zsh). In addition, the utility features a unique capability that detects if the utility is executed from the command line or by double-clicking. \r\n\r\nBy default it is configured to connect to the Internet Protocol (IP) address, 203.95.8.98 on Transmission Control Protocol (TCP) port 1080. It must receive a specially formed packet from the C2 for the utility to deploy on the system.", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "malware_types": [ + "trojan" + ], + "is_family": false, + "sample_refs": [ + "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f" + ] + }, + { + "type": "indicator", + "spec_version": "2.1", + "id": "indicator--8a72c4d8-0846-400d-8812-6105d4f98dc4", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "name": "BrightmetricAgent.exe", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "indicator_types": [ + "malicious-activity" + ], + "pattern": "[file:hashes.'MD5'='fd41134e8ead1c18ccad27c62a260aa6' OR file:hashes.'SHA-1'='04423659f175a6878b26ac7d6b6e47c6fd9194d1' OR file:hashes.'SHA-256'='edc0c63065e88ec96197c8d7a40662a15a812a9583dc6c82b18ecd7e43b13b70' OR file:hashes.'SHA-512'='df55591e730884470afba688e17c83fafb157ecf94c9f10a20e21f229434ea58b59f8eb771f8f9e29993f43f4969fe66dd913128822b534c9b1a677453dbb93c']", + "pattern_type": "stix", + "pattern_version": "2.1", + "valid_from": "2024-02-02T15:11:50.14103Z" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--2e9778d4-e97e-56dc-a8fd-fd39a8bfe9d5", + "value": "203.95.8.98", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ] + }, + { + "type": "note", + "spec_version": "2.1", + "id": "note--1e5d2e39-ec90-4553-961b-3877d97d39c4", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "content": "BrightmetricAgent.exe (edc0c63065...) attempts to connect to this IP address. The IP address hosts a proxy server.", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "object_refs": [ + "ipv4-addr--2e9778d4-e97e-56dc-a8fd-fd39a8bfe9d5" + ] + }, + { + "type": "location", + "spec_version": "2.1", + "id": "location--34610caa-9135-4875-ac37-4746088dd006", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-02-02T15:11:50.25412Z", + "modified": "2024-02-02T15:11:50.25412Z", + "name": "203.95.8.98", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "description": "Domain Name: pdsguam.biz\r\nRegistry Domain ID: D15926452-BIZ\r\nRegistrar WHOIS Server: whois.godaddy.com\r\nRegistrar URL: whois.godaddy.com\r\nUpdated Date: 2023-06-15T04:28:19Z\r\nCreation Date: 2007-01-10T00:40:37Z\r\nRegistry Expiry Date: 2024-01-09T23:59:59Z\r\nRegistrar: GoDaddy.com, LLC\r\nRegistrar IANA ID: 146\r\nRegistrar Abuse Contact Email: abuse@godaddy.com\r\nRegistrar Abuse Contact Phone: +1.4806242505\r\nRegistrant Organization: Domains By Proxy, LLC\r\nRegistrant State/Province: Arizona\r\nRegistrant Country: US\r\nRegistrant Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\r\nAdmin Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\r\nTech Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\r\nName Server: ns.pdsguam.biz\r\nName Server: ns2.pdsguam.biz\r\nDNSSEC: unsigned", + "region": "northern-america", + "country": "US" + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c", + "hashes": { + "MD5": "3a97d9b6f17754dcd38ca7fc89caab04", + "SHA-1": "ffb1d8ea3039d3d5eb7196d27f5450cac0ea4f34", + "SHA-256": "eaef901b31b5835035b75302f94fee27288ce46971c6db6221ecbea9ba7ff9d0", + "SHA-512": "d99941e4445efed5d4e407f91a9e5bba08d1be3f0dab065d1bfb4e70ab48d6526a730233d6889ba58de449f622e6a14e99dab853d40fc30a508627fd2735c973", + "SSDEEP": "384:ahXoLj9Zez0Bm4SUZa8WLLXyjSL2RtfAwj/yneIMUogQ:ahXoLhZez0m4SIabLLCmL2Rvj/yeIEg" + }, + "size": 20480, + "name": "eaef901b31b5835035b75302f94fee27288ce46971c6db6221ecbea9ba7ff9d0", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ] + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--c3964dad-86fe-4235-a174-49bd49422ee7", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "adaware", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Unavailable (production)", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--6996c7b2-7f76-49d4-bb56-985101b2ce9f", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "ahnlab", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Unwanted/Win32.Foundstone", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--004e4ae2-0349-4464-b9d9-33a1cce2e8b1", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "antiy", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "HackTool[NetTool]/Win32.Portscan", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--a5cc9df5-c105-47ab-9f12-5ac694bae64d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "bitdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Unavailable (production)", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--b6e682d8-10ab-4f05-962c-7ea774f1920d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "clamav", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Win.Trojan.Scanline-1", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--2f43287b-bb70-4d99-ab26-5adbcbbecedd", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "comodo", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "ApplicUnwnt", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--c13c10ef-1fdc-4855-8555-8fc0bade8818", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "cylance", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Malware", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--de0c9309-93b5-44a4-8f58-0f5d93079a34", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "filseclab", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Hacktool.ScanLine.a.fsff", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--a08a9f25-d8e2-41a4-bbea-86d9c217a64e", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "ikarus", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Virtool", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--ca9c3dc5-bb4f-4b7f-99db-0c653f95d415", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "mcafee", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Unavailable (production)", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--3fefb2c2-d39c-4028-8c2a-f3b8684d141b", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "microsoftdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Malware", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--b565d211-a4b1-46d1-87d2-6b4364aa3636", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "nanoav", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Riskware.Win32.ScanLine.dhhus", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--2d3f9171-807d-4388-96e0-4d844fc21968", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "quickheal", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Trojan.Win32", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--a083e2ec-1f21-4a6b-bfa0-f259abbda95a", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "scrutiny", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Malware", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--2ece688f-fd0d-45b4-982e-4cf47cdfa4a0", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "sophos", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "App/ScanLn-A", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--a54e9075-ab72-4adb-a73f-703f14611e0f", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "virusblokada", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Trojan.Genome.fl", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--55967892-3008-460e-83f0-7a1f92f3c924", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "webrootsmd", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Unavailable (production)", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--a3040dc9-9cd9-4b96-9c55-a49587f7f9cb", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "zillya", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Tool.Portscan.Win32.77", + "result": "unknown", + "sample_ref": "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + }, + { + "type": "malware", + "spec_version": "2.1", + "id": "malware--8dff02fd-d899-4b84-a668-5be524f7da05", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "description": "This artifact is a command-line port scanning utility from Foundstone, Inc. called ScanLine, which is packed using UPX. It is used to scan for open UDP and TCP ports, grab banners from open ports, resolve IP addresses to host names, and bind to specified ports and IP addresses.", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "malware_types": [ + "trojan" + ], + "is_family": false, + "sample_refs": [ + "file--70bfcb9c-8313-5dac-a096-ff7f5578721c" + ] + }, + { + "type": "indicator", + "spec_version": "2.1", + "id": "indicator--333ee8b9-18f8-4cc8-8e63-f04b4d0fecc7", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "name": "eaef901b31b5835035b75302f94fee27288ce46971c6db6221ecbea9ba7ff9d0", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "indicator_types": [ + "malicious-activity" + ], + "pattern": "[file:hashes.'MD5'='3a97d9b6f17754dcd38ca7fc89caab04' OR file:hashes.'SHA-1'='ffb1d8ea3039d3d5eb7196d27f5450cac0ea4f34' OR file:hashes.'SHA-256'='eaef901b31b5835035b75302f94fee27288ce46971c6db6221ecbea9ba7ff9d0' OR file:hashes.'SHA-512'='d99941e4445efed5d4e407f91a9e5bba08d1be3f0dab065d1bfb4e70ab48d6526a730233d6889ba58de449f622e6a14e99dab853d40fc30a508627fd2735c973']", + "pattern_type": "stix", + "pattern_version": "2.1", + "valid_from": "2024-02-02T15:11:50.287884Z" + }, + { + "type": "file", + "spec_version": "2.1", + "id": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436", + "hashes": { + "MD5": "b1de37bf229890ac181bdef1ad8ee0c2", + "SHA-1": "ffdb3cc7ab5b01d276d23ac930eb21ffe3202d11", + "SHA-256": "99b80c5ac352081a64129772ed5e1543d94cad708ba2adc46dc4ab7a0bd563f1", + "SHA-512": "e41df636a36ac0cce38e7db5c2ce4d04a1a7f9bc274bdf808912d14067dc1ef478268035521d0d4b7bcf96facce7f515560b38a7ebe47995d861b9c482e07e25", + "SSDEEP": "98304:z2eyMq4PuR5d7wgdo0OFfnFJkEUCGdaQLhpYYEfRTl6sysy:ryxzbdo0ifnoEOdz9pY7j5" + }, + "size": 3712512, + "name": "SMSvcService.exe", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "extensions": { + "windows-pebinary-ext": { + "pe_type": "exe", + "number_of_sections": 4, + "time_date_stamp": "1970-01-01T00:00:00Z", + "size_of_optional_header": 512, + "sections": [ + { + "name": "header", + "size": 512, + "entropy": 2.499747, + "hashes": { + "MD5": "7f8e8722da728b6e834260b5a314cbac" + } + }, + { + "name": "UPX0", + "size": 0, + "entropy": 0.0, + "hashes": { + "MD5": "d41d8cd98f00b204e9800998ecf8427e" + } + }, + { + "name": "UPX1", + "size": 3711488, + "entropy": 7.890727, + "hashes": { + "MD5": "f9943591918adeeeee7da80e4d985a49" + } + }, + { + "name": "UPX2", + "size": 512, + "entropy": 1.371914, + "hashes": { + "MD5": "5c0061445ac2f8e6cadf694e54146914" + } + } + ] + } + } + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--f62bbb36-6561-431c-94b5-cedbb0e30604", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "adaware", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.105C517F", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--98c0e7b0-3117-4f30-a73c-55b51a24384b", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "ahnlab", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "HackTool/Win.Frpc", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--57abe6be-190b-48a9-9e83-58204f847fb4", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "antiy", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "GrayWare/Win32.Kryptik.ffp", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--d79545b2-1d05-40c8-bf71-689428c36e1b", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "bitdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.105C517F", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--5dee8895-7db8-4649-b502-e0ec64c8b871", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "eset", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "a variant of WinGo/Riskware.Frp.U application", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--1bd586c5-5182-47d6-b755-8e77076709d6", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "emsisoft", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Generic.Trojan.Volt.Marte.A.105C517F (B)", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--188dc319-886c-4b27-9bac-fbb06c0401ae", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "ikarus", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Trojan.WinGo.Shellcoderunner", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--e0c25271-10ef-4595-b252-0650f428e273", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "microsoftdefender", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "Malware", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--bb30dc97-78b7-4456-a11f-1cf550e948dd", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "sophos", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "App/FRProxy-F", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware-analysis", + "spec_version": "2.1", + "id": "malware-analysis--dfd5d242-6931-4e6e-9686-05b968380c8d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "product": "varist", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "result_name": "W64/Agent.FXW.gen!Eldorado", + "result": "unknown", + "sample_ref": "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + }, + { + "type": "malware", + "spec_version": "2.1", + "id": "malware--d90aea2c-20f7-4125-b930-1ec855c27f98", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "description": "This artifact is a 64-bit Windows executable file that is packed using UPX. This packed file contains a compiled version of an open-source tool published on GitHub called \"FRPC\". The \"FRPC\" is a command-line tool written in Golang that is designed to open a reverse proxy between the compromised system and the TA's C2 server. \r\n\r\nWhen the \"FRPC\" is installed and executed on the compromised system, it attempts to establish a connection with the Fast Reverse Proxy Server (FRPS) using the reverse proxy method to allow the TA to control the compromised system. This \"FRPC\" application supports encryption, compression, and allows easy token authentication. It also supports the protocols below:\r\n\r\n--Begin protocols--\r\nTransmission Control Protocol (TCP)\r\nUser Datagram Protocol (UDP)\r\nAn alternative Hypertext Transfer Protocol (HTTP)\r\nAn alternative Hypertext Transfer Protocol Secure (HTTPS)\r\n--End protocols--\r\n\r\nDisplayed below is the \"FRPC\" tool configuration that contains the network communication method, the remote \"FRPS\" server's public Internet Protocol (IP) address and port numbers: \r\n\r\n--Begin configuration--\r\n[common]\r\n\tserver_addr = 192.168.18.111\r\n\tserver_port = 8081\r\n\tserver_addrs = 203.95.9.54,203.95.9.54,203.95.9.54\r\n\tserver_ports = 8443,8443,8443\r\n\ttoken = 1kyRdFmuk0i25JbCJmtift1c9VA05VBS\r\n\tprotocol = tcp\r\n\ttls_enable = true\r\n\tdisable_custom_tls_first_byte = true\r\n\tlog_level = debug\r\n\t\r\n\t[plugin_socks5]\r\n\ttype = tcp\r\n\tremote_port = 1080\r\n\tplugin = socks5\r\n\tuse_encryption = true\r\n\tuse_compression = true\r\n--End configuration--\r\n\r\nDisplayed below are the command-line usages and flags of the \"FRPC\" tool:\r\n\r\n--Begin usages and flags--\r\n\r\nUsage:\r\n frpc [flags]\r\n frpc [command]\r\n\r\nAvailable Commands:\r\n help Help about any command\r\n tcp Run frpc with a single tcp proxy\r\n udp Run frpc with a single udp proxy\r\n verify Verify that the configures is valid\r\n\r\nFlags:\r\n -c, --config string config file of frpc (default \"./frpc.ini\")\r\n -h, --help help for frpc\r\n -v, --version version of frpc\r\n\r\nUse \"frpc [command] --help\" for more information about a command.\r\n\r\n--------------------------------------------------------------------------------------------\r\nRun frpc with a single tcp proxy\r\n\r\nUsage:\r\n frpc tcp [flags]\r\n\r\nFlags:\r\n --disable_log_color disable log color in console\r\n -h, --help help for tcp\r\n -i, --local_ip string local ip (default \"127.0.0.1\")\r\n -l, --local_port int local port\r\n --log_file string console or file path (default \"console\")\r\n --log_level string log level (default \"info\")\r\n --log_max_days int log file reversed days (default 3)\r\n -p, --protocol string tcp or kcp or websocket (default \"tcp\")\r\n -n, --proxy_name string proxy name\r\n -r, --remote_port int remote port\r\n -s, --server_addr string frp server's address (default \"127.0.0.1:7000\")\r\n --tls_enable enable frpc tls\r\n -t, --token string auth token\r\n --uc use compression\r\n --ue use encryption\r\n -u, --user string user\r\n\r\nGlobal Flags:\r\n -c, --config string config file of frpc (default \"./frpc.ini\")\r\n -v, --version version of frpc\r\n\r\n-------------------------------------------------------------------------------------------------------------------\r\nRun frpc with a single udp proxy\r\n\r\nUsage:\r\n frpc udp [flags]\r\n\r\nFlags:\r\n --disable_log_color disable log color in console\r\n -h, --help help for udp\r\n -i, --local_ip string local ip (default \"127.0.0.1\")\r\n -l, --local_port int local port\r\n --log_file string console or file path (default \"console\")\r\n --log_level string log level (default \"info\")\r\n --log_max_days int log file reversed days (default 3)\r\n -p, --protocol string tcp or kcp or websocket (default \"tcp\")\r\n -n, --proxy_name string proxy name\r\n -r, --remote_port int remote port\r\n -s, --server_addr string frp server's address (default \"127.0.0.1:7000\")\r\n --tls_enable enable frpc tls\r\n -t, --token string auth token\r\n --uc use compression\r\n --ue use encryption\r\n -u, --user string user\r\n\r\nGlobal Flags:\r\n -c, --config string config file of frpc (default \"./frpc.ini\")\r\n -v, --version version of frpc\r\n----------------------------------------------------------------------------------------------------------------------------\r\nVerify that the configures is valid\r\n\r\nUsage:\r\n frpc verify [flags]\r\n\r\nFlags:\r\n -h, --help help for verify\r\n\r\nGlobal Flags:\r\n -c, --config string config file of frpc (default \"./frpc.ini\")\r\n -v, --version version of frpc\r\n\r\n--End usages and flags--", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "malware_types": [ + "trojan" + ], + "is_family": false, + "sample_refs": [ + "file--6ee289fa-fe03-5ca5-bbdf-451603a31436" + ] + }, + { + "type": "indicator", + "spec_version": "2.1", + "id": "indicator--64e4dba4-aec4-4cb4-90b6-fd07ababf48a", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "name": "SMSvcService.exe", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "indicator_types": [ + "malicious-activity" + ], + "pattern": "[file:hashes.'MD5'='b1de37bf229890ac181bdef1ad8ee0c2' OR file:hashes.'SHA-1'='ffdb3cc7ab5b01d276d23ac930eb21ffe3202d11' OR file:hashes.'SHA-256'='99b80c5ac352081a64129772ed5e1543d94cad708ba2adc46dc4ab7a0bd563f1' OR file:hashes.'SHA-512'='e41df636a36ac0cce38e7db5c2ce4d04a1a7f9bc274bdf808912d14067dc1ef478268035521d0d4b7bcf96facce7f515560b38a7ebe47995d861b9c482e07e25']", + "pattern_type": "stix", + "pattern_version": "2.1", + "valid_from": "2024-02-02T15:11:50.319139Z" + }, + { + "type": "ipv4-addr", + "spec_version": "2.1", + "id": "ipv4-addr--58669179-fc75-5d7c-aad0-0e91bd473884", + "value": "203.95.9.54", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ] + }, + { + "type": "note", + "spec_version": "2.1", + "id": "note--b2868bba-8b77-43cd-b365-db3b8441b2a6", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "content": "The IP address used to establish a connection with the remote FRPS.", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "object_refs": [ + "ipv4-addr--58669179-fc75-5d7c-aad0-0e91bd473884" + ] + }, + { + "type": "location", + "spec_version": "2.1", + "id": "location--95b8e68e-ffeb-4a90-b208-ce978d168750", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-02-02T15:11:50.33828Z", + "modified": "2024-02-02T15:11:50.33828Z", + "name": "203.95.9.54", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "description": "Domain Name: pdsguam.biz\r\nRegistry Domain ID: D15926452-BIZ\r\nRegistrar WHOIS Server: whois.godaddy.com\r\nRegistrar URL: whois.godaddy.com\r\nUpdated Date: 2023-01-15T17:08:00Z\r\nCreation Date: 2007-01-10T00:40:37Z\r\nRegistry Expiry Date: 2024-01-09T23:59:59Z\r\nRegistrar: GoDaddy.com, LLC\r\nRegistrar IANA ID: 146\r\nRegistrar Abuse Contact Email: abuse@godaddy.com\r\nRegistrar Abuse Contact Phone: +1.4806242505\r\nRegistrant Organization: Domains By Proxy, LLC\r\nRegistrant State/Province: Arizona\r\nRegistrant Country: US\r\nName Server: ns.pdsguam.biz\r\nName Server: ns2.pdsguam.biz\r\nDNSSEC: unsigned\r\n", + "region": "northern-america", + "country": "US" + }, + { + "type": "relationship", + "spec_version": "2.1", + "id": "relationship--57519801-6fd1-473b-9e0d-d113f32a6cb5", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "relationship_type": "communicates-with", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "source_ref": "malware--664d9112-90fe-4d52-b07b-105daad69618", + "target_ref": "ipv4-addr--2e9778d4-e97e-56dc-a8fd-fd39a8bfe9d5" + }, + { + "type": "relationship", + "spec_version": "2.1", + "id": "relationship--bcccf3d1-580d-4d74-810c-9471d8df2c9a", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "relationship_type": "communicates-with", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "source_ref": "malware--d90aea2c-20f7-4125-b930-1ec855c27f98", + "target_ref": "ipv4-addr--58669179-fc75-5d7c-aad0-0e91bd473884" + }, + { + "type": "report", + "spec_version": "2.1", + "id": "report--0bfb40d7-c9e3-4cd3-a383-702cfefec39d", + "created_by_ref": "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "created": "2024-01-16T20:09:58.000Z", + "modified": "2024-01-16T20:09:58.000Z", + "name": "MAR-10448362.c1.v1", + "object_marking_refs": [ + "marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487", + "marking-definition--d896763f-3f6f-4917-86e8-1a4b043d9771" + ], + "description": "CISA received three files for analysis obtained from a critical infrastructure compromised by the People\u2019s Republic of China (PRC) state-sponsored cyber group known as Volt Typhoon.\r\n\r\nThe submitted files enable discovery and command-and-control (C2): (1) An open source Fast Reverse Proxy Client (FRPC) tool used to open a reverse proxy between the compromised system and a Volt Typhoon C2 server; (2) a Fast Reverse Proxy (FRP) that can be used to reveal servers situated behind a network firewall or obscured through Network Address Translation (NAT); and (3) a publicly available port scanner called ScanLine.\r\n\r\nFor more information on Volt Typhoon see, joint Cybersecurity Advisory PRC State-Sponsored Actors Compromise, and Maintain Persistent Access to, U.S. Critical Infrastructure. For more information on PRC state-sponsored malicious cyber activity, see CISA\u2019s China Cyber Threat Overview and Advisories, webpage.", + "report_types": [ + "observed-data", + "malware", + "indicator" + ], + "published": "2024-01-16T20:09:58Z", + "object_refs": [ + "identity--8e112e72-aa8f-4190-a359-28a9abae2896", + "file--6f60abb6-c78c-5fa5-8275-08ed20ad058f", + "malware-analysis--c577e744-04a1-49d3-b636-4ff7d836bb6b", + "malware-analysis--57df436c-ff51-45e7-9455-2dcf69685336", + "malware-analysis--92c4b747-2167-4c2f-a023-1f7a46868668", + "malware-analysis--4ed8abe7-b4cd-4523-a0e3-433a90d94e3d", + "malware-analysis--4d173e26-37d0-4c55-94ce-1dd701d5957d", + "malware-analysis--efd0ed4a-c9fe-47c9-9c2b-aa676e676ae0", + "malware-analysis--28c48841-d813-4522-baa8-4021ebe3dacc", + "malware-analysis--9e9777f4-44db-4db2-8a64-11fa9670f67f", + "malware-analysis--967dd29b-dc96-43e2-9869-2ff448474a9e", + "malware--664d9112-90fe-4d52-b07b-105daad69618", + "indicator--8a72c4d8-0846-400d-8812-6105d4f98dc4", + "ipv4-addr--2e9778d4-e97e-56dc-a8fd-fd39a8bfe9d5", + "note--1e5d2e39-ec90-4553-961b-3877d97d39c4", + "location--34610caa-9135-4875-ac37-4746088dd006", + "file--70bfcb9c-8313-5dac-a096-ff7f5578721c", + "malware-analysis--c3964dad-86fe-4235-a174-49bd49422ee7", + "malware-analysis--6996c7b2-7f76-49d4-bb56-985101b2ce9f", + "malware-analysis--004e4ae2-0349-4464-b9d9-33a1cce2e8b1", + "malware-analysis--a5cc9df5-c105-47ab-9f12-5ac694bae64d", + "malware-analysis--b6e682d8-10ab-4f05-962c-7ea774f1920d", + "malware-analysis--2f43287b-bb70-4d99-ab26-5adbcbbecedd", + "malware-analysis--c13c10ef-1fdc-4855-8555-8fc0bade8818", + "malware-analysis--de0c9309-93b5-44a4-8f58-0f5d93079a34", + "malware-analysis--a08a9f25-d8e2-41a4-bbea-86d9c217a64e", + "malware-analysis--ca9c3dc5-bb4f-4b7f-99db-0c653f95d415", + "malware-analysis--3fefb2c2-d39c-4028-8c2a-f3b8684d141b", + "malware-analysis--b565d211-a4b1-46d1-87d2-6b4364aa3636", + "malware-analysis--2d3f9171-807d-4388-96e0-4d844fc21968", + "malware-analysis--a083e2ec-1f21-4a6b-bfa0-f259abbda95a", + "malware-analysis--2ece688f-fd0d-45b4-982e-4cf47cdfa4a0", + "malware-analysis--a54e9075-ab72-4adb-a73f-703f14611e0f", + "malware-analysis--55967892-3008-460e-83f0-7a1f92f3c924", + "malware-analysis--a3040dc9-9cd9-4b96-9c55-a49587f7f9cb", + "malware--8dff02fd-d899-4b84-a668-5be524f7da05", + "indicator--333ee8b9-18f8-4cc8-8e63-f04b4d0fecc7", + "file--6ee289fa-fe03-5ca5-bbdf-451603a31436", + "malware-analysis--f62bbb36-6561-431c-94b5-cedbb0e30604", + "malware-analysis--98c0e7b0-3117-4f30-a73c-55b51a24384b", + "malware-analysis--57abe6be-190b-48a9-9e83-58204f847fb4", + "malware-analysis--d79545b2-1d05-40c8-bf71-689428c36e1b", + "malware-analysis--5dee8895-7db8-4649-b502-e0ec64c8b871", + "malware-analysis--1bd586c5-5182-47d6-b755-8e77076709d6", + "malware-analysis--188dc319-886c-4b27-9bac-fbb06c0401ae", + "malware-analysis--e0c25271-10ef-4595-b252-0650f428e273", + "malware-analysis--bb30dc97-78b7-4456-a11f-1cf550e948dd", + "malware-analysis--dfd5d242-6931-4e6e-9686-05b968380c8d", + "malware--d90aea2c-20f7-4125-b930-1ec855c27f98", + "indicator--64e4dba4-aec4-4cb4-90b6-fd07ababf48a", + "ipv4-addr--58669179-fc75-5d7c-aad0-0e91bd473884", + "note--b2868bba-8b77-43cd-b365-db3b8441b2a6", + "location--95b8e68e-ffeb-4a90-b208-ce978d168750", + "relationship--57519801-6fd1-473b-9e0d-d113f32a6cb5", + "relationship--bcccf3d1-580d-4d74-810c-9471d8df2c9a" + ] + } + ] +} \ No newline at end of file diff --git a/tests/data/cisa_stix_test_cmds.storm b/tests/data/cisa_stix_test_cmds.storm new file mode 100644 index 0000000..655753a --- /dev/null +++ b/tests/data/cisa_stix_test_cmds.storm @@ -0,0 +1,7 @@ +$x="https://www.cisa.gov/sites/default/files/2024-02/MAR-10448362.c1.v1.CLEAR_stix2.json" +$resp=$lib.inet.http.get($x) +$bundle = $lib.json.load($resp.body) +$c=$lib.stix.import.config() +$lib.print($lib.json.save($c)) +yield $lib.stix.import.ingest($bundle, config=$c) +$lib.print($bundle) \ No newline at end of file diff --git a/tests/data/cisa_stix_warnings.txt b/tests/data/cisa_stix_warnings.txt new file mode 100644 index 0000000..06ab3c1 --- /dev/null +++ b/tests/data/cisa_stix_warnings.txt @@ -0,0 +1,8 @@ +WARNING: STIX bundle ingest has no object definition for: marking-definition. +..... +WARNING: STIX bundle ingest has no object definition for: file. +WARNING: STIX bundle ingest has no object definition for: malware-analysis. +................ +WARNING: STIX bundle ingest has no object definition for: ipv4-addr. +WARNING: STIX bundle ingest has no object definition for: note. +WARNING: STIX bundle ingest has no object definition for: location. \ No newline at end of file diff --git a/tests/data/expand_stix_conf.txt b/tests/data/expand_stix_conf.txt new file mode 100644 index 0000000..036c098 --- /dev/null +++ b/tests/data/expand_stix_conf.txt @@ -0,0 +1,177 @@ +{ + "addbundle": true, + "bundle": { + "storm": " + it:sec:stix:bundle:id=$bundle.id + return($node) + [ it:sec:stix:bundle=* :id=$bundle.id ] + return($node) + " + }, + "objects": { + "intrusion-set": { + "storm": " + ($ok, $name) = $lib.trycast(ou:name, $object.name) + if $ok { + + ou:name=$name -> ou:org + { for $alias in $object.aliases { [ :names?+=$alias ] } } + return($node) + + [ ou:org=* :name=$name ] + { for $alias in $object.aliases { [ :names?+=$alias ] } } + return($node) + } + " + }, + "identity": { + "storm": " + switch $object.identity_class { + group: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]} + organization: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]} + individual: {[ ps:contact=(stix, identity, $object.id) :name?=$object.name ]} + system: {[ it:host=(stix, identity, $object.id) :name?=$object.name ]} + } + " + }, + "tool": { + "storm": " + ($ok, $name) = $lib.trycast(it:prod:softname, $object.name) + if $ok { + it:prod:softname=$name -> it:prod:soft + return($node) + [ it:prod:soft=* :name=$name ] + return($node) + } + " + }, + "threat-actor": { + "storm": " + [ ps:contact=(stix, threat-actor, $object.id) + :name?=$object.name + :desc?=$object.description + :names?=$object.aliases + ] + $node.data.set(stix:object, $object) + return($node) + " + }, + "course-of-action": { + "storm": " + [ risk:mitigation=(stix, course-of-action, $object.id) + :name?=$object.name + :desc?=$object.description + ] + $node.data.set(stix:object, $object) + return($node) + " + }, + "campaign": { + "storm": " + [ ou:campaign=(stix, campaign, $object.id) + :name?=$object.name + :desc?=$object.description + .seen?=$object.last_seen + .seen?=$object.first_seen + ] + $node.data.set(stix:object, $object) + return($node) + " + }, + "malware": { + "storm": " + ($ok, $name) = $lib.trycast(it:prod:softname, $object.name) + if $ok { + it:prod:softname=$name -> it:prod:soft + return($node) + [ it:prod:soft=* :name=$name ] + return($node) + } + " + }, + "indicator": { + "storm": " + $guid = $lib.guid(stix, indicator, $object.id) + switch $object.pattern_type { + + yara: {[ it:app:yara:rule=$guid + :name?=$object.name + :text?=$object.pattern + ]} + + snort: {[ it:app:snort:rule=$guid + :name?=$object.name + :text?=$object.pattern + ]} + + *: {[ it:sec:stix:indicator=$guid + :name?=$object.name + :pattern?=$object.pattern + :created?=$object.created + :updated?=$object.modified] + | scrape --refs :pattern + } + } + $node.data.set(stix:object, $object) + return($node) + " + }, + "report": { + "storm": " + [ media:news=(stix, report, $object.id) + :title?=$object.name + :summary?=$object.description + :published?=$object.published + ] + $node.data.set(stix:object, $object) + return($node) + " + } + }, + "relationships": [ + { + "type": [ + "campaign", + "attributed-to", + "intrusion-set" + ], + "storm": " + $n1node.props.org = $n2node + " + }, + { + "type": [ + "intrusion-set", + "attributed-to", + "threat-actor" + ], + "storm": " + $n2node.props.org = $n1node + " + }, + { + "type": [ + null, + "uses", + null + ], + "storm": "yield $n1node [ +(uses)> { yield $n2node } ]" + }, + { + "type": [ + null, + "indicates", + null + ], + "storm": "yield $n1node [ +(indicates)> { yield $n2node } ]" + }, + { + "type": [ + "threat-actor", + "attributed-to", + "identity" + ], + "storm": "" + } + ] +} \ No newline at end of file diff --git a/tests/data/original_stix_conf.json b/tests/data/original_stix_conf.json new file mode 100644 index 0000000..d649c9c --- /dev/null +++ b/tests/data/original_stix_conf.json @@ -0,0 +1,77 @@ +{ + "addbundle": true, + "bundle": { + "storm": "\n it:sec:stix:bundle:id=$bundle.id\n return($node)\n [ it:sec:stix:bundle=* :id=$bundle.id ]\n return($node)\n " + }, + "objects": { + "intrusion-set": { + "storm": "\n ($ok, $name) = $lib.trycast(ou:name, $object.name)\n if $ok {\n\n ou:name=$name -> ou:org\n { for $alias in $object.aliases { [ :names?+=$alias ] } }\n return($node)\n\n [ ou:org=* :name=$name ]\n { for $alias in $object.aliases { [ :names?+=$alias ] } }\n return($node)\n }\n " + }, + "identity": { + "storm": "\n switch $object.identity_class {\n group: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]}\n organization: {[ ps:contact=(stix, identity, $object.id) :orgname?=$object.name ]}\n individual: {[ ps:contact=(stix, identity, $object.id) :name?=$object.name ]}\n system: {[ it:host=(stix, identity, $object.id) :name?=$object.name ]}\n }\n " + }, + "tool": { + "storm": "\n ($ok, $name) = $lib.trycast(it:prod:softname, $object.name)\n if $ok {\n it:prod:softname=$name -> it:prod:soft\n return($node)\n [ it:prod:soft=* :name=$name ]\n return($node)\n }\n " + }, + "threat-actor": { + "storm": "\n [ ps:contact=(stix, threat-actor, $object.id)\n :name?=$object.name\n :desc?=$object.description\n :names?=$object.aliases\n ]\n $node.data.set(stix:object, $object)\n return($node)\n " + }, + "course-of-action": { + "storm": "\n [ risk:mitigation=(stix, course-of-action, $object.id)\n :name?=$object.name\n :desc?=$object.description\n ]\n $node.data.set(stix:object, $object)\n return($node)\n " + }, + "campaign": { + "storm": "\n [ ou:campaign=(stix, campaign, $object.id)\n :name?=$object.name\n :desc?=$object.description\n .seen?=$object.last_seen\n .seen?=$object.first_seen\n ]\n $node.data.set(stix:object, $object)\n return($node)\n " + }, + "malware": { + "storm": "\n ($ok, $name) = $lib.trycast(it:prod:softname, $object.name)\n if $ok {\n it:prod:softname=$name -> it:prod:soft\n return($node)\n [ it:prod:soft=* :name=$name ]\n return($node)\n }\n " + }, + "indicator": { + "storm": "\n $guid = $lib.guid(stix, indicator, $object.id)\n switch $object.pattern_type {\n\n yara: {[ it:app:yara:rule=$guid\n :name?=$object.name\n :text?=$object.pattern\n ]}\n\n snort: {[ it:app:snort:rule=$guid\n :name?=$object.name\n :text?=$object.pattern\n ]}\n\n *: {[ it:sec:stix:indicator=$guid\n :name?=$object.name\n :pattern?=$object.pattern\n :created?=$object.created\n :updated?=$object.modified]\n | scrape --refs :pattern\n }\n }\n $node.data.set(stix:object, $object)\n return($node)\n " + }, + "report": { + "storm": "\n [ media:news=(stix, report, $object.id)\n :title?=$object.name\n :summary?=$object.description\n :published?=$object.published\n ]\n $node.data.set(stix:object, $object)\n return($node)\n " + } + }, + "relationships": [ + { + "type": [ + "campaign", + "attributed-to", + "intrusion-set" + ], + "storm": "\n $n1node.props.org = $n2node\n " + }, + { + "type": [ + "intrusion-set", + "attributed-to", + "threat-actor" + ], + "storm": "\n $n2node.props.org = $n1node\n " + }, + { + "type": [ + null, + "uses", + null + ], + "storm": "yield $n1node [ +(uses)> { yield $n2node } ]" + }, + { + "type": [ + null, + "indicates", + null + ], + "storm": "yield $n1node [ +(indicates)> { yield $n2node } ]" + }, + { + "type": [ + "threat-actor", + "attributed-to", + "identity" + ], + "storm": "" + } + ] +} \ No newline at end of file