374 lines
14 KiB
Python
374 lines
14 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
ABUSE STACK — реально работающий набор инструментов
|
||
=====================================================
|
||
Создано: 2026-07-08
|
||
Статус компонентов:
|
||
✅ Mail.tm — создание/чтение/удаление временных почт (API, без ключа)
|
||
✅ Прокси — fetch + check из GitHub (5046 шт, ~14% живых)
|
||
✅ SMS — temp-number.com, quackr.io (браузерные)
|
||
❌ Webshare — блокирует disposable email + reCAPTCHA
|
||
❌ Dexodata — Cloudflare Turnstile + возможен блок disposable
|
||
❌ DataImpulse — Cloudflare Turnstile
|
||
|
||
Использование:
|
||
python abuse_stack.py email create # Создать временную почту
|
||
python abuse_stack.py email check ID # Проверить письма
|
||
python abuse_stack.py email delete ID # Удалить почту
|
||
python abuse_stack.py proxy fetch # Скачать свежие прокси
|
||
python abuse_stack.py proxy check # Проверить живость
|
||
python abuse_stack.py proxy alive # Только живые (порт 80)
|
||
python abuse_stack.py sms list # Список доступных SMS-сервисов
|
||
python abuse_stack.py all # Полный цикл: почта + прокси + SMS
|
||
"""
|
||
|
||
import requests
|
||
import json
|
||
import random
|
||
import string
|
||
import concurrent.futures
|
||
import time
|
||
import sys
|
||
import os
|
||
from pathlib import Path
|
||
|
||
CONFIG = {
|
||
"mail_tm": {
|
||
"api_base": "https://api.mail.tm",
|
||
"token_file": str(Path.home() / "AppData/Local/hermes/tokens/mail_tm.json"),
|
||
},
|
||
"proxy": {
|
||
"sources": [
|
||
"https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/http.txt",
|
||
"https://raw.githubusercontent.com/monosans/proxy-list/main/proxies/http.txt",
|
||
"https://raw.githubusercontent.com/hookzof/socks5_list/master/proxy.txt",
|
||
"https://raw.githubusercontent.com/roosterkid/openproxylist/main/HTTPS_RAW.txt",
|
||
"https://raw.githubusercontent.com/jetkai/proxy-list/main/online-proxies/txt/proxies-http.txt",
|
||
],
|
||
"proxy_file": str(Path.home() / "AppData/Local/hermes/tokens/proxies.json"),
|
||
"check_url": "http://httpbin.org/ip",
|
||
"check_timeout": 5,
|
||
"workers": 30,
|
||
},
|
||
"sms": {
|
||
"sites": [
|
||
"https://temp-number.com/",
|
||
"https://quackr.io/",
|
||
],
|
||
},
|
||
}
|
||
|
||
# ============================================================
|
||
# MAIL.TM
|
||
# ============================================================
|
||
|
||
class MailTM:
|
||
"""Работа с временной почтой через mail.tm API"""
|
||
|
||
def __init__(self):
|
||
self.api = CONFIG["mail_tm"]["api_base"]
|
||
self.token_file = Path(CONFIG["mail_tm"]["token_file"])
|
||
self.token_file.parent.mkdir(parents=True, exist_ok=True)
|
||
self.accounts = self._load_accounts()
|
||
|
||
def _load_accounts(self):
|
||
if self.token_file.exists():
|
||
return json.loads(self.token_file.read_text())
|
||
return []
|
||
|
||
def _save_accounts(self):
|
||
self.token_file.write_text(json.dumps(self.accounts, indent=2))
|
||
|
||
def create(self, count=1):
|
||
"""Создать временные почты"""
|
||
r = requests.get(f"{self.api}/domains")
|
||
domain = r.json()["hydra:member"][0]["domain"]
|
||
|
||
created = []
|
||
for _ in range(count):
|
||
username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=12))
|
||
email = f"{username}@{domain}"
|
||
password = ''.join(random.choices(string.ascii_letters + string.digits + "!@#$", k=16))
|
||
|
||
r = requests.post(f"{self.api}/accounts", json={"address": email, "password": password})
|
||
if r.status_code != 201:
|
||
print(f" ERROR creating {email}: {r.status_code}")
|
||
continue
|
||
|
||
r = requests.post(f"{self.api}/token", json={"address": email, "password": password})
|
||
token = [REDACTED])["token"]
|
||
|
||
acc = {
|
||
"id": r.json().get("id", ""),
|
||
"email": email,
|
||
"password": password,
|
||
"token": token,
|
||
"token_masked": f"{token[:8]}...{token[-8:]}",
|
||
"domain": domain,
|
||
"created_at": time.strftime("%Y-%m-%dT%H:%M:%S"),
|
||
}
|
||
self.accounts.append(acc)
|
||
created.append(acc)
|
||
print(f" ✅ {email}")
|
||
|
||
self._save_accounts()
|
||
return created
|
||
|
||
def check(self, email_or_index=None):
|
||
"""Проверить входящие письма"""
|
||
if email_or_index is not None:
|
||
if isinstance(email_or_index, int):
|
||
acc = self.accounts[email_or_index]
|
||
else:
|
||
acc = next((a for a in self.accounts if a["email"] == email_or_index), None)
|
||
if not acc:
|
||
print(f" Account not found: {email_or_index}")
|
||
return
|
||
targets = [acc]
|
||
else:
|
||
targets = self.accounts
|
||
|
||
for acc in targets:
|
||
r = requests.get(
|
||
f"{self.api}/messages",
|
||
headers={"Authorization": f"Bearer {acc['token']}"}
|
||
)
|
||
if r.status_code == 200:
|
||
msgs = r.json().get("hydra:member", [])
|
||
print(f" 📧 {acc['email']}: {len(msgs)} messages")
|
||
for msg in msgs[-5:]:
|
||
print(f" From: {msg.get('from', {}).get('address', '?')}")
|
||
print(f" Subject: {msg.get('subject', '?')}")
|
||
print(f" ID: {msg.get('id')}")
|
||
else:
|
||
print(f" ❌ {acc['email']}: {r.status_code}")
|
||
|
||
def delete(self, email_or_index):
|
||
"""Удалить временную почту"""
|
||
if isinstance(email_or_index, int):
|
||
acc = self.accounts[email_or_index]
|
||
else:
|
||
acc = next((a for a in self.accounts if a["email"] == email_or_index), None)
|
||
|
||
if not acc:
|
||
print(f" Account not found: {email_or_index}")
|
||
return
|
||
|
||
r = requests.delete(
|
||
f"{self.api}/accounts/{acc['id']}",
|
||
headers={"Authorization": f"Bearer {acc['token']}"}
|
||
)
|
||
if r.status_code == 204:
|
||
self.accounts = [a for a in self.accounts if a["id"] != acc["id"]]
|
||
self._save_accounts()
|
||
print(f" ✅ Deleted: {acc['email']}")
|
||
else:
|
||
print(f" ❌ Failed: {r.status_code}")
|
||
|
||
def list(self):
|
||
"""Список активных почт"""
|
||
if not self.accounts:
|
||
print(" No active accounts")
|
||
return
|
||
for i, acc in enumerate(self.accounts):
|
||
print(f" [{i}] {acc['email']} | token={acc['token_masked']} | created={acc['created_at']}")
|
||
|
||
|
||
# ============================================================
|
||
# PROXY
|
||
# ============================================================
|
||
|
||
class ProxyPool:
|
||
"""Сбор и проверка бесплатных прокси"""
|
||
|
||
def __init__(self):
|
||
self.proxy_file = Path(CONFIG["proxy"]["proxy_file"])
|
||
self.proxy_file.parent.mkdir(parents=True, exist_ok=True)
|
||
self.proxies = self._load()
|
||
|
||
def _load(self):
|
||
if self.proxy_file.exists():
|
||
return json.loads(self.proxy_file.read_text())
|
||
return {"all": [], "alive": [], "updated": None}
|
||
|
||
def _save(self):
|
||
self.proxy_file.write_text(json.dumps(self.proxies, indent=2, default=list))
|
||
|
||
def fetch(self):
|
||
"""Скачать свежие прокси со всех источников"""
|
||
print(" Fetching proxies...")
|
||
all_proxies = set()
|
||
for url in CONFIG["proxy"]["sources"]:
|
||
try:
|
||
r = requests.get(url, timeout=10)
|
||
count = 0
|
||
for line in r.text.strip().split('\n'):
|
||
line = line.strip()
|
||
if line and ':' in line and not line.startswith('#'):
|
||
all_proxies.add(line)
|
||
count += 1
|
||
print(f" {url.split('/')[-1]}: {count}")
|
||
except Exception as e:
|
||
print(f" {url.split('/')[-1]}: ERROR - {e}")
|
||
|
||
self.proxies["all"] = list(all_proxies)
|
||
self.proxies["updated"] = time.strftime("%Y-%m-%dT%H:%M:%S")
|
||
self._save()
|
||
print(f" ✅ Total: {len(all_proxies)} unique proxies")
|
||
return len(all_proxies)
|
||
|
||
def check(self, sample=None):
|
||
"""Проверить живость проксей"""
|
||
targets = random.sample(self.proxies["all"], min(sample or 50, len(self.proxies["all"])))
|
||
print(f" Checking {len(targets)} proxies...")
|
||
|
||
alive = []
|
||
def _check(proxy):
|
||
try:
|
||
start = time.time()
|
||
r = requests.get(
|
||
CONFIG["proxy"]["check_url"],
|
||
proxies={"http": f"http://{proxy}", "https": f"http://{proxy}"},
|
||
timeout=CONFIG["proxy"]["check_timeout"]
|
||
)
|
||
if r.status_code == 200:
|
||
return {
|
||
"proxy": proxy,
|
||
"latency_ms": round((time.time() - start) * 1000),
|
||
"ip": r.json().get("origin"),
|
||
"checked_at": time.strftime("%Y-%m-%dT%H:%M:%S"),
|
||
}
|
||
except:
|
||
pass
|
||
return None
|
||
|
||
with concurrent.futures.ThreadPoolExecutor(max_workers=CONFIG["proxy"]["workers"]) as ex:
|
||
for result in ex.map(_check, targets):
|
||
if result:
|
||
alive.append(result)
|
||
print(f" ✅ {result['proxy']} | {result['latency_ms']}ms")
|
||
|
||
self.proxies["alive"] = alive
|
||
self.proxies["updated"] = time.strftime("%Y-%m-%dT%H:%M:%S")
|
||
self._save()
|
||
print(f" ✅ Alive: {len(alive)}/{len(targets)}")
|
||
return alive
|
||
|
||
def alive(self):
|
||
"""Показать только живые прокси"""
|
||
if not self.proxies.get("alive"):
|
||
print(" No alive proxies. Run 'proxy check' first.")
|
||
return
|
||
for p in self.proxies["alive"]:
|
||
print(f" {p['proxy']} | {p['latency_ms']}ms | {p.get('ip', '?')}")
|
||
|
||
def stats(self):
|
||
"""Статистика пула"""
|
||
print(f" Total: {len(self.proxies.get('all', []))}")
|
||
print(f" Alive: {len(self.proxies.get('alive', []))}")
|
||
print(f" Updated: {self.proxies.get('updated', 'never')}")
|
||
|
||
|
||
# ============================================================
|
||
# SMS
|
||
# ============================================================
|
||
|
||
class SMSServices:
|
||
"""Список доступных SMS-сервисов"""
|
||
|
||
def list(self):
|
||
"""Проверить доступность и показать"""
|
||
print(" Checking SMS services...")
|
||
for url in CONFIG["sms"]["sites"]:
|
||
try:
|
||
r = requests.get(url, timeout=10)
|
||
status = "✅" if r.status_code == 200 else f"❌ ({r.status_code})"
|
||
print(f" {status} {url}")
|
||
except Exception as e:
|
||
print(f" ❌ {url} - {e}")
|
||
|
||
print("\n 📋 Дополнительные SMS-сервисы (требуют браузера):")
|
||
print(" - receive-smss.com (403 с API, работает через браузер)")
|
||
print(" - receive-sms-free.cc (403 с API, работает через браузер)")
|
||
print(" - smspinverify.com")
|
||
print(" - sms-activate.guru")
|
||
print(" - smspool.net")
|
||
print(" - 7sim.net")
|
||
print(" - Telegram: @ReceiveSMSRobot, @receive_sms_cc")
|
||
|
||
|
||
# ============================================================
|
||
# CLI
|
||
# ============================================================
|
||
|
||
def main():
|
||
if len(sys.argv) < 2:
|
||
print(__doc__)
|
||
return
|
||
|
||
cmd = sys.argv[1]
|
||
|
||
if cmd == "email":
|
||
mail = MailTM()
|
||
sub = sys.argv[2] if len(sys.argv) > 2 else "list"
|
||
arg = sys.argv[3] if len(sys.argv) > 3 else None
|
||
|
||
if sub == "create":
|
||
count = int(arg) if arg else 1
|
||
mail.create(count)
|
||
elif sub == "check":
|
||
if arg:
|
||
mail.check(int(arg) if arg.isdigit() else arg)
|
||
else:
|
||
mail.check()
|
||
elif sub == "delete":
|
||
mail.delete(int(arg) if arg and arg.isdigit() else arg)
|
||
elif sub == "list":
|
||
mail.list()
|
||
|
||
elif cmd == "proxy":
|
||
pool = ProxyPool()
|
||
sub = sys.argv[2] if len(sys.argv) > 2 else "stats"
|
||
|
||
if sub == "fetch":
|
||
pool.fetch()
|
||
elif sub == "check":
|
||
pool.check()
|
||
elif sub == "alive":
|
||
pool.alive()
|
||
elif sub == "stats":
|
||
pool.stats()
|
||
|
||
elif cmd == "sms":
|
||
sms = SMSServices()
|
||
sub = sys.argv[2] if len(sys.argv) > 2 else "list"
|
||
if sub == "list":
|
||
sms.list()
|
||
|
||
elif cmd == "all":
|
||
print("=" * 60)
|
||
print("FULL ABUSE STACK")
|
||
print("=" * 60)
|
||
|
||
print("\n📧 MAIL.TM")
|
||
mail = MailTM()
|
||
mail.create(2)
|
||
|
||
print("\n🌐 PROXIES")
|
||
pool = ProxyPool()
|
||
pool.fetch()
|
||
pool.check()
|
||
|
||
print("\n📱 SMS")
|
||
sms = SMSServices()
|
||
sms.list()
|
||
|
||
print("\n" + "=" * 60)
|
||
print("✅ DONE. Check:")
|
||
print(f" {CONFIG['mail_tm']['token_file']}")
|
||
print(f" {CONFIG['proxy']['proxy_file']}")
|
||
print("=" * 60)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |