Scan for Malware (Everything and the Kitchen Sink)

MS-DOS button to use various programs to scan a file/folder for malware.

//Sam Tulach VT uploader / or Errante VT Command 
//For either option, you will need to create a user command and then reference it here. 
//Examples of how to achieve this are available on resource.dopus. 
VT 

//Scan with Defender
//Must turn on periodic scanning for Defender to work. 
//Adjust path to MpCmdRun.exe on your PC. 
@admin
@echo off
for %%F in ({allfilepath$}) do (
  "C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25110.6-0\MpCmdRun.exe" -Scan -ScanType 3 -File "%%~fF"
)

//Eset Nod32 Scan
//Must add ecls.exe to your path in environment variables. 
@echo off
ecls {allfilepath$} /files /subdir /arch /sfx /rtp /heur /adv-heur /pattern /unwanted /unsafe /clean-mode=standard /quarantine

//Emsisoft Scanner 
//Use correct path to a2cmd.exe.
@admin
@echo off
for %%F in ({allfilepath$}) do (
  "C:\EEK\bin64\a2cmd.exe" /f="%%~fF" /pup /a /n /log="%temp%\EEK_scan.log"
)

//Loki Scan
@echo off
@admin
"E:\OneDrive\New Install\loki\loki.exe" -p {filepath$} --noprocscan --nolisten --nopesieve --allreasons

//Yara Scan
//I am using a wrapper that i created but just put in the path to yara64.exe instead. 
@admin
@echo off
cmd /k py "C:\Utilities\Yara\yara_triage.py" --target "{allfilepath$}"

//Malwarebytes (You will need to create a user command containing the following, and then reference it here - ContextMenu LABEL="Scan with Malwarebytes"
//Malwarebytes_(Scan_With) - this is the name of the user command. 

//Sirius LLM (Same as above)
//Sirius_(Scan_With)

Example CLI output:

Alternatively use a Python Wrapper for cleaner output

Example Python Wrapper Code - save as "multi_scan.py" - not thoroughly tested

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import shutil
import subprocess
import tempfile
import datetime
from pathlib import Path

# ============================================================
# CONFIG
# ============================================================

DEFENDER = r"C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25110.6-0\MpCmdRun.exe"
ESET = "ecls.exe"  # or full path if not on PATH
EMSISOFT = r"C:\EEK\bin64\a2cmd.exe"
LOKI = r"E:\OneDrive\New Install\loki\loki.exe"
YARA_WRAPPER = r"C:\Utilities\Yara\yara_triage.py"

ENABLE_DEFENDER = True
ENABLE_ESET = True
ENABLE_EMSISOFT = True
ENABLE_LOKI = True
ENABLE_YARA = True

LOG_DIR = Path.home() / "Desktop" / "MultiScanLogs"

# ============================================================
# ANSI / UI
# ============================================================

class C:
    RESET = "\033[0m"
    BOLD = "\033[1m"
    DIM = "\033[2m"

    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    BLUE = "\033[34m"
    CYAN = "\033[36m"
    WHITE = "\033[37m"

    BRIGHT_RED = "\033[91m"
    BRIGHT_GREEN = "\033[92m"
    BRIGHT_YELLOW = "\033[93m"
    BRIGHT_BLUE = "\033[94m"
    BRIGHT_CYAN = "\033[96m"

def enable_windows_ansi() -> None:
    if os.name != "nt":
        return
    try:
        import ctypes
        kernel32 = ctypes.windll.kernel32
        handle = kernel32.GetStdHandle(-11)  # STD_OUTPUT_HANDLE
        mode = ctypes.c_uint32()
        if kernel32.GetConsoleMode(handle, ctypes.byref(mode)):
            kernel32.SetConsoleMode(handle, mode.value | 0x0004)
    except Exception:
        pass

def hline(char: str = "=") -> None:
    print(char * 70)

def banner(title: str) -> None:
    hline("=")
    print(f"{C.BOLD}{C.BRIGHT_CYAN}  {title}{C.RESET}")
    hline("=")

def section(title: str) -> None:
    print()
    print(f"{C.BOLD}{C.BRIGHT_BLUE}[{title}]{C.RESET}")
    hline("-")

def status_ok(text: str) -> None:
    print(f"{C.BRIGHT_GREEN}{text}{C.RESET}")

def status_warn(text: str) -> None:
    print(f"{C.BRIGHT_YELLOW}{text}{C.RESET}")

def status_err(text: str) -> None:
    print(f"{C.BRIGHT_RED}{text}{C.RESET}")

def info(label: str, value: str) -> None:
    print(f"{C.DIM}{label:<10}: {value}{C.RESET}")

# ============================================================
# HELPERS
# ============================================================

def timestamp() -> str:
    return datetime.datetime.now().strftime("%Y%m%d_%H%M%S")

def ensure_log_dir() -> None:
    LOG_DIR.mkdir(parents=True, exist_ok=True)

def quote_cmd(cmd: list[str]) -> str:
    return subprocess.list2cmdline(cmd)

def have_executable(path_or_name: str) -> bool:
    if os.path.isabs(path_or_name):
        return os.path.exists(path_or_name)
    return shutil.which(path_or_name) is not None

def print_streamed_output(proc: subprocess.Popen) -> None:
    assert proc.stdout is not None
    for line in proc.stdout:
        line = line.rstrip("\r\n")
        low = line.lower()

        if any(x in low for x in ("detected", "threat", "malware", "warning", "suspicious", "infected")):
            print(f"{C.BRIGHT_YELLOW}{line}{C.RESET}")
        elif any(x in low for x in ("error", "failed", "unable to", "cannot", "incorrect parameters")):
            print(f"{C.BRIGHT_RED}{line}{C.RESET}")
        elif any(x in low for x in ("cleaned", "ok", "scan completed", "finished", "no threats")):
            print(f"{C.BRIGHT_GREEN}{line}{C.RESET}")
        else:
            print(line)

def run_command(name: str, cmd: list[str]) -> int:
    section(name)
    print(f"{C.DIM}Command: {quote_cmd(cmd)}{C.RESET}")
    hline("-")

    try:
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True,
            encoding="utf-8",
            errors="replace",
            shell=False,
        )
    except FileNotFoundError:
        status_err(f"[{name} ERROR] Executable not found.")
        return 9001
    except Exception as e:
        status_err(f"[{name} ERROR] {e}")
        return 9002

    print_streamed_output(proc)
    rc = proc.wait()

    hline("-")
    if rc == 0:
        status_ok(f"[{name} OK] Exit code: {rc}")
    else:
        status_warn(f"[{name} EXIT] Exit code: {rc}")
    return rc

def normalize_targets(args: list[str]) -> list[Path]:
    out: list[Path] = []
    for raw in args:
        raw = raw.strip().strip('"')
        if not raw:
            continue
        p = Path(raw)
        out.append(p)
    return out

# ============================================================
# SCANNERS
# ============================================================

def run_defender(target: Path) -> int:
    if not ENABLE_DEFENDER:
        return 0
    cmd = [DEFENDER, "-Scan", "-ScanType", "3", "-File", str(target)]
    return run_command("DEFENDER", cmd)

def run_eset(target: Path) -> int:
    if not ENABLE_ESET:
        return 0
    cmd = [
        ESET,
        str(target),
        "/files",
        "/subdir",
        "/arch",
        "/sfx",
        "/rtp",
        "/heur",
        "/adv-heur",
        "/pattern",
        "/unwanted",
        "/unsafe",
        "/clean-mode=standard",
        "/quarantine",
    ]
    return run_command("ESET", cmd)

def run_emsisoft(target: Path, stamp: str) -> int:
    if not ENABLE_EMSISOFT:
        return 0
    log_file = LOG_DIR / f"Emsisoft_{target.stem}_{stamp}.log"
    cmd = [
        EMSISOFT,
        "/f",
        str(target),
        "/pup",
        "/a",
        "/n",
        "/log",
        str(log_file),
    ]
    return run_command("EMSISOFT", cmd)

def run_loki(target: Path) -> int:
    if not ENABLE_LOKI:
        return 0
    cmd = [
        LOKI,
        "-p",
        str(target),
        "--noprocscan",
        "--nolisten",
        "--nopesieve",
    ]
    return run_command("LOKI", cmd)

def run_yara(target: Path) -> int:
    if not ENABLE_YARA:
        return 0
    cmd = [
        sys.executable,
        YARA_WRAPPER,
        "--target",
        str(target),
    ]
    return run_command("YARA", cmd)

# ============================================================
# VALIDATION
# ============================================================

def preflight() -> None:
    banner("MULTI-SCANNER")

    ensure_log_dir()

    info("Time", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    info("Logs", str(LOG_DIR))
    print()

    checks = [
        ("Defender", ENABLE_DEFENDER, DEFENDER),
        ("ESET", ENABLE_ESET, ESET),
        ("Emsisoft", ENABLE_EMSISOFT, EMSISOFT),
        ("Loki", ENABLE_LOKI, LOKI),
        ("YARA", ENABLE_YARA, YARA_WRAPPER),
    ]

    for name, enabled, path in checks:
        if not enabled:
            status_warn(f"{name}: disabled")
            continue
        if have_executable(path):
            status_ok(f"{name}: found")
        else:
            status_err(f"{name}: missing -> {path}")

def scan_target(target: Path) -> dict[str, int]:
    print()
    banner(f"TARGET: {target}")

    if not target.exists():
        status_err("Target does not exist.")
        return {
            "DEFENDER": 9990,
            "ESET": 9990,
            "EMSISOFT": 9990,
            "LOKI": 9990,
            "YARA": 9990,
        }

    stamp = timestamp()
    results: dict[str, int] = {}

    if ENABLE_DEFENDER:
        results["DEFENDER"] = run_defender(target)
    if ENABLE_ESET:
        results["ESET"] = run_eset(target)
    if ENABLE_EMSISOFT:
        results["EMSISOFT"] = run_emsisoft(target, stamp)
    if ENABLE_LOKI:
        results["LOKI"] = run_loki(target)
    if ENABLE_YARA:
        results["YARA"] = run_yara(target)

    return results

def print_summary(all_results: dict[Path, dict[str, int]]) -> None:
    print()
    banner("SUMMARY")

    for target, results in all_results.items():
        print(f"{C.BOLD}{target}{C.RESET}")
        for scanner, rc in results.items():
            if rc == 0:
                print(f"  {C.BRIGHT_GREEN}{scanner:<10} OK    ({rc}){C.RESET}")
            else:
                print(f"  {C.BRIGHT_YELLOW}{scanner:<10} EXIT  ({rc}){C.RESET}")
        print()

# ============================================================
# MAIN
# ============================================================

def main() -> int:
    enable_windows_ansi()
    preflight()

    targets = normalize_targets(sys.argv[1:])
    if not targets:
        print()
        status_err("No target(s) supplied.")
        print()
        print("Usage:")
        print(r'  py multi_scan.py "C:\path\file.exe"')
        print(r'  py multi_scan.py "C:\path\file1.exe" "C:\path\file2.dll"')
        input("\nPress Enter to exit...")
        return 1

    all_results: dict[Path, dict[str, int]] = {}

    for target in targets:
        all_results[target] = scan_target(target)

    print_summary(all_results)
    input("Press Enter to exit...")
    return 0

if __name__ == "__main__":
    raise SystemExit(main())

Button code to launch python wrapper

@admin
py "E:\OneDrive\New Install\Yara\multi_scan.py" {allfilepath$}

1 Like

Updated to include Yara Scanners and Sirius LLM.

This is the final version of my python wrapper. Unfortunately, i cannot share due to licensing.