import os import subprocess import json import re import time import uuid from flask import Flask, render_template_string, request, session, redirect, url_for, send_file, Response, make_response app = Flask(__name__) app.secret_key = "JST_STABLE_SECRET_KEY_ZIE_2026" # Konfigurasi Session dibikin standar aja biar HP gak rewel app.config.update( PERMANENT_SESSION_LIFETIME=86400 ) # --- SYSTEM LIMITER (MAX 4 ORANG) --- ACTIVE_USERS = {} MAX_CONCURRENT_USERS = 4 @app.before_request def track_sessions(): now = time.time() # Bersihin session yang udah afk / mati lebih dari 2 jam (7200 detik) dead_uids = [u for u, t in ACTIVE_USERS.items() if now - t > 7200] for d in dead_uids: del ACTIVE_USERS[d] if 'uid' in session: ACTIVE_USERS[session['uid']] = now # --- IDENTITY & CREDENTIALS --- OWNER_NAME = "WhyLaugh404" TEAM_NAME = "JakartaSecTeam" LOGIN_LOGO = "https://i.pinimg.com/736x/c2/9a/b9/c29ab9478d9c8f3f84e070d65b2514bc.jpg" DASH_LOGO = "https://i.pinimg.com/736x/22/46/87/224687d938e12d1bfaf9edd0385fd42b.jpg" PASSWORDS = { "owner": "izie19281933", "admin": "admin404jst", "member": "memberjst404" } ACCESS_LEVELS = { "member": ["sherlock", "socialscan", "holehe", "exiftool"], "admin": ["sherlock", "maigret", "socialscan", "holehe", "phoneinfoga", "exiftool", "cloud_enum"], "owner": ["sherlock", "maigret", "socialscan", "holehe", "phoneinfoga", "twint", "exiftool", "ghunt", "cloud_enum"] } ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') # --- STYLING: FULLY RESPONSIVE B&W --- CSS = """ :root { --bg: #000; --text: #fff; --panel: #0a0a0a; --border: #333; } body { background: var(--bg); color: var(--text); font-family: 'Courier New', monospace; margin: 0; padding: 0; overflow-x: hidden; } /* LAYOUT LOGIN */ .login-screen { display: flex; align-items: center; justify-content: center; min-height: 100vh; flex-direction: column; padding: 20px; box-sizing: border-box; } .login-logo { width: 150px; height: 150px; border-radius: 50%; margin-bottom: 25px; filter: grayscale(100%); border: 3px solid var(--text); } .jst-brand { font-size: 2.2em; font-weight: bold; letter-spacing: 5px; text-align: center; margin-bottom: 25px; } .login-card { background: var(--panel); border: 1px solid var(--border); padding: 40px 30px; width: 100%; max-width: 380px; text-align: center; box-sizing: border-box; } /* HEADER DASHBOARD */ .header { background: var(--panel); border-bottom: 1px solid var(--border); padding: 20px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; } .header-left { display: flex; align-items: center; gap: 15px; } .mrx-logo { width: 60px; height: 60px; border-radius: 50%; border: 1px solid var(--border); filter: grayscale(100%); } .header-title { font-size: 1.5em; font-weight: bold; letter-spacing: 3px; } .header-sub { font-size: 0.7em; color: #aaa; margin-top: 5px; } /* BUTTONS & INPUTS (Lebih gede biar gampang dipencet di HP) */ .logout-btn { color: var(--bg); background: var(--text); text-decoration: none; padding: 10px 20px; font-size: 0.9em; font-weight: bold; border: 1px solid var(--text); transition: 0.3s; } .logout-btn:hover { background: var(--bg); color: var(--text); } input { background: var(--bg); border: 1px solid var(--border); color: var(--text); padding: 15px; width: 100%; box-sizing: border-box; outline: none; margin-bottom: 15px; font-family: inherit; font-size: 1em; } input:focus { border-color: var(--text); } button { background: var(--bg); border: 1px solid var(--text); color: var(--text); padding: 15px; width: 100%; cursor: pointer; font-weight: bold; letter-spacing: 2px; font-size: 1em; transition: 0.3s; } button:hover:not(:disabled) { background: var(--text); color: var(--bg); } /* GRID SYSTEM MANTAP (Gak Berdempetan) */ .container { max-width: 1400px; margin: 30px auto; padding: 0 20px; } .guide-box { border: 1px dashed var(--border); padding: 20px; margin-bottom: 30px; background: var(--panel); font-size: 0.9em; line-height: 1.8; } .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 30px; } .card { background: var(--panel); border: 1px solid var(--border); padding: 25px; box-sizing: border-box; display: flex; flex-direction: column; } .card h3 { margin-top: 0; border-bottom: 1px dashed var(--border); padding-bottom: 10px; font-size: 1em; } /* CONSOLE BOX */ .console-box { background: var(--bg); border: 1px solid var(--border); margin-top: 20px; display: none; flex-direction: column; flex-grow: 1; } .console-header { background: #111; padding: 10px; font-size: 0.8em; display: flex; justify-content: space-between; border-bottom: 1px solid var(--border); align-items: center; } .console-body { padding: 15px; height: 300px; overflow-y: auto; font-size: 0.85em; white-space: pre-wrap; color: #ccc; } .dl-btn { color: var(--bg); background: var(--text); text-decoration: none; padding: 5px 12px; display: none; font-weight:bold; font-size: 0.9em; } /* RESPONSIVE ANDROID / MOBILE */ @media (max-width: 768px) { .header { flex-direction: column; text-align: center; gap: 20px; } .header-left { flex-direction: column; } .logout-btn { width: 100%; box-sizing: border-box; text-align: center; padding: 15px; } .grid { grid-template-columns: 1fr; gap: 20px; } .container { margin: 15px auto; padding: 0 15px; } .card { padding: 20px; } } """ # --- SERVER LOGIC --- @app.route('/', methods=['GET', 'POST']) def entry(): if request.method == 'POST': p = request.form.get('p', '').strip() matched_role = None for role, val in PASSWORDS.items(): if p == val: matched_role = role break if matched_role: if 'uid' not in session and len(ACTIVE_USERS) >= MAX_CONCURRENT_USERS: return f"""

[!] SERVER FULL

sabar dulu temen lu lagi osint mek


[ RELOAD ]""" if 'uid' not in session: new_uid = str(uuid.uuid4()) session['uid'] = new_uid ACTIVE_USERS[new_uid] = time.time() session['role'] = matched_role return redirect(url_for('entry')) return "

[!] ACCESS DENIED


[ BACK ]" if 'role' in session: # Tambahin proteksi cache di dashboard biar pas logout gak bisa di-back resp = make_response(render_template_string(T_DASHBOARD, css=CSS, owner=OWNER_NAME, team=TEAM_NAME, role=session['role'], allowed=ACCESS_LEVELS[session['role']], mrx_url=DASH_LOGO)) resp.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' resp.headers['Pragma'] = 'no-cache' resp.headers['Expires'] = '0' return resp return render_template_string(T_LOGIN, css=CSS, team=TEAM_NAME, login_logo=LOGIN_LOGO) @app.route('/stream/') def stream(tool_id): if 'role' not in session or tool_id not in ACCESS_LEVELS[session['role']]: return Response("Unauthorized", status=403) target = request.args.get('target', '').strip() def generate(): cmds = { "sherlock": f"sherlock {target} --timeout 5", "maigret": f"maigret {target} --timeout 10", "socialscan": f"socialscan {target}", "holehe": f"holehe {target}", "phoneinfoga": f"phoneinfoga scan -n {target}", "twint": f"twint -u {target}", "exiftool": f"exiftool {target}", "ghunt": f"ghunt email {target}", "cloud_enum": f"python3 /home/user/cloud_enum/cloud_enum.py -k {target}" } cmd = cmds.get(tool_id) report_file = f"JST_REPORT_{tool_id.upper()}_{target.replace('.', '_')}.txt" init_msg = f"> Initiating: {tool_id.upper()}\n> Target: {target}\n\n" yield f"data: {json.dumps({'line': init_msg})}\n\n" process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, universal_newlines=True) full_log = "" for line in process.stdout: clean_line = ansi_escape.sub('', line) full_log += clean_line yield f"data: {json.dumps({'line': clean_line})}\n\n" process.wait() with open(report_file, "w") as f: f.write(full_log) yield f"data: {json.dumps({'done': True, 'file': report_file})}\n\n" return Response(generate(), mimetype='text/event-stream') @app.route('/dl/') def dl(filename): if filename.startswith("JST_REPORT_") and os.path.exists(filename): return send_file(filename, as_attachment=True) return "Error", 404 @app.route('/logout') def logout(): # Hapus dari tracker 4 orang if 'uid' in session and session['uid'] in ACTIVE_USERS: del ACTIVE_USERS[session['uid']] # Hapus sesi session.clear() # PENTING: Paksa browser lupain cache biar beneran mental resp = redirect(url_for('entry')) resp.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' resp.headers['Pragma'] = 'no-cache' resp.headers['Expires'] = '0' return resp # --- HTML TEMPLATES --- T_LOGIN = """ {{team}} | AUTH
{{team}}
""" T_DASHBOARD = """ {{team}} CONSOLE
{{team}} CONSOLE
OP: {{owner}} | LVL: {{role.upper()}}
LOGOUT SESSION
{% if role in ['member', 'admin'] %}
[ PANDUAN PENGGUNAAN MODULE ]

- SHERLOCK / MAIGRET: Tracing username di ribuan platform sosial media. (Input: username)
- SOCIALSCAN / HOLEHE: Validasi apakah email/username terdaftar di platform tertentu. (Input: email/username)
- PHONEINFOGA: Gathering informasi dari nomor HP. (Input: Gunakan kode negara, ex: +62812...)
- EXIFTOOL: Ekstrak jejak digital/metadata tersembunyi dari file gambar/dokumen. (Input: nama_file.jpg)
- CLOUD_ENUM / GHUNT: Enumerasi asset cloud dan investigasi akun Google. (Input: keyword/email)
{% endif %}
{% for t_id in allowed %}

>> MODULE: {{t_id.upper()}}

LOG: {{t_id.upper()}}SAVE LOG
{% endfor %}
""" if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, threaded=True)