Compare commits
7 Commits
741e6bb0d3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c6849c35ea | |||
| b4025b8a41 | |||
| baaf779636 | |||
| 6a118db573 | |||
| aaf26b87e4 | |||
| 46968f2194 | |||
| 5c9ac91b64 |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -2,8 +2,13 @@
|
|||||||
*.session
|
*.session
|
||||||
*.session-journal
|
*.session-journal
|
||||||
bot_session*
|
bot_session*
|
||||||
|
.claude/*
|
||||||
|
|
||||||
# Data — keep the folder, ignore contents
|
# logs: keep the folder, ignore contents
|
||||||
|
logs/*
|
||||||
|
|
||||||
|
# Data: keep the folder, ignore contents
|
||||||
|
data/*
|
||||||
data/hits.db
|
data/hits.db
|
||||||
data/hits.txt
|
data/hits.txt
|
||||||
data/hits.csv
|
data/hits.csv
|
||||||
@@ -15,6 +20,7 @@ data/logs/
|
|||||||
|
|
||||||
# Env
|
# Env
|
||||||
.env
|
.env
|
||||||
|
config_local.py
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@@ -22,3 +28,4 @@ __pycache__/
|
|||||||
*.pyo
|
*.pyo
|
||||||
.venv/
|
.venv/
|
||||||
venv/
|
venv/
|
||||||
|
*.egg-info*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ULP Credential Monitor
|
# stealergram
|
||||||
|
|
||||||
A Telegram-based credential exposure monitor for threat intelligence teams.
|
A Telegram-based credential exposure monitor for threat intelligence teams.
|
||||||
Watches channels for combo/stealer log files and alerts you when your
|
Watches channels for combo/stealer log files and alerts you when your
|
||||||
@@ -22,7 +22,7 @@ User session (Telethon)
|
|||||||
## Project structure
|
## Project structure
|
||||||
|
|
||||||
```
|
```
|
||||||
ulp_monitor/
|
stealergram/
|
||||||
├── main.py Entry point
|
├── main.py Entry point
|
||||||
├── config.py All settings (keywords, channels, paths)
|
├── config.py All settings (keywords, channels, paths)
|
||||||
│
|
│
|
||||||
|
|||||||
41
config.py
41
config.py
@@ -41,23 +41,7 @@ _DEFAULT_KEYWORDS: list[str] = [
|
|||||||
|
|
||||||
# Use usernames (without @) or numeric channel IDs (-100xxxxxxxxxx)
|
# Use usernames (without @) or numeric channel IDs (-100xxxxxxxxxx)
|
||||||
_DEFAULT_CHANNELS: list[str | int] = [
|
_DEFAULT_CHANNELS: list[str | int] = [
|
||||||
#-1002230225603,
|
#"channelName",
|
||||||
#"cloudxlog",
|
|
||||||
##-1001967030016, # daisycloud
|
|
||||||
##"berserklogs", # berserklogs
|
|
||||||
##"BorwitaFreeLogs", # borwita
|
|
||||||
#-1002748707556, # darkcloud
|
|
||||||
#-1001684073398, # BHF Cloud
|
|
||||||
#-1003163621939, # Wich Love from R
|
|
||||||
#-1003611713618, # Khazan Cloud
|
|
||||||
#-1003328682684, # LogsPlanet
|
|
||||||
#-1003204260194, # JDP
|
|
||||||
#-1002828367761, # HesoyamCloud
|
|
||||||
#-1003513974925, # Slurm Logs
|
|
||||||
#-1003599300787, # Arhont Corp
|
|
||||||
#-1002582513379, # OnlyLogs
|
|
||||||
#-1002788333372, # Ickis Cloud
|
|
||||||
-1002643355608, # Cloud URL
|
|
||||||
#-1001234567890, # private channel by ID
|
#-1001234567890, # private channel by ID
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -122,15 +106,13 @@ MAX_FILE_SIZE = 4 * 1024 * 1024 * 1024 # 4 GB (Telegram Premium max)
|
|||||||
|
|
||||||
# ─── Archive passwords to try ────────────────────────────────────────────────
|
# ─── Archive passwords to try ────────────────────────────────────────────────
|
||||||
ARCHIVE_PASSWORDS: list[bytes] = [
|
ARCHIVE_PASSWORDS: list[bytes] = [
|
||||||
b"1234",
|
|
||||||
b"0000",
|
|
||||||
b"infected",
|
|
||||||
b"telegram",
|
|
||||||
b"password",
|
|
||||||
b"12345",
|
|
||||||
b"",
|
b"",
|
||||||
b"Borwita",
|
b"infected",
|
||||||
b"@WichLoveFromR",
|
b"password",
|
||||||
|
b"1234",
|
||||||
|
b"12345",
|
||||||
|
b"0000",
|
||||||
|
b"telegram",
|
||||||
]
|
]
|
||||||
|
|
||||||
# ─── Backfill settings ───────────────────────────────────────────────────────
|
# ─── Backfill settings ───────────────────────────────────────────────────────
|
||||||
@@ -141,7 +123,7 @@ BACKFILL_LIMIT = 500
|
|||||||
# Namespace tdl was logged into. Run `tdl login` with no -n flag → namespace
|
# Namespace tdl was logged into. Run `tdl login` with no -n flag → namespace
|
||||||
# is "default". Run `tdl login -n foo` → namespace is "foo".
|
# is "default". Run `tdl login -n foo` → namespace is "foo".
|
||||||
# Set to None to omit -n entirely (tdl will use "default" anyway).
|
# Set to None to omit -n entirely (tdl will use "default" anyway).
|
||||||
TDL_NAMESPACE: str | None = "ulpmon"
|
TDL_NAMESPACE: str | None = "monitor_session"
|
||||||
|
|
||||||
# Parallel chunk workers per file (-t / --threads global flag)
|
# Parallel chunk workers per file (-t / --threads global flag)
|
||||||
TDL_THREADS = 8
|
TDL_THREADS = 8
|
||||||
@@ -156,3 +138,10 @@ TDL_AMOUNT = 4
|
|||||||
# Whether to use a Telegram takeout session for downloads (lower flood limits).
|
# Whether to use a Telegram takeout session for downloads (lower flood limits).
|
||||||
# Takeout sessions are rate-limited differently - good for bulk backfill.
|
# Takeout sessions are rate-limited differently - good for bulk backfill.
|
||||||
TDL_TAKEOUT = True
|
TDL_TAKEOUT = True
|
||||||
|
|
||||||
|
# ─── Local overrides (gitignored) ────────────────────────────────────────────
|
||||||
|
# Create config_local.py to override any value above without touching this file.
|
||||||
|
try:
|
||||||
|
from config_local import * # noqa: F401, F403
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|||||||
26
config_local.py.example
Normal file
26
config_local.py.example
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# config_local.py - machine-specific overrides (copy to config_local.py, never commit)
|
||||||
|
# Any name defined here replaces the value in config.py at import time.
|
||||||
|
|
||||||
|
# Extra archive passwords specific to your targets
|
||||||
|
ARCHIVE_PASSWORDS: list[bytes] = [
|
||||||
|
b"",
|
||||||
|
b"infected",
|
||||||
|
b"password",
|
||||||
|
b"1234",
|
||||||
|
# add your own below
|
||||||
|
]
|
||||||
|
|
||||||
|
# tdl namespace you logged into (tdl login -n <name>)
|
||||||
|
TDL_NAMESPACE: str | None = "monitor_session"
|
||||||
|
|
||||||
|
# Default keyword patterns (overridden by runtime_config.json when present)
|
||||||
|
_DEFAULT_KEYWORDS: list[str] = [
|
||||||
|
r"yourdomain\.com",
|
||||||
|
r"@yourdomain\.com",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Default channels (overridden by runtime_config.json when present)
|
||||||
|
_DEFAULT_CHANNELS: list[str | int] = [
|
||||||
|
# "channelname",
|
||||||
|
# -1001234567890,
|
||||||
|
]
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
2026-04-02 00:45:48,909 [INFO] utils.database: Database ready: data/hits.db
|
|
||||||
2026-04-02 00:45:49,119 [INFO] telethon.crypto.aes: libssl detected, it will be used for encryption
|
|
||||||
2026-04-02 00:45:49,156 [INFO] utils.database: Database ready: data/hits.db
|
|
||||||
2026-04-02 00:45:49,159 [INFO] tui.app: [bot] Connecting bot_client...
|
|
||||||
2026-04-02 00:45:49,159 [INFO] telethon.network.mtprotosender: Connecting to 149.154.175.59:443/TcpFull...
|
|
||||||
2026-04-02 00:45:49,203 [INFO] tui.app: [bus] EvStatus: Starting — 12 channel(s), 2 pattern(s)
|
|
||||||
2026-04-02 00:45:49,281 [INFO] telethon.network.mtprotosender: Connection to 149.154.175.59:443/TcpFull complete!
|
|
||||||
2026-04-02 00:45:49,900 [INFO] tui.app: [bot] bot_client connected, authorizing...
|
|
||||||
2026-04-02 00:45:49,901 [INFO] tui.app: [bot] bot_client ready
|
|
||||||
2026-04-02 00:45:49,901 [INFO] tui.app: [bot] Connecting user_client...
|
|
||||||
2026-04-02 00:45:49,901 [INFO] telethon.network.mtprotosender: Connecting to 149.154.175.59:443/TcpFull...
|
|
||||||
2026-04-02 00:45:49,908 [INFO] __main__: Cleaning up tmp/...
|
|
||||||
2026-04-02 00:54:16,429 [INFO] utils.database: Database ready: data/hits.db
|
|
||||||
2026-04-02 00:54:16,638 [INFO] telethon.crypto.aes: libssl detected, it will be used for encryption
|
|
||||||
2026-04-02 00:54:16,666 [ERROR] tui.app: [bot-thread] Unhandled exception: cannot import name 'HITS_CSV' from 'config' (/home/anti/Tools/sj/telegrammer/config.py)
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "/home/anti/Tools/sj/telegrammer/tui/app.py", line 848, in _run_bot_thread
|
|
||||||
loop.run_until_complete(self._bot_main())
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
|
|
||||||
File "/usr/lib64/python3.14/asyncio/base_events.py", line 719, in run_until_complete
|
|
||||||
return future.result()
|
|
||||||
~~~~~~~~~~~~~^^
|
|
||||||
File "/home/anti/Tools/sj/telegrammer/tui/app.py", line 865, in _bot_main
|
|
||||||
from core.notifier import send_status
|
|
||||||
File "/home/anti/Tools/sj/telegrammer/core/notifier.py", line 22, in <module>
|
|
||||||
from config import HITS_FILE, HITS_CSV, NOTIFY_CHAT_ID
|
|
||||||
ImportError: cannot import name 'HITS_CSV' from 'config' (/home/anti/Tools/sj/telegrammer/config.py)
|
|
||||||
2026-04-02 00:54:16,716 [INFO] tui.app: [bus] EvStatus: Bot thread crashed: cannot import name 'HITS_CSV' from 'config' (/home/anti/Tools/sj/telegrammer/config.py)
|
|
||||||
2026-04-02 00:54:22,624 [INFO] __main__: Cleaning up tmp/...
|
|
||||||
2026-04-02 00:54:34,773 [INFO] utils.database: Database ready: data/hits.db
|
|
||||||
2026-04-02 00:54:34,983 [INFO] telethon.crypto.aes: libssl detected, it will be used for encryption
|
|
||||||
2026-04-02 00:54:35,015 [INFO] utils.database: Database ready: data/hits.db
|
|
||||||
2026-04-02 00:54:35,015 [INFO] tui.app: [bot] Connecting bot_client...
|
|
||||||
2026-04-02 00:54:35,015 [INFO] telethon.network.mtprotosender: Connecting to 149.154.175.59:443/TcpFull...
|
|
||||||
2026-04-02 00:54:35,063 [INFO] tui.app: [bus] EvStatus: Starting — 12 channel(s), 2 pattern(s)
|
|
||||||
2026-04-02 00:54:35,120 [INFO] telethon.network.mtprotosender: Connection to 149.154.175.59:443/TcpFull complete!
|
|
||||||
2026-04-02 00:54:35,698 [INFO] tui.app: [bot] bot_client connected, authorizing...
|
|
||||||
2026-04-02 00:54:35,698 [INFO] tui.app: [bot] bot_client ready
|
|
||||||
2026-04-02 00:54:35,698 [INFO] tui.app: [bot] Connecting user_client...
|
|
||||||
2026-04-02 00:54:35,698 [INFO] telethon.network.mtprotosender: Connecting to 149.154.175.59:443/TcpFull...
|
|
||||||
2026-04-02 00:54:35,810 [INFO] telethon.network.mtprotosender: Connection to 149.154.175.59:443/TcpFull complete!
|
|
||||||
2026-04-02 00:54:36,420 [INFO] tui.app: [bot] user_client connected, checking auth...
|
|
||||||
2026-04-02 00:54:36,420 [INFO] tui.app: [bot] user_client ready
|
|
||||||
2026-04-02 00:54:36,563 [INFO] tui.app: [bus] EvStatus: Connected as 4n (@clp_c)
|
|
||||||
2026-04-02 00:54:36,653 [INFO] core.scraper: Warming entity cache (fetching dialogs)...
|
|
||||||
2026-04-02 00:54:38,437 [INFO] core.scraper: Entity cache ready.
|
|
||||||
2026-04-02 00:54:38,437 [INFO] tui.app: [bot] Handler registered for 12 channel(s)
|
|
||||||
2026-04-02 00:54:38,437 [INFO] core.scraper: [Backfill] Starting for 12 channel(s)...
|
|
||||||
2026-04-02 00:54:38,437 [INFO] core.scraper: [Backfill] Scanning history: cloudxlog (last 500 messages)
|
|
||||||
2026-04-02 00:54:38,463 [INFO] tui.app: [bus] EvStatus: Watching 12 channel(s)
|
|
||||||
2026-04-02 00:54:38,463 [INFO] tui.app: [bus] EvStatus: Live listener active
|
|
||||||
2026-04-02 00:54:38,585 [INFO] core.scraper: [Batch] 4 file(s): @cloud t13.txt, @cloud t12.txt, @cloud t11.txt, @cloud t10.txt
|
|
||||||
2026-04-02 00:54:38,585 [INFO] core.tdl_downloader: [tdl] Batch (4 files): @cloud t13.txt, @cloud t12.txt, @cloud t11.txt, @cloud t10.txt
|
|
||||||
2026-04-02 00:54:40,248 [INFO] __main__: Cleaning up tmp/...
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools>=68"]
|
requires = ["setuptools>=68"]
|
||||||
build-backend = "setuptools.backends.legacy:build"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "stealergram"
|
name = "stealergram"
|
||||||
|
|||||||
@@ -18,10 +18,16 @@ def isolated_web(tmp_path, monkeypatch):
|
|||||||
db_path = tmp_path / "web.db"
|
db_path = tmp_path / "web.db"
|
||||||
cfg_path = tmp_path / "runtime_config.json"
|
cfg_path = tmp_path / "runtime_config.json"
|
||||||
|
|
||||||
|
import utils.database as hitdb_mod
|
||||||
|
|
||||||
|
hits_path = tmp_path / "hits.db"
|
||||||
|
|
||||||
monkeypatch.setattr(db_mod, "DB_FILE", db_path)
|
monkeypatch.setattr(db_mod, "DB_FILE", db_path)
|
||||||
monkeypatch.setattr(cfg_mod, "RUNTIME_CONFIG_PATH", cfg_path)
|
monkeypatch.setattr(cfg_mod, "RUNTIME_CONFIG_PATH", cfg_path)
|
||||||
|
monkeypatch.setattr(hitdb_mod, "DB_FILE", hits_path)
|
||||||
|
|
||||||
db_mod.init_db()
|
db_mod.init_db()
|
||||||
|
hitdb_mod.init_db()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
Reference in New Issue
Block a user