Browse by type
Hunt down malicious Telegram bots used as malware command-and-control (C2).
Matkap is the web version of 0x6rss/matkap. A lot of commodity malware (stealers, RATs) exfiltrates stolen data to a Telegram bot and reads it from a private chat. If you recover that bot's token, Matkap lets you validate it, recover the operator's data, monitor the bot live, and discover more leaked tokens from threat-intel sources.
This is a defensive Telegram threat-hunting tool, not a malware-analysis engine. Use it only on projects and tokens you are authorized to investigate.
forwardMessage.getMe) and resolve chat ids (getUpdates).telegram_bot_api YARA rule, plus manually check report hashes.The screenshots below show MATKAP's main workspaces. Any indicators or expired
credentials visible in these examples are historical test data; .env values,
provider API keys, Telegram string sessions, and personal account details are
not included.

Validate an authorized bot token, start or pause an investigation, forward messages, and review operation logs and captured content from one workspace.

Search supported intelligence sources for exposed Telegram bot artifacts, optionally validate results, resolve chat IDs, and send a result to Hunt.

Review community-reported Telegram C2 indicators, related infrastructure, malware tags, and links back to the original public reports.

Search selected threat-intelligence publishers and rank reports by Telegram C2 signals such as bot API endpoints, bot references, chat IDs, and send methods.

Track metadata for recent samples matched by MalwareBazaar's
telegram_bot_api YARA rule without downloading malware files.

Connect to the packaged read-only JADX MCP connector, scan the project already open in JADX, and optionally use a configured AI provider as a fallback.

Explore 7, 14, or 30-day malware, feed, family, campaign, and daily-activity statistics assembled from cached MATKAP data sources.
getMe) and, using a Telegram user account you
control, sends /start to the bot to trigger an update.getUpdates reveals the operator's chat id and the latest message id.forwardMessage privilege, Matkap forwards the
operator's messages into your own chat, capturing text and files.DATABASE_URL, MCP findings run in memory.api_id / api_hash from https://my.telegram.orggit clone https://github.com/0x6rss/matkap.git
cd matkap
npm install
Copy-Item .env.example .env
On Linux or macOS, use cp .env.example .env instead of Copy-Item.
A ready-to-use PostgreSQL database is provided through Docker. Skip this entire step if persistence is not needed; MATKAP will still run, but captured logs and feed caches will exist only in memory and are lost when the server stops.
To start only PostgreSQL on local port 5433:
docker compose up -d db
Then set in .env:
DATABASE_URL=postgres://matkap:matkap@localhost:5433/matkap
The database is reachable only from this computer. Any other reachable PostgreSQL instance can be used; MATKAP creates its required tables on start.
Log in at https://my.telegram.org -> API development tools, and copy your
api_id and api_hash into .env:
TELEGRAM_API_ID=123456
TELEGRAM_API_HASH=your_api_hash
TELEGRAM_PHONE=+1555...
Leave TELEGRAM_STRING_SESSION empty and start the app in a local terminal
with NODE_ENV=development (the provided default). MATKAP asks for the login
code sent by Telegram and, if enabled on the account, the 2FA password:
npm start
# Enter the Telegram login code: 12345
# Enter Telegram 2FA password (if requested)
# [default] Login OK. String session saved to .env for future starts.
MATKAP writes the generated TELEGRAM_STRING_SESSION directly to .env
without printing it. Later npm start runs reuse that session and do not ask
for a code. If Telegram invalidates the saved session, development mode asks
you to log in again and replaces it automatically. Keep .env private and
never commit or share it.
Single account — just fill the fields above.
Multiple accounts — set TELEGRAM_ACCOUNTS to a JSON array (this overrides
the single-account fields). On first login, include phone and leave
stringSession empty for each account. MATKAP saves each generated session back
into the JSON value in .env. The UI shows an account selector; the server
round-robins if you do not pick one:
TELEGRAM_ACCOUNTS=[{"label":"acc1","apiId":"111","apiHash":"aaa","phone":"+15550000001","stringSession":""},{"label":"acc2","apiId":"222","apiHash":"bbb","phone":"+15550000002","stringSession":""}]
npm start
# open http://localhost:3000
For the complete Docker stack, first complete the one-time Telegram login above
with npm start, then stop it with Ctrl+C. The generated session is now in
.env, so the container will not need an interactive login. Start the app and
database with:
docker compose up --build
Open http://localhost:3000. Both the web application and PostgreSQL published
ports are restricted to 127.0.0.1 by the provided Compose configuration.
The current release supports JADX only. Ghidra and Binary Ninja connectors are shown as SOON and will be added later. MATKAP does not execute or upload the APK; it reads the project already open in JADX through a local connector.
MATKAP-JADX-Connector-6.4.1.zip from GitHub Releases or from
connectors/jadx/dist
in the cloned repository.powershell -ExecutionPolicy Bypass -File .\install.ps1
That is the entire connector setup. End users do not compile anything and do not install Maven, Python, Node.js, or a separate MCP bridge for the connector. The ZIP contains the ready JAR, installer, SHA-256 checksum, license, and notice.
When running directly from this repository, the same installer is available at:
powershell -ExecutionPolicy Bypass -File .\connectors\jadx\install.ps1
MATKAP's default connector configuration is:
JADX_MCP_URL=http://127.0.0.1:8650
JADX_MCP_TRANSPORT=jadx-rest
The installer verifies the packaged JAR's SHA-256 and backs up an existing
jadx-ai-mcp.jar before replacing it. The endpoint listens only on the local
machine. APK resources are size-limited, treated as data, and never executed.
MATKAP first scans likely text resources locally; enable Use AI fallback after
local scan only when deeper source analysis is wanted.
Add at least one provider key to .env (choose whichever provider you use):
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
GEMINI_API_KEY=
XAI_API_KEY=
KIMI_API_KEY=
DEEPSEEK_API_KEY=
An AI key is optional for the local deterministic MCP preflight. It is used only when Use AI fallback after local scan is explicitly enabled and the preflight cannot recover an exact token and chat ID.
The bundled adapters use each provider's REST API. Every default model and
endpoint can be overridden with <PROVIDER>_MODEL and <PROVIDER>_BASE_URL;
see .env.example for the complete list. Choose one configured provider in
MCP Lab, enable the AI fallback checkbox, and click Scan open JADX project.
Provider output is treated as untrusted: candidates must match MATKAP's exact Telegram token/chat-id formats before storage. Dashboard bot tokens stay masked until the local user clicks Reveal.
For a lightweight MCP-only launch, set:
MATKAP_DISABLE_DATABASE=true
MATKAP_DISABLE_TELEGRAM=true
MATKAP_DISABLE_FEEDS=true
Run the MCP and mocked provider-adapter tests with npm test.
The UI is organised into tabs:
The IOC Discovery panel searches threat-intel sources for Telegram bot credentials and parses out bot tokens + chat ids. Use auto-fills the hunt.
| Source | Env key | Default query | Notes |
|---|---|---|---|
| ThreatFox | ABUSECH_AUTH_KEY |
api.telegram.org |
abuse.ch IOC DB; values are often full bot<token> URLs; malware family attached. Best free source. Also tag:telegram-c2 / malware:... |
| urlscan | URLSCAN_KEY |
domain:api.telegram.org |
Free tier; pulls each scan's request URLs + DOM (capped at 50) |
| ZoomEye | ZOOMEYE_KEY |
http.body="api.telegram.org" |
body needs a Business plan; free tier works with "Fetch pages directly" |
Options in the panel:
link on the free
tier (ZoomEye), the server fetches each discovered link and parses it locally.
Trade-off: your server connects to those (often malicious) hosts, revealing its
IP. Off by default.getMe + deletes any
webhook + getUpdates) to mark it live @username / dead and fill the
chat id when a pending update exists (works for idle bots; active bots consume
their own updates).Adding a source is one file: create sources/<name>.js exporting
search({ key, query, size }) that returns [{host, ip, port, link, title, date, body}],
then register it in sources/index.js. The token/chat-id parser (ioc.js) is
shared across all sources.
Both feeds are refreshed every 10 minutes and cached in the DB; the panels load the cache instantly and show "updated X ago".
"telegram bot"-style
dorks across reputable TI publishers and scores each article on Telegram-bot
signals; only hits at/above the min score are shown. Uses DuckDuckGo by
default (which rate-limits scraping); setGOOGLE_CSE_KEY+GOOGLE_CSE_CX`
(free Google Programmable Search, 100/day) for reliable results.
The MalwareBazaar tab automatically queries the telegram_bot_api YARA rule,
keeps samples first seen during the last 14 days, and displays their SHA-256,
other hashes, family, file metadata, tags, detections, reporter, and abuse.ch
sample page. Metadata refreshes on server startup and every 3 hours; MATKAP does
not download malware files. This feed uses the YARA rule only and does not merge
the broader Telegram tag r
$ claude mcp add matkap \
-- python -m otcore.mcp_server <graph>