diff --git a/analyzer/windows/data/yara/Formbook.yar b/analyzer/windows/data/yara/Formbook.yar index e2e94223605..8c65140d05b 100644 --- a/analyzer/windows/data/yara/Formbook.yar +++ b/analyzer/windows/data/yara/Formbook.yar @@ -71,5 +71,5 @@ rule FormconfB $config = {40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 [4] 48 81 EC [2] 00 00 45 33 ?? 33 C0 4C 8B E9 4C 89} $sleep = {B9 88 13 00 00 FF D7 44 8B 9B [4] 41 81 FB 00 01 00 00 75 ?? 48 39 B3 [4] 74 ?? 8B 83 [4] 05 00 20 00 00 39 B0} condition: - 3 of them + $decoy and any of ($c2_*) and ($config or $sleep) } diff --git a/lib/cuckoo/common/utils.py b/lib/cuckoo/common/utils.py index 0d4281bc2e8..1b1064e87a9 100644 --- a/lib/cuckoo/common/utils.py +++ b/lib/cuckoo/common/utils.py @@ -841,6 +841,16 @@ def get_options(optstring: str): ) +def option_enabled(optstring: Union[str, None], option_name: str) -> bool: + """Return True when an option is set to a truthy value (1/true/yes).""" + return option_dict_enabled(get_options(optstring), option_name) + + +def option_dict_enabled(options: dict, option_name: str) -> bool: + """Return True when an already-parsed option is set to a truthy value (1/true/yes).""" + return str(options.get(option_name, "")).strip().lower() in {"1", "true", "yes"} + + # get iface ip def get_ip_address(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) diff --git a/lib/cuckoo/core/plugins.py b/lib/cuckoo/core/plugins.py index 7998a75b027..ffea9f76540 100644 --- a/lib/cuckoo/core/plugins.py +++ b/lib/cuckoo/core/plugins.py @@ -28,7 +28,7 @@ from lib.cuckoo.common.mapTTPs import mapTTP from lib.cuckoo.common.path_utils import path_exists from lib.cuckoo.common.scoring import calc_scoring -from lib.cuckoo.common.utils import add_family_detection +from lib.cuckoo.common.utils import add_family_detection, get_options, option_dict_enabled from lib.cuckoo.core.database import Database from utils.community_blocklist import blocklist @@ -268,6 +268,10 @@ def __init__(self, task, results): self.cfg = processing_cfg self.cuckoo_cfg = Config() self.results = results + task_opts = task.get("_options_parsed") + if not isinstance(task_opts, dict): + task_opts = get_options(task.get("options")) + self.minproc = option_dict_enabled(task_opts, "minproc") def process(self, module): """Run a processing module. @@ -346,6 +350,14 @@ def run(self): # If no modules are loaded, return an empty dictionary. if processing_list: processing_list.sort(key=lambda module: module.order) + if self.minproc: + allowed = {"AnalysisInfo", "BehaviorAnalysis", "Debug"} + processing_list = [module for module in processing_list if module.__name__ in allowed] + log.info( + "minproc enabled for task %s: running minimal processing modules: %s", + self.task.get("id"), + ", ".join(module.__name__ for module in processing_list) or "none", + ) # Run every loaded processing module. for module in processing_list: diff --git a/utils/process.py b/utils/process.py index 695c39888ad..8babe538cce 100644 --- a/utils/process.py +++ b/utils/process.py @@ -39,7 +39,7 @@ from lib.cuckoo.common.config import Config from lib.cuckoo.common.constants import CUCKOO_ROOT from lib.cuckoo.common.path_utils import path_delete, path_exists, path_mkdir -from lib.cuckoo.common.utils import get_options +from lib.cuckoo.common.utils import get_options, option_dict_enabled from lib.cuckoo.core.database import Database, init_database from lib.cuckoo.core.data.task import ( TASK_COMPLETED, @@ -122,10 +122,10 @@ def process( task_dict = task.to_dict() or {} task_id = task_dict.get("id") or 0 + task_options = get_options(task_dict.get("options")) + task_dict["_options_parsed"] = task_options # cluster mode - main_task_id = False - if "main_task_id" in task_dict.get("options", ""): - main_task_id = get_options(task_dict["options"]).get("main_task_id", 0) + main_task_id = task_options.get("main_task_id", 0) if "main_task_id" in task_options else False # ToDo new logger here per_analysis_handler = init_per_analysis_logging(tid=str(task_id), debug=debug) @@ -133,6 +133,7 @@ def process( setproctitle(f"{original_proctitle} [Task {task_id}]") results = {"statistics": {"processing": [], "signatures": [], "reporting": []}} try: + minproc = option_dict_enabled(task_options, "minproc") if memory_debugging: gc.collect() log.info("(1) GC object counts: %d, %d", len(gc.get_objects()), len(gc.garbage)) @@ -145,7 +146,10 @@ def process( gc.collect() log.info("(3) GC object counts: %d, %d", len(gc.get_objects()), len(gc.garbage)) - RunSignatures(task=task_dict, results=results).run() + if not minproc: + RunSignatures(task=task_dict, results=results).run() + else: + log.info("minproc enabled for task %s: skipping signatures", task_id) if memory_debugging: gc.collect() log.info("(4) GC object counts: %d, %d", len(gc.get_objects()), len(gc.garbage)) diff --git a/web/templates/submission/index.html b/web/templates/submission/index.html index ed852350e95..991e4954991 100644 --- a/web/templates/submission/index.html +++ b/web/templates/submission/index.html @@ -442,6 +442,10 @@
debugminprocdebugminprocbp0...bp3