SSDeepReputation
Calculate ssdeep reputation based on similar files (by ssdeep similarity) on the system.
python · Common Scripts
Source
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 from typing import Any, cast REPUTATIONS = {0: "None", 1: "Good", 2: "Suspicious", 3: "Bad"} def get_investigation_ids(indicator: dict[str, Any]) -> list[str]: """Get investigation IDs from indicator, supporting both 'investigationIDs' and 'investigationID' keys. Args: indicator: The indicator object Returns: List of investigation IDs """ inv_ids = indicator.get("investigationIDs") if inv_ids is not None: return inv_ids if isinstance(inv_ids, list) else [inv_ids] inv_id = indicator.get("investigationID") if inv_id is not None: return [inv_id] if not isinstance(inv_id, list) else inv_id return [] def get_indicator_from_value(indicator_value: str | None) -> dict[str, Any] | None: try: if not indicator_value: return None res = demisto.executeCommand("findIndicators", {"value": indicator_value}) if res and isinstance(res, list) and len(res) > 0: contents = res[0].get("Contents") if contents and isinstance(contents, list) and len(contents) > 0: return contents[0] return None except Exception: return None def get_ssdeep_related_indicators(ssdeep_indicator: dict[str, Any]) -> list[dict[str, Any]]: related_indicators: list[dict[str, Any] | None] = [ssdeep_indicator] for inv_id in get_investigation_ids(ssdeep_indicator): try: res = demisto.executeCommand("getContext", {"id": inv_id}) if res and isinstance(res, list) and len(res) > 0: contents = res[0].get("Contents", {}) context = contents.get("context") if isinstance(contents, dict) else {} # Sanitize ssdeep value to prevent DT query syntax errors ssdeep_value = str(ssdeep_indicator.get("value", "")).replace("'", "\\'") file_obj = demisto.dt(context, f"File(val.SSDeep == '{ssdeep_value}')") if file_obj is None: file_obj = {} elif isinstance(file_obj, list) and len(file_obj) > 0: file_obj = file_obj[0] if isinstance(file_obj, dict): related_indicators.append(get_indicator_from_value(file_obj.get("MD5"))) related_indicators.append(get_indicator_from_value(file_obj.get("SHA1"))) related_indicators.append(get_indicator_from_value(file_obj.get("SHA256"))) except Exception: continue return [x for x in related_indicators if x is not None] def main(): ssdeep_value = demisto.args().get("input") current_incident_id = demisto.investigation().get("id") res = demisto.executeCommand( "similarSsdeep", { "value": ssdeep_value, "daysTimeFrame": int(demisto.args().get("timeFrameDays", "1")), "threshold": int(demisto.args().get("threshold", "50")), }, ) ssdeep_indicators: list[dict[str, Any]] = [] if res and isinstance(res, list) and len(res) > 0: contents = res[0].get("Contents", []) if isinstance(contents, list): ssdeep_indicators = [ cast(dict[str, Any], x.get("indicator") or {}) for x in contents if isinstance(x, dict) and isinstance(x.get("indicator"), dict) ] ssdeep_indicator = get_indicator_from_value(ssdeep_value) if not ssdeep_indicator: # make the current ssdeep part of the current invastigation ssdeep_indicator = {"investigationIDs": [current_incident_id], "score": 0} else: # make sure the current ssdeep part of the current invastigation # Check if investigationIDs key exists (supporting both singular and plural forms) if "investigationIDs" not in ssdeep_indicator and "investigationID" not in ssdeep_indicator: # Neither key exists - create investigationIDs ssdeep_indicator["investigationIDs"] = [current_incident_id] else: # At least one key exists - get the IDs and check if current_incident_id is in them inv_ids = get_investigation_ids(ssdeep_indicator) if current_incident_id not in inv_ids: # Need to add current_incident_id if "investigationIDs" in ssdeep_indicator: # investigationIDs exists - use setdefault for defensive programming # Protects against edge case where key exists but value is None or not a list ssdeep_indicator.setdefault("investigationIDs", []).append(current_incident_id) elif "investigationID" in ssdeep_indicator: # Only investigationID exists - convert to investigationIDs and add new ID existing = ssdeep_indicator.pop("investigationID") existing_list = [existing] if not isinstance(existing, list) else existing existing_list.append(current_incident_id) ssdeep_indicator["investigationIDs"] = existing_list ssdeep_indicators.append(ssdeep_indicator) related_indicators = [] for i in ssdeep_indicators: related_indicators += get_ssdeep_related_indicators(i) max_score = max([x.get("score", 0) for x in related_indicators]) max_score_indicator = next(x for x in related_indicators if x.get("score", 0) == max_score) if isinstance(max_score, int) and max_score > ssdeep_indicator.get("score", 0) and max_score > 1: entry = { "Type": entryTypes["note"], "HumanReadable": f"Similarity to {REPUTATIONS[max_score_indicator['score']]}" f" {max_score_indicator['indicator_type']}:{max_score_indicator['value']}", "ReadableContentsFormat": formats["markdown"], "Contents": max_score, "ContentsFormat": formats["text"], } ec = {"DBotScore": {"Indicator": ssdeep_value, "Type": "ssdeep", "Vendor": "DBot", "Score": max_score}} entry["EntryContext"] = ec demisto.results(entry) else: demisto.results(ssdeep_indicator.get("score", 0)) if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
Calculates the SSdeep reputation based on similar files (by ssdeep similarity) on the system.
Script Data
| Name | Description |
|---|---|
| Script Type | python |
| Tags | reputation |
Inputs
| Argument Name | Description |
|---|---|
| input | The SSdeep value. |
| timeFrameDays | Checks similar values in this time frame (in days). |
| threshold | Considerers similar SSdeep above this threshold. |
Outputs
There are no outputs for this script.