jerzy99jerzy/phantomatics
GitHub: jerzy99jerzy/phantomatics
将社交媒体多源行为信号融合为加权图并通过社区发现检测协同虚假行为的分析管线,刻意不做自动化归因。
Stars: 0 | Forks: 0
# Phantomatics
用于社交媒体数据的协同虚假行为检测。找出
**哪些账号如同一个有机体般行动**,并将其与**谁
在幕后操控**严格区分开来,同时通过自适应的对手来测试自身。
[](https://github.com/jerzy99jerzy/phantomatics/actions/workflows/ci.yml)
## 它做什么,以及它刻意不做什么
Phantomatics 很好地回答了一个问题:*给定一个推文快照,哪些账号
在协同行动?* 它通过将五个独立的信号(共享
来源、共享基础设施、复用的媒体、近乎重复的文本、紧密的
共转推时间)融合成一个加权图并检测密集社区来实现这一点。
它**不会**告诉你谁在运营这些账号。这一步——归因于
具名参与者——是这个问题在认识论上最薄弱、影响最重大的部分:
将错误的“外国特工”标签贴在真实的人身上是实质性的伤害,并且
在欧盟,这是实质性的责任。因此,这里的归因**永远不会自动化**。系统
产生*协同嫌疑*,并附带明确的置信度和证据链,
将最后的跳跃交给人类。
这种分离不是事后补上的免责声明;它是由架构
和测试强制执行的 (`test_report_never_claims_attribution`)。
## 负责任地使用
这是**防御性**的 CTI 工具,属于关于
协同检测的开放学术工作的脉络 (Pacheco & Menczer / OSoMe, Luceri & Ferrara) 以及公开的
调查工作 (DFRLab, EU DisinfoLab, Graphika)。它旨在用于研究、
威胁情报和平台完整性工作。
- 它检测的是*协同*,这不等同于*虚假*或*恶意*
—— 合法的编辑室、活动家网络和广告活动也会协同行动。
检测到的集群是一条线索,而不是一个判决。
- 未经人工审查和确凿证据,不要使用其输出
公开指控、封禁或针对个人。
- 如果你将其指向真实数据,你需要对其法律依据负责
(在
欧盟,即使是公开的个人数据也适用 GDPR;需要具备狭隘的研究/合法
利益依据)。
- 捆绑的数据是**完全合成的**。账号、域名(例如伪造的
typosquat `wiadomosci-p0lska.info`)和叙事都是生成的 —— 没有一个是真实的
妥协指标。
## 安装
```
git clone https://github.com/jerzy99jerzy/phantomatics
cd phantomatics
pip install -e ".[dev]"
```
Python 3.11+。核心依赖:DuckDB, PyArrow, python-igraph, leidenalg, SciPy。
## 快速入门
```
# 1. 生成 synthetic worlds(默认情况下不对 real data 运行任何操作)
phantomatics fixture --out data # naive world
phantomatics fixture --out data --adversarial # adaptation-hardened world
phantomatics fixture --out data --multi-origin # source-distribution world
# 2. 检测 coordination
phantomatics detect --snapshot data/events.parquet \
--truth data/ground_truth.json --out reports
# 3. origin-level meta-clustering(捕获 distributed-source evasion)
phantomatics meta --snapshot data/events_multi.parquet \
--truth data/ground_truth_multi.json --out reports
```
要针对你自己的数据运行,请将 `--snapshot` 指向任何匹配
`EVENT_SCHEMA` 的 Parquet 文件(参见 `phantomatics/schema.py`)。供应商适配器是模式
转换,其上方的任何内容都不会改变。
### 真实数据
包含了一个针对公开 IRA / FiveThirtyEight 数据集的适配器:
```
phantomatics ingest --input IRAhandle_tweets_1.csv --format ira --out data --limit 40000
phantomatics detect --snapshot data/events.parquet --out reports
```
`ingest` 会打印一份 **channel-availability 报告**:真实的转储是有损的(没有
感知哈希,转推结构被剥离,URL 被缩短),因此几个通道
会变暗,恢复时必须考虑到这一点。正是对
该数据集的对抗,促使我们添加了 `content_hashtag` 通道 —— 当
转推结构无法保留时,标签在导出后依然存在 —— 并让该项目明白,单个归因的参与者
是*多叙事*的,因此干净的恢复意味着将其拆分为子行动,而
不是恢复一个庞然大物。参见 [`docs/SPRINT6_REAL_DATA.md`](docs/SPRINT6_REAL_DATA.md)。
## 工作原理(一段话)
每个通道都表示为一个稀疏的 **account × token** 关联矩阵 `B`
(token = 共享的域名、来源、媒体哈希、文本桶或共转推窗口),
经过 IDF 加权,使得罕见的共享 token 比常见的权重更高。协同
图是稀疏投影 `A = B·Bᵀ` —— 没有 O(k²) 的成对物化,
这也消除了针对检测器本身的拒绝服务向量。Leiden
寻找社区;每个社区通过 `density × corroboration × mass` 进行评分,其中
这三个因素阻止了三种不同的攻击(单通道自适应、检测器
投毒、大小优势)。有向的转推流随后分配角色:**origin**
(播种者)、**amplifier**、**bridge**(洗钱节点,botnet 内容
通过它跨越到真实触达范围)、**target**。当对手将
叙事分布在许多来源中以击败共享来源信号时,
向上一层(**origin × narrative**)的相同
投影会恢复协同,因为
叙事是 payload,无法被轮换。
完整细节:[`docs/MECHANISMS.md`](docs/MECHANISMS.md)。
## 对手自适应测试
系统针对三个难度递增的合成世界进行了验证,
每个世界都有明确的 ground truth:
| 世界 | 测试内容 | 恢复率 |
|---|---|---|
| naive | 干净的信号,所有通道都存在 | F1 = 0.96 |
| adversarial | 域名轮换 + jitter + 独特的 LLM 文本 | F1 = 0.92 |
| multi-origin | 分布式来源(击败了 shared-source) | meta F1 = 1.00 |
| multi-narrative | 一个参与者,几个平行的叙事 | 干净的子集群拆分 |
| doppelganger* | 以基础设施为中心的行动 (typosquat 域名 + 回收的资产) | F1 = 0.97 |
\* Doppelganger 世界是合成的,基于已记录的 TTP 构建 —— 不是真实的 IOC。它
反映了 IRA 通道特征:infra + phash 占主导地位,标签几乎为零,
证明了该通道架构可泛化到不同的威胁模型。一个 `--profile`
标志 (`full_api` / `public_dump`) 会根据来源重新加权通道,因为公开
转储剥离了转推结构,而完整的 API feed 保留了它。
adversarial 世界是一等公民,而不是事后诸葛亮:正是它
真正验证了通道权重。仅在 naive 世界中,“infra 维持
最久”看起来是真的;在自适应下,这是错的 —— *共享的*
infra 依然存在,但域名轮换成本很低。这种反转是
`shared_source` 被赋予最高权重的原因。
## 项目布局
```
phantomatics/ the package
schema.py normalized event schema (the adapter boundary)
adapters/ real-data adapters (IRA / FiveThirtyEight)
fixture.py three synthetic worlds + ground truth
channels.py pairwise channels (test oracle only, not user-facing)
text.py SimHash / Hamming primitives
bipartite.py sparse account×token core (the efficient engine)
detect.py pairwise detection (correctness oracle for the bipartite engine)
detect_bipartite.py bipartite detection (the engine)
scoring.py single home for weights + the scoring formula
roles.py L3 role assignment from directed retweet flow
meta.py origin-level meta-clustering (Sprint 4)
evaluate.py recovery vs ground truth
cli.py fixture / detect / meta commands
tests/ end-to-end smoke tests (run through the CLI)
tools/ sweep_roles.py (threshold calibration)
docs/ design notes and analysis
```
## 状态与局限
Alpha 阶段。所有验证均在合成固件上进行。对于真实的
feed 的现实预期:**更低的召回率**(公开的 ground-truth 是
已经被抓到的操作者中存在幸存者偏差的样本)和**更低的精确率**(更丰富的
有机噪声)。接入真实的
数据集(Twitter/X IO 存档、Doppelganger 域名列表)以进行
离线验证是下一步,并且可能会破坏某些东西 —— 这正是
这样做的意义所在。
设计说明、代码审查和引擎等价分析位于
[`docs/`](docs/)。
## 许可证
参见 [许可证](LICENSE)。
标签:逆向工具