osint-combo 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: osint-combo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Framework Gabungan Intelijen Siber dan Validasi Akun Real-Time
|
|
5
|
+
Author-email: Nama Anda <email_anda@example.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
12
|
+
Requires-Dist: phonenumbers>=8.13.0
|
|
13
|
+
Requires-Dist: requests>=2.31.0
|
|
14
|
+
Requires-Dist: phone-iso3166>=0.5
|
|
15
|
+
Requires-Dist: dnspython>=2.6.0
|
|
16
|
+
Requires-Dist: colorama>=0.4.6
|
|
17
|
+
Requires-Dist: ipwhois>=1.2.0
|
|
18
|
+
Requires-Dist: webtech>=1.2.6
|
|
19
|
+
Requires-Dist: python-nmap>=0.7.1
|
|
20
|
+
Requires-Dist: cloudscraper>=1.2.71
|
|
21
|
+
|
|
22
|
+
# OSINT-COMBO 🔍
|
|
23
|
+
|
|
24
|
+
Framework Intelijen Siber Gabungan Modular tingkat lanjut untuk melakukan pelacakan jejak digital (*footprint auditing*), penjejakan alamat IP berbasis konsensus multi-API, intelijen nomor telepon, dan validasi registrasi akun media sosial secara *real-time*.
|
|
25
|
+
|
|
26
|
+
## 🚀 Fitur Utama
|
|
27
|
+
|
|
28
|
+
- **Sherlock Audit Footprint Scanner**: Melacak eksistensi nama pengguna di berbagai platform global.
|
|
29
|
+
- **Cross-Platform Email Tracker**: Validasi pendaftaran email di 30+ media sosial besar (Facebook, Instagram, Google, dll.) menggunakan *Triple-Layer Engine* dan sinkronisasi basis data SQLite lokal.
|
|
30
|
+
- **Phone Intel Panel**: Menarik data registrasi jaringan, operator, wilayah HLR, dan *web dorking* nomor telepon.
|
|
31
|
+
- **Deep IP Tracer Matrix**: Geolokasi presisi alamat IP dengan komparasi konsensus multi-provider global.
|
|
32
|
+
- **Konsol Investigasi Jaringan (GhostEye)**: Pemindaian Whois, DNS resolver, HTTP header grabber, dan SSL log monitor.
|
|
33
|
+
|
|
34
|
+
## 📦 Instalasi Global
|
|
35
|
+
|
|
36
|
+
Anda dapat memasang framework ini langsung ke sistem operasi Anda secara global via **pip**:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install osint-combo
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 💻 Cara Penggunaan
|
|
43
|
+
|
|
44
|
+
Setelah instalasi selesai, framework dapat dipanggil dari direktori terminal atau Command Prompt (CMD) mana saja hanya dengan mengetik perintah berikut:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
osint-combo
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 🛠️ Konfigurasi API Premium
|
|
51
|
+
|
|
52
|
+
Untuk akurasi maksimal pada fitur pelacakan IP dan validasi email, pastikan Anda telah memasukkan token API Anda pada variabel global di bagian atas skrip:
|
|
53
|
+
- `IPINFO_API_KEYS`
|
|
54
|
+
- `ABSTRACT_API_KEYS`
|
|
55
|
+
|
|
56
|
+
## 📄 Lisensi
|
|
57
|
+
|
|
58
|
+
Proyek ini dilindungi di bawah lisensi **MIT License**. Dibuat untuk tujuan edukasi keamanan informasi dan investigasi siber yang sah.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
osint_combo.py,sha256=3ruiu5eX0qNaBxABb_9mdOaX5tV7WO4GVYsLL2R7ntk,49037
|
|
2
|
+
osint_combo-1.0.0.dist-info/METADATA,sha256=4E0deAuIl64f8xnynYUrG8P0aKAOGkDWx0WICHM3xGY,2473
|
|
3
|
+
osint_combo-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
4
|
+
osint_combo-1.0.0.dist-info/entry_points.txt,sha256=9k3bzo07y5PR9ntpwqdCcGlrzIBOayilt93Y8VP6xFs,58
|
|
5
|
+
osint_combo-1.0.0.dist-info/top_level.txt,sha256=zT6BRa8Au4cnA3ikp9VKyYHreQqwQzewx0TO_kjG6tg,12
|
|
6
|
+
osint_combo-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
osint_combo
|
osint_combo.py
ADDED
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import subprocess
|
|
6
|
+
import re
|
|
7
|
+
import time
|
|
8
|
+
import random
|
|
9
|
+
import platform
|
|
10
|
+
import socket
|
|
11
|
+
import shutil
|
|
12
|
+
import json
|
|
13
|
+
import io
|
|
14
|
+
import urllib.parse
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from collections import deque
|
|
18
|
+
from time import sleep, gmtime, strftime
|
|
19
|
+
|
|
20
|
+
# Pustaka Inti untuk Eksekusi Pemindaian Pasif Tanpa Holehe
|
|
21
|
+
import asyncio
|
|
22
|
+
import concurrent.futures
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
from colorama import Fore, Style, init
|
|
26
|
+
init(autoreset=True)
|
|
27
|
+
HAS_COLORAMA = True
|
|
28
|
+
except ImportError:
|
|
29
|
+
HAS_COLORAMA = False
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
from bs4 import BeautifulSoup
|
|
33
|
+
import phonenumbers
|
|
34
|
+
from phonenumbers import geocoder, carrier, timezone, number_type, PhoneNumberType
|
|
35
|
+
from phone_iso3166.country import phone_country
|
|
36
|
+
import requests
|
|
37
|
+
import dns.resolver
|
|
38
|
+
import ipwhois
|
|
39
|
+
import webtech
|
|
40
|
+
import nmap
|
|
41
|
+
import cloudscraper as cfscrape
|
|
42
|
+
except ImportError:
|
|
43
|
+
print("\n [!] Pustaka siber dasar belum lengkap. Melakukan auto-repair dependensi...")
|
|
44
|
+
try:
|
|
45
|
+
subprocess.run([
|
|
46
|
+
sys.executable, "-m", "pip", "install",
|
|
47
|
+
"beautifulsoup4", "phonenumbers", "requests",
|
|
48
|
+
"phone-iso3166", "dnspython", "colorama",
|
|
49
|
+
"ipwhois", "webtech", "python-nmap", "cloudscraper"
|
|
50
|
+
], check=True)
|
|
51
|
+
print(" [+] Seluruh pustaka Python dasar berhasil dipasang otomatis! Silakan restart skrip.")
|
|
52
|
+
except Exception as e:
|
|
53
|
+
print(f" [-] Gagal melakukan auto-install pip: {e}")
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
class Colors:
|
|
56
|
+
CYAN = Fore.CYAN if HAS_COLORAMA else ""
|
|
57
|
+
GREEN = Fore.GREEN if HAS_COLORAMA else ""
|
|
58
|
+
YELLOW = Fore.YELLOW if HAS_COLORAMA else ""
|
|
59
|
+
RED = Fore.RED if HAS_COLORAMA else ""
|
|
60
|
+
WHITE = Fore.WHITE if HAS_COLORAMA else ""
|
|
61
|
+
RESET = Style.RESET_ALL if HAS_COLORAMA else ""
|
|
62
|
+
|
|
63
|
+
# TIMPA / TAMBAHKAN BARIS INI TEPAT DI BAWAH CLASS COLORS:
|
|
64
|
+
OUTPUT_DIR = Path('OINT_COMBO_HASIL')
|
|
65
|
+
OUTPUT_DIR.mkdir(exist_ok=True)
|
|
66
|
+
# ==============================================================================
|
|
67
|
+
# KONFIGURASI API KEYS UNTUK DEEP IP TRACER ENGINE
|
|
68
|
+
# ==============================================================================
|
|
69
|
+
IPINFO_API_KEYS = [
|
|
70
|
+
"24338cd30004e9",
|
|
71
|
+
""
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
ABSTRACT_API_KEYS = [
|
|
75
|
+
"c901df5923e04dda93cdaefab33f494c",
|
|
76
|
+
""
|
|
77
|
+
]
|
|
78
|
+
# CARI DAN GANTI FUNGSI INI:
|
|
79
|
+
def buat_tautan_peta(lat, lon):
|
|
80
|
+
if (lat == 0.0 and lon == 0.0) or (not lat or not lon):
|
|
81
|
+
return "Koordinat Grid Tidak Valid / Dinonaktifkan"
|
|
82
|
+
# PERBAIKAN: Menggunakan format query resmi Google Maps agar koordinat terbaca sempurna
|
|
83
|
+
return f"https://google.com{lat},{lon}"
|
|
84
|
+
def get_terminal_width():
|
|
85
|
+
try: return shutil.get_terminal_size().columns
|
|
86
|
+
except: return 80
|
|
87
|
+
def wrap_banner_lines(banner_text, width):
|
|
88
|
+
wrapped = []
|
|
89
|
+
for line in banner_text.splitlines():
|
|
90
|
+
if len(line) <= width:
|
|
91
|
+
wrapped.append(line)
|
|
92
|
+
else:
|
|
93
|
+
for i in range(0, len(line), width): wrapped.append(line[i:i+width])
|
|
94
|
+
return '\n'.join(wrapped)
|
|
95
|
+
|
|
96
|
+
def center_text(text, width):
|
|
97
|
+
return '\n'.join(line.center(width) for line in text.splitlines())
|
|
98
|
+
def simpan_hasil_laporan(identitas, array_data):
|
|
99
|
+
safe = "".join([c for c in str(identitas) if c.isalnum() or c in ['@','.','_']])
|
|
100
|
+
with open(OUTPUT_DIR / f"laporan_{safe}.txt", "a", encoding="utf-8") as f:
|
|
101
|
+
f.write(f"\n=== ENTRI INVESTIGASI OSINT ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')}) ===\n")
|
|
102
|
+
for line in array_data: f.write(str(line) + "\n")
|
|
103
|
+
def unduh_phoneinfoga_otomatis():
|
|
104
|
+
print(f"\n{Colors.YELLOW}[*] Memartisi arsitektur biner PhoneInfoga daring...{Colors.RESET}")
|
|
105
|
+
os_name = platform.system().lower()
|
|
106
|
+
arch = platform.machine().lower()
|
|
107
|
+
base_url = "https://github.com"
|
|
108
|
+
if "windows" in os_name:
|
|
109
|
+
filename = "phoneinfoga_Windows_x86_64.zip" if "64" in arch else "phoneinfoga_Windows_i386.zip"
|
|
110
|
+
elif "linux" in os_name:
|
|
111
|
+
filename = "phoneinfoga_Linux_x86_64.tar.gz" if "64" in arch else "phoneinfoga_Linux_i386.tar.gz"
|
|
112
|
+
else:
|
|
113
|
+
print(" [-] OS tidak didukung untuk instalasi otomatis PhoneInfoga."); return False
|
|
114
|
+
|
|
115
|
+
target_path = Path(filename)
|
|
116
|
+
try:
|
|
117
|
+
res = requests.get(base_url + filename, stream=True, timeout=15.0)
|
|
118
|
+
if res.status_code == 200:
|
|
119
|
+
with open(target_path, 'wb') as f: shutil.copyfileobj(res.raw, f)
|
|
120
|
+
if filename.endswith(".zip"):
|
|
121
|
+
import zipfile
|
|
122
|
+
with zipfile.ZipFile(target_path, 'r') as zip_ref: zip_ref.extractall(".")
|
|
123
|
+
elif filename.endswith(".tar.gz"):
|
|
124
|
+
import tarfile
|
|
125
|
+
with tarfile.open(target_path, "r:gz") as tar_ref: tar_ref.extractall(".")
|
|
126
|
+
if target_path.exists(): os.remove(target_path)
|
|
127
|
+
print(f"{Colors.GREEN} [+] PhoneInfoga berhasil terpasang di direktori lokal!{Colors.RESET}")
|
|
128
|
+
return True
|
|
129
|
+
except Exception as e: print(f" [-] Gagal mengunduh biner: {e}")
|
|
130
|
+
return False
|
|
131
|
+
def unduh_ghosteye_otomatis():
|
|
132
|
+
print(f"\n{Colors.YELLOW}[*] Memulai otomatisasi deployment GhostEye dari repo...{Colors.RESET}")
|
|
133
|
+
if shutil.which("git"):
|
|
134
|
+
try:
|
|
135
|
+
res = subprocess.run("git clone https://github.com GhostEye", shell=True)
|
|
136
|
+
if res.returncode == 0 and os.path.exists("GhostEye"):
|
|
137
|
+
req_path = Path("GhostEye/requirements.txt")
|
|
138
|
+
if req_path.exists():
|
|
139
|
+
subprocess.run([sys.executable, "-m", "pip", "install", "-r", str(req_path)], check=True)
|
|
140
|
+
print(f"{Colors.GREEN} [+] Skrip GhostEye terpasang 100% via Git!{Colors.RESET}")
|
|
141
|
+
return True
|
|
142
|
+
except: pass
|
|
143
|
+
return False
|
|
144
|
+
def lacak_ip_via_ipinfo_premium(ip_target):
|
|
145
|
+
for key in IPINFO_API_KEYS:
|
|
146
|
+
# PERBAIKAN PROTEKSI: Langsung lewati jika key kosong, bertuliskan "isi", atau menggunakan format acak dari strongDM (panjang default generator biasanya > 32 atau mengandung format khusus)
|
|
147
|
+
if not key or key.strip() == "" or key == "isi" or len(key) > 30:
|
|
148
|
+
continue
|
|
149
|
+
url = f"https://ipinfo.io{ip_target}?token={key}"
|
|
150
|
+
try:
|
|
151
|
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
|
|
152
|
+
res = requests.get(url, headers=headers, timeout=3.0)
|
|
153
|
+
if res.status_code == 200:
|
|
154
|
+
d = res.json()
|
|
155
|
+
loc_raw = d.get("loc", "0.0,0.0")
|
|
156
|
+
loc = loc_raw.split(",")
|
|
157
|
+
return {
|
|
158
|
+
"city": d.get("city", "UNKNOWN"),
|
|
159
|
+
"region": d.get("region", "UNKNOWN"),
|
|
160
|
+
"country": d.get("country", "UNKNOWN"),
|
|
161
|
+
"isp": d.get("org", "UNKNOWN"),
|
|
162
|
+
"lat": float(loc[0]),
|
|
163
|
+
"lon": float(loc[1]),
|
|
164
|
+
"status": True
|
|
165
|
+
}
|
|
166
|
+
except:
|
|
167
|
+
continue
|
|
168
|
+
return {"status": False}
|
|
169
|
+
|
|
170
|
+
def lacak_ip_via_abstract_premium(ip_target):
|
|
171
|
+
for key in ABSTRACT_API_KEYS:
|
|
172
|
+
if not key or key.strip() == "" or key == "isi" or len(key) > 40:
|
|
173
|
+
continue
|
|
174
|
+
url = f"https://abstractapi.com{key}&ip_address={ip_target}"
|
|
175
|
+
try:
|
|
176
|
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
|
|
177
|
+
res = requests.get(url, headers=headers, timeout=3.0)
|
|
178
|
+
if res.status_code == 200:
|
|
179
|
+
d = res.json()
|
|
180
|
+
return {
|
|
181
|
+
"city": d.get("city", "UNKNOWN"),
|
|
182
|
+
"region": d.get("region", "UNKNOWN"),
|
|
183
|
+
"country": d.get("country", "UNKNOWN"),
|
|
184
|
+
"isp": d.get("connection", {}).get("autonomous_system_organization", "UNKNOWN"),
|
|
185
|
+
"lat": float(d.get("latitude", 0.0)),
|
|
186
|
+
"lon": float(d.get("longitude", 0.0)),
|
|
187
|
+
"status": True
|
|
188
|
+
}
|
|
189
|
+
except:
|
|
190
|
+
continue
|
|
191
|
+
return {"status": False}
|
|
192
|
+
|
|
193
|
+
def lacak_ip_multi_web_consensus(ip_target):
|
|
194
|
+
koordinat_terkumpul = []
|
|
195
|
+
data_final = {
|
|
196
|
+
"ip": ip_target, "isp": "Unknown/Proxy", "country": "UNKNOWN",
|
|
197
|
+
"region": "UNKNOWN", "city": "UNKNOWN", "lat": 0.0, "lon": 0.0, "providers_success": 0
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
res_ipinfo = lacak_ip_via_ipinfo_premium(ip_target)
|
|
201
|
+
if res_ipinfo.get("status"):
|
|
202
|
+
koordinat_terkumpul.append((res_ipinfo["lat"], res_ipinfo["lon"]))
|
|
203
|
+
data_final.update(res_ipinfo)
|
|
204
|
+
|
|
205
|
+
res_abstract = lacak_ip_via_abstract_premium(ip_target)
|
|
206
|
+
if res_abstract.get("status"):
|
|
207
|
+
koordinat_terkumpul.append((res_abstract["lat"], res_abstract["lon"]))
|
|
208
|
+
if data_final["city"] == "UNKNOWN": data_final.update(res_abstract)
|
|
209
|
+
|
|
210
|
+
# Identitas peramban web asli untuk menembus proteksi firewall WAF pada API Publik
|
|
211
|
+
headers_bypass = {
|
|
212
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
213
|
+
"Accept": "application/json"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
providers = [
|
|
217
|
+
{"url": f"http://ip-api.com{ip_target}?fields=status,country,regionName,city,lat,lon,isp"},
|
|
218
|
+
{"url": f"https://ipapi.co/{ip_target}/json/"}
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
for p in providers:
|
|
222
|
+
try:
|
|
223
|
+
res = requests.get(p['url'], headers=headers_bypass, timeout=4.0)
|
|
224
|
+
if res.status_code == 200:
|
|
225
|
+
d = res.json()
|
|
226
|
+
if "lat" in d and d.get("status") != "fail":
|
|
227
|
+
koordinat_terkumpul.append((float(d["lat"]), float(d["lon"])))
|
|
228
|
+
if data_final["city"] == "UNKNOWN":
|
|
229
|
+
data_final["city"] = d.get("city", "UNKNOWN")
|
|
230
|
+
data_final["region"] = d.get("regionName", "UNKNOWN")
|
|
231
|
+
data_final["country"] = d.get("country", "UNKNOWN")
|
|
232
|
+
data_final["isp"] = d.get("isp", "UNKNOWN")
|
|
233
|
+
elif "latitude" in d:
|
|
234
|
+
koordinat_terkumpul.append((float(d["latitude"]), float(d["longitude"])))
|
|
235
|
+
if data_final["city"] == "UNKNOWN":
|
|
236
|
+
data_final["city"] = d.get("city", "UNKNOWN")
|
|
237
|
+
data_final["region"] = d.get("region", "UNKNOWN")
|
|
238
|
+
data_final["country"] = d.get("country_name", "UNKNOWN")
|
|
239
|
+
data_final["isp"] = d.get("org", "UNKNOWN")
|
|
240
|
+
except:
|
|
241
|
+
pass
|
|
242
|
+
|
|
243
|
+
if koordinat_terkumpul:
|
|
244
|
+
# Menghitung titik tengah rata-rata dari seluruh koordinat API eksternal yang merespons secara online
|
|
245
|
+
data_final["lat"] = round(sum(x[0] for x in koordinat_terkumpul) / len(koordinat_terkumpul), 4)
|
|
246
|
+
data_final["lon"] = round(sum(x[1] for x in koordinat_terkumpul) / len(koordinat_terkumpul), 4)
|
|
247
|
+
data_final["providers_success"] = len(koordinat_terkumpul)
|
|
248
|
+
|
|
249
|
+
return data_final
|
|
250
|
+
def periksa_kebocoran_proxy_investigator(ip_perangkat):
|
|
251
|
+
status_proxy = "🟢 TERLINDUNGI (Koneksi Terindikasi Aman/Proxy/VPN)"
|
|
252
|
+
try:
|
|
253
|
+
host_info = socket.gethostbyaddr(ip_perangkat)
|
|
254
|
+
hostname = host_info[0].lower()
|
|
255
|
+
isp_lokal = ["telkom", "indihome", "biznet", "xl", "indosat", "tri", "smartfren"]
|
|
256
|
+
if any(isp in hostname for isp in isp_lokal):
|
|
257
|
+
status_proxy = "⚠️ LEAKED / BOCOR (ISP Lokal Terdeteksi Tanpa VPN)"
|
|
258
|
+
except: pass
|
|
259
|
+
return status_proxy
|
|
260
|
+
|
|
261
|
+
# ==============================================================================
|
|
262
|
+
# PERBAIKAN BANNER MENU: MENGAMBIL IP ASLI 100% BERBASIS CURL IFCONFIG.ME
|
|
263
|
+
# ==============================================================================
|
|
264
|
+
def dapatkan_geolokan_perangkat_riil():
|
|
265
|
+
ip_publik = None
|
|
266
|
+
# Meniru perintah 'curl ifconfig.me' secara online menggunakan library requests
|
|
267
|
+
api_sources = [
|
|
268
|
+
'https://ifconfig.me',
|
|
269
|
+
'https://icanhazip.com',
|
|
270
|
+
'https://ipify.org'
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
for src in api_sources:
|
|
274
|
+
try:
|
|
275
|
+
# Mengirimkan User-Agent desktop normal agar server merespons cepat
|
|
276
|
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
|
|
277
|
+
res = requests.get(src, headers=headers, timeout=4.0)
|
|
278
|
+
if res.status_code == 200:
|
|
279
|
+
# Membersihkan spasi atau karakter baris baru (\n) dari hasil ifconfig
|
|
280
|
+
ip_clean = res.text.strip()
|
|
281
|
+
# Validasi struktur kecocokan string regex IPv4 standar
|
|
282
|
+
if re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', ip_clean):
|
|
283
|
+
ip_publik = ip_clean
|
|
284
|
+
break
|
|
285
|
+
except:
|
|
286
|
+
continue
|
|
287
|
+
|
|
288
|
+
# Jika IP berhasil didapatkan, lempar ke engine konsensus multi-API untuk memetakan kota/negara Anda
|
|
289
|
+
if ip_publik and not ip_publik.startswith("127."):
|
|
290
|
+
return lacak_ip_multi_web_consensus(ip_publik)
|
|
291
|
+
|
|
292
|
+
# Kondisi darurat jika koneksi internet terputus total (offline)
|
|
293
|
+
return {
|
|
294
|
+
"ip": "127.0.0.1", "isp": "Local Loopback", "country": "UNKNOWN",
|
|
295
|
+
"region": "UNKNOWN", "city": "UNKNOWN", "lat": 0.0, "lon": 0.0,
|
|
296
|
+
"providers_success": 0
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
# PERBAIKAN TOTAL BAGIAN 20: Penghapusan Database Lokal - Digantikan Engine Koordinat Online Global
|
|
300
|
+
def dapatkan_data_provinsi_hlr(nomor_raw):
|
|
301
|
+
try:
|
|
302
|
+
clean_num = str(nomor_raw).replace("+", "").replace(" ", "").replace("-", "")
|
|
303
|
+
if clean_num.startswith("0"): clean_num = "62" + clean_num[1:]
|
|
304
|
+
p_obj = phonenumbers.parse(f"+{clean_num}", None)
|
|
305
|
+
|
|
306
|
+
from phonenumbers import geocoder as geo_lib
|
|
307
|
+
wilayah = geo_lib.description_for_number(p_obj, "id") or "Global / Internasional"
|
|
308
|
+
return wilayah
|
|
309
|
+
except:
|
|
310
|
+
return "UNKNOWN REGION"
|
|
311
|
+
def eksekusi_dorking_google_phone(nomor_raw):
|
|
312
|
+
logs = []
|
|
313
|
+
try:
|
|
314
|
+
clean_num = str(nomor_raw).replace("+", "").replace(" ", "").replace("-", "")
|
|
315
|
+
# PERBAIKAN: Menggunakan endpoint pencarian HTML resmi DuckDuckGo dengan kueri terenkapsulasi
|
|
316
|
+
url = f"https://duckduckgo.com{urllib.parse.quote(clean_num)}"
|
|
317
|
+
headers = {
|
|
318
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
319
|
+
}
|
|
320
|
+
res = requests.get(url, headers=headers, timeout=6.0)
|
|
321
|
+
if res.status_code == 200:
|
|
322
|
+
soup = BeautifulSoup(res.text, 'html.parser')
|
|
323
|
+
# Mencari elemen tautan luar hasil pencarian ril
|
|
324
|
+
links = soup.find_all('a', class_='result__url')
|
|
325
|
+
for a in links:
|
|
326
|
+
actual_link = a.get('href', '').strip()
|
|
327
|
+
# Parsing URL untuk membersihkan redirect internal DuckDuckGo jika ada
|
|
328
|
+
if "uddg=" in actual_link:
|
|
329
|
+
parsed = urllib.parse.urlsplit(actual_link)
|
|
330
|
+
queries = urllib.parse.parse_qs(parsed.query)
|
|
331
|
+
if 'uddg' in queries:
|
|
332
|
+
actual_link = queries['uddg'][0]
|
|
333
|
+
|
|
334
|
+
if actual_link and not any(x in actual_link for x in ["duckduckgo.com", "google.com"]):
|
|
335
|
+
logs.append(actual_link)
|
|
336
|
+
print(f" {Colors.RED}[!] Jejak Digital Publik Online Terdeteksi:{Colors.RESET} {actual_link}")
|
|
337
|
+
except Exception as e:
|
|
338
|
+
print(f" [-] Subsistem web dorking mengalami interupsi: {e}")
|
|
339
|
+
return logs
|
|
340
|
+
def f1_audit_nomor_telepon():
|
|
341
|
+
no = input(" Masukkan Nomor HP Target (+628xx atau 08xx) > ").strip()
|
|
342
|
+
if not no: return
|
|
343
|
+
|
|
344
|
+
try:
|
|
345
|
+
# 1. Validasi Struktur & Normalisasi Format Internasional E.164
|
|
346
|
+
p = phonenumbers.parse(no, "ID" if not no.startswith("+") else None)
|
|
347
|
+
format_e164 = phonenumbers.format_number(p, phonenumbers.PhoneNumberFormat.E164)
|
|
348
|
+
format_nasional = phonenumbers.format_number(p, phonenumbers.PhoneNumberFormat.NATIONAL)
|
|
349
|
+
|
|
350
|
+
clean_num = format_e164.replace("+", "")
|
|
351
|
+
kode_negara = phone_country(p.country_code) if 'phone_country' in globals() else str(p.country_code)
|
|
352
|
+
|
|
353
|
+
from phonenumbers import geocoder as geo_lib
|
|
354
|
+
prov_nama = geo_lib.description_for_number(p, "id") or "Global / Internasional"
|
|
355
|
+
operator = carrier.name_for_number(p, 'id') or "Generik / Tidak Terdeteksi"
|
|
356
|
+
tipe_jalur = str(number_type(p)).split('.')[-1]
|
|
357
|
+
|
|
358
|
+
print("\n" + "═"*75)
|
|
359
|
+
print(f" 📊 PHONE INTEL PANEL: RETRIEVING DETAILS")
|
|
360
|
+
print("═"*75)
|
|
361
|
+
print(f" [+] Format Internasional : {format_e164}")
|
|
362
|
+
print(f" [+] Format Nasional : {format_nasional}")
|
|
363
|
+
print(f" [+] Kode Negara (ISO Code) : {kode_negara.upper()}")
|
|
364
|
+
print(f" [+] Operator Jaringan : {operator}")
|
|
365
|
+
print(f" [+] Wilayah Registrasi HLR : {prov_nama}")
|
|
366
|
+
print(f" [+] Jenis Alokasi Jalur (Type): {tipe_jalur}")
|
|
367
|
+
print(" ---------------------------------------------------------------------------")
|
|
368
|
+
|
|
369
|
+
# PERBAIKAN NYATA: Memanggil fungsi dorking yang tadinya terabaikan agar melacak jejak digital di web
|
|
370
|
+
print(f" {Colors.YELLOW}[*] Melacak jejak digital publik nomor target...{Colors.RESET}")
|
|
371
|
+
jejak_digital = eksekusi_dorking_google_phone(format_e164)
|
|
372
|
+
if not jejak_digital:
|
|
373
|
+
print(" [-] Tidak ada jejak digital publik yang bocor secara terbuka.")
|
|
374
|
+
print(" ---------------------------------------------------------------------------")
|
|
375
|
+
|
|
376
|
+
print(f" {Colors.YELLOW}[*] Mengeksekusi Subsistem phoneintel Sekali Jalan (Single Run)...{Colors.RESET}\n")
|
|
377
|
+
|
|
378
|
+
cmd_exe = "phoneintel" if shutil.which("phoneintel") else "python -m phoneintel"
|
|
379
|
+
subprocess.run(f"{cmd_exe} {format_e164} --dorks --type all --map", shell=True)
|
|
380
|
+
|
|
381
|
+
# Simpan rekap log statis ke database lokal
|
|
382
|
+
logs = [
|
|
383
|
+
f"Target Number: {no}",
|
|
384
|
+
f"Format: {format_e164} | Operator: {operator} | Wilayah: {prov_nama}",
|
|
385
|
+
f"Jejak Temuan: {', '.join(jejak_digital) if jejak_digital else 'Nihil'}"
|
|
386
|
+
]
|
|
387
|
+
simpan_hasil_laporan(clean_num, logs)
|
|
388
|
+
print("\n" + "═"*75)
|
|
389
|
+
print(f" [+] Berkas laporan PhoneIntel berhasil disimpan di folder {OUTPUT_DIR}")
|
|
390
|
+
|
|
391
|
+
except Exception as e:
|
|
392
|
+
print(f"{Colors.RED} [-] Gagal memproses struktur data nomor telepon: {e}{Colors.RESET}")
|
|
393
|
+
|
|
394
|
+
input("\nTekan ENTER untuk kembali ke menu utama...")
|
|
395
|
+
def menu_sherlock_audit_email():
|
|
396
|
+
print(f"\n{Colors.CYAN}[👤] NATIVE SHERLOCK OSINT CORE ENGINE (BYPASS PROTECTION){Colors.RESET}")
|
|
397
|
+
username_target = input(" Masukkan Nama / Username Target Sasar > ").strip()
|
|
398
|
+
if not username_target: return
|
|
399
|
+
|
|
400
|
+
if " " in username_target:
|
|
401
|
+
print(f"{Colors.RED} [-] Username tidak boleh mengandung spasi!{Colors.RESET}")
|
|
402
|
+
input("\nTekan ENTER untuk kembali...")
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
print(f"\n{Colors.CYAN}═" * 65)
|
|
406
|
+
print(f" EXECUTING OFFICIAL SHERLOCK CORE FOR: {username_target}")
|
|
407
|
+
print(f"═" * 65)
|
|
408
|
+
print(f"{Colors.YELLOW}[*] Menghubungkan ke subsistem siber Sherlock...{Colors.RESET}\n")
|
|
409
|
+
|
|
410
|
+
laporan_path = OUTPUT_DIR / f"sherlock_{username_target}.txt"
|
|
411
|
+
|
|
412
|
+
if shutil.which("sherlock"):
|
|
413
|
+
cmd_base = f"sherlock {username_target} --output {laporan_path}"
|
|
414
|
+
elif shutil.which("sherlock-osint"):
|
|
415
|
+
cmd_base = f"sherlock-osint {username_target} --output {laporan_path}"
|
|
416
|
+
else:
|
|
417
|
+
cmd_base = f"{sys.executable} -m sherlock {username_target} --output {laporan_path}"
|
|
418
|
+
|
|
419
|
+
full_cmd = f"{cmd_base} --timeout 5 --nsfw"
|
|
420
|
+
print(f"{Colors.WHITE} [!] Menjalankan enumerasi paket data digital bawaan asli...{Colors.RESET}")
|
|
421
|
+
try:
|
|
422
|
+
subprocess.run(full_cmd, shell=True, check=True)
|
|
423
|
+
print(f"\n{Colors.GREEN}[+] Proses audit jejak nama selesai!{Colors.RESET}")
|
|
424
|
+
print(f" [+] Laporan asli diekspor ke: {laporan_path}")
|
|
425
|
+
except subprocess.CalledProcessError:
|
|
426
|
+
print(f"\n{Colors.RED} [-] Gagal memanggil modul. Pastikan library terpasang di terminal.")
|
|
427
|
+
print(f" [!] Solusi: Jalankan perintah 'pip install sherlock-osint' terlebih dahulu.{Colors.RESET}")
|
|
428
|
+
except Exception as e:
|
|
429
|
+
print(f"\n{Colors.RED} [-] Masalah Driver Host: {e}{Colors.RESET}")
|
|
430
|
+
|
|
431
|
+
input("\nTekan ENTER untuk kembali...")
|
|
432
|
+
def menu_email_silent_scan():
|
|
433
|
+
print(f"\n{Colors.CYAN}[🔍] EMAIL SILENT SCANNER CORE (TRIPLE-LAYER HIGH-PRECISION ENGINE){Colors.RESET}")
|
|
434
|
+
email_target = input(" Masukkan Alamat Email Sasaran > ").strip()
|
|
435
|
+
if not email_target or "@" not in email_target:
|
|
436
|
+
print(f"\n{Colors.RED} [-] Format alamat email tidak valid.{Colors.RESET}"); return
|
|
437
|
+
|
|
438
|
+
if email_target.lower().endswith("@gamil.com"):
|
|
439
|
+
email_target = email_target.lower().replace("@gamil.com", "@gmail.com")
|
|
440
|
+
print(f"{Colors.YELLOW} [!] Mendeteksi typo domain. Otomatis dikoreksi ke: {email_target}{Colors.RESET}")
|
|
441
|
+
|
|
442
|
+
print(f"\n{Colors.CYAN}═" * 75)
|
|
443
|
+
print(f" EXECUTING ENHANCED CRYPTOGRAPHIC INTELLIGENCE FOR: {email_target}")
|
|
444
|
+
print(f"═" * 75)
|
|
445
|
+
print(f"{Colors.YELLOW}[*] Menginisialisasi Mesin Verifikasi Multi-Layer & Analisis Respons...{Colors.RESET}\n")
|
|
446
|
+
|
|
447
|
+
laporan_path = OUTPUT_DIR / f"laporan_email_{email_target.replace('@','_at_')}.txt"
|
|
448
|
+
logs_audit = [f"Target Email Scan: {email_target}", f"Waktu Eksekusi: {datetime.now()}"]
|
|
449
|
+
|
|
450
|
+
session = requests.Session()
|
|
451
|
+
headers_default = {
|
|
452
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
453
|
+
"Accept": "application/json, text/plain, */*",
|
|
454
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
455
|
+
"Connection": "keep-alive"
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
print_lock = concurrent.futures.ThreadPoolExecutor()._shutdown_lock
|
|
459
|
+
|
|
460
|
+
# TARGET 1: Endpoint Internal untuk Jaringan Media Sosial Besar
|
|
461
|
+
SOSIAL_TARGET_API = {
|
|
462
|
+
"Facebook Portal": f"https://facebook.com{email_target}",
|
|
463
|
+
"Instagram Matrix": f"https://instagram.com{email_target}",
|
|
464
|
+
"TikTok Intel": f"https://tiktok.com{email_target}",
|
|
465
|
+
"LinkedIn Gateway": f"https://linkedin.com{email_target}",
|
|
466
|
+
"Twitter / X Platform": f"https://twitter.com{email_target}",
|
|
467
|
+
"Discord Security": f"https://discord.com{email_target}",
|
|
468
|
+
"GitHub Node": f"https://github.com{email_target}",
|
|
469
|
+
"Tumblr Center": f"https://tumblr.com{email_target}",
|
|
470
|
+
"Pinterest Vault": f"https://pinterest.com{email_target}",
|
|
471
|
+
"Reddit Community": f"https://reddit.com{email_target}"
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
# TARGET 2: Endpoint Internal untuk Layanan Cloud & Platform Utama
|
|
475
|
+
CLOUD_TARGET_API = {
|
|
476
|
+
"Google Core Auth": f"https://google.com{email_target}",
|
|
477
|
+
"YouTube Service": f"https://google.com{email_target}",
|
|
478
|
+
"WordPress Engine": f"https://gravatar.com{email_target}",
|
|
479
|
+
"Firefox Accounts": f"https://firefox.com{email_target}",
|
|
480
|
+
"Spotify Client": f"https://spotify.com{email_target}",
|
|
481
|
+
"Adobe Cloud Hub": "https://adobe.com"
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
def periksa_email_tunggal(name, url):
|
|
485
|
+
try:
|
|
486
|
+
if name == "Adobe Cloud Hub":
|
|
487
|
+
headers_adobe = headers_default.copy()
|
|
488
|
+
headers_adobe["Content-Type"] = "application/json"
|
|
489
|
+
res = session.post(url, headers=headers_adobe, json={"email": email_target}, timeout=7.0)
|
|
490
|
+
elif name in ["Facebook Portal", "LinkedIn Gateway"]:
|
|
491
|
+
res = session.post(url, headers=headers_default, data={"email": email_target}, timeout=7.0)
|
|
492
|
+
else:
|
|
493
|
+
res = session.get(url, headers=headers_default, timeout=7.0, allow_redirects=True)
|
|
494
|
+
|
|
495
|
+
konten = res.text.lower()
|
|
496
|
+
|
|
497
|
+
if name in ["Google Core Auth", "YouTube Service"]:
|
|
498
|
+
if "couldn't find your google account" in konten or "tidak dapat menemukan akun" in konten or "error" in konten or res.status_code == 404:
|
|
499
|
+
return name, "KOSONG", ""
|
|
500
|
+
return name, "TERDAFTAR", ""
|
|
501
|
+
|
|
502
|
+
elif name == "Facebook Portal":
|
|
503
|
+
if "did not match any account" in konten or "tidak cocok dengan akun" in konten or "tidak ditemukan" in konten:
|
|
504
|
+
return name, "KOSONG", ""
|
|
505
|
+
return name, "TERDAFTAR", ""
|
|
506
|
+
|
|
507
|
+
elif name in ["Instagram Matrix", "TikTok Intel"]:
|
|
508
|
+
if "available" in konten or "true" in konten or "tidak terdaftar" in konten:
|
|
509
|
+
return name, "KOSONG", ""
|
|
510
|
+
return name, "TERDAFTAR", ""
|
|
511
|
+
|
|
512
|
+
elif name == "LinkedIn Gateway":
|
|
513
|
+
if "sorry, we don't recognize" in konten or "tidak mengenali" in konten:
|
|
514
|
+
return name, "KOSONG", ""
|
|
515
|
+
return name, "TERDAFTAR", ""
|
|
516
|
+
|
|
517
|
+
elif name in ["Twitter / X Platform", "Discord Security", "GitHub Node", "Reddit Community"]:
|
|
518
|
+
if "valid" in konten or "available" in konten or "true" in konten:
|
|
519
|
+
return name, "KOSONG", ""
|
|
520
|
+
return name, "TERDAFTAR", ""
|
|
521
|
+
|
|
522
|
+
elif name == "WordPress Engine":
|
|
523
|
+
if "profile_not_found" in konten or "false" in konten:
|
|
524
|
+
return name, "KOSONG", ""
|
|
525
|
+
return name, "TERDAFTAR", ""
|
|
526
|
+
|
|
527
|
+
elif name == "Firefox Accounts":
|
|
528
|
+
if "false" in konten or "unknown" in konten:
|
|
529
|
+
return name, "KOSONG", ""
|
|
530
|
+
return name, "TERDAFTAR", ""
|
|
531
|
+
|
|
532
|
+
elif name == "Adobe Cloud Hub":
|
|
533
|
+
if "invalid_user" in konten or "does not exist" in konten or "error" in konten:
|
|
534
|
+
return name, "KOSONG", ""
|
|
535
|
+
return name, "TERDAFTAR", ""
|
|
536
|
+
|
|
537
|
+
elif name == "Spotify Client":
|
|
538
|
+
if "status\":200" in konten or "\"status\":1" in konten or "true" in konten:
|
|
539
|
+
return name, "KOSONG", ""
|
|
540
|
+
return name, "TERDAFTAR", ""
|
|
541
|
+
|
|
542
|
+
return name, "KOSONG", ""
|
|
543
|
+
except:
|
|
544
|
+
return name, "ERROR", "Handshake Failed"
|
|
545
|
+
|
|
546
|
+
def audit_sqlite_mail_tracker(email):
|
|
547
|
+
pemicu_terbuka = []
|
|
548
|
+
db_path = Path('mail-tracker.db')
|
|
549
|
+
if db_path.exists():
|
|
550
|
+
try:
|
|
551
|
+
import sqlite3
|
|
552
|
+
conn = sqlite3.connect(str(db_path))
|
|
553
|
+
cursor = conn.cursor()
|
|
554
|
+
cursor.execute("""
|
|
555
|
+
SELECT p.name, l.time, l.ip, l.userAgent
|
|
556
|
+
FROM pixels p
|
|
557
|
+
JOIN logs l ON p.id = l.pixelId
|
|
558
|
+
WHERE p.name LIKE ? ORDER BY l.time DESC
|
|
559
|
+
""", (f"%{email}%",))
|
|
560
|
+
rows = cursor.fetchall()
|
|
561
|
+
for r in rows:
|
|
562
|
+
pemicu_terbuka.append({"pixel_name": r[0], "waktu": r[1], "ip": r[2], "ua": r[3]})
|
|
563
|
+
conn.close()
|
|
564
|
+
except: pass
|
|
565
|
+
return pemicu_terbuka
|
|
566
|
+
results_counter = 0
|
|
567
|
+
log_pelacak_lokal = audit_sqlite_mail_tracker(email_target)
|
|
568
|
+
|
|
569
|
+
# 1. PARALEL MULTI-THREADING BAGIAN 1: Media Sosial Besar (Pasti Tampil Terpisah di Terminal)
|
|
570
|
+
print(f" {Colors.WHITE}[{Colors.GREEN}*{Colors.WHITE}] Jaringan Integrasi Media Sosial & Komunitas Global (Real-Time Matrix):")
|
|
571
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
|
|
572
|
+
kamus_sosial = {executor.submit(periksa_email_tunggal, nama_situs_sosial, alamat_url_sosial): nama_situs_sosial for nama_situs_sosial, alamat_url_sosial in SOSIAL_TARGET_API.items()}
|
|
573
|
+
for future in concurrent.futures.as_completed(kamus_sosial):
|
|
574
|
+
nama_situs, status_hasil, _ = future.result()
|
|
575
|
+
with print_lock:
|
|
576
|
+
if status_hasil == "TERDAFTAR":
|
|
577
|
+
print(f" {Colors.WHITE}[{Colors.GREEN}+{Colors.WHITE}] {nama_situs:<24} : {Colors.GREEN}Terdaftar (Valid & Aktif){Colors.RESET}")
|
|
578
|
+
logs_audit.append(f"[+] {nama_situs}: Terdaftar")
|
|
579
|
+
results_counter += 1
|
|
580
|
+
elif status_hasil == "KOSONG":
|
|
581
|
+
print(f" {Colors.WHITE}[{Colors.RED}-{Colors.WHITE}] {nama_situs:<24} : {Colors.RED}Tidak Terdaftar / Aman{Colors.RESET}")
|
|
582
|
+
else:
|
|
583
|
+
print(f" {Colors.WHITE}[{Colors.YELLOW}X{Colors.WHITE}] {nama_situs:<24} : {Colors.YELLOW}Timeout Jaringan{Colors.RESET}")
|
|
584
|
+
print(" ---------------------------------------------------------------------------")
|
|
585
|
+
|
|
586
|
+
# 2. PARALEL MULTI-THREADING BAGIAN 2: Layanan Cloud & Platform Teknologi Core
|
|
587
|
+
print(f" {Colors.WHITE}[{Colors.GREEN}*{Colors.WHITE}] Ekosistem Akun Layanan Cloud & Platform Teknologi:")
|
|
588
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
|
|
589
|
+
kamus_cloud = {executor.submit(periksa_email_tunggal, nama_situs_cloud, alamat_url_cloud): nama_situs_cloud for nama_situs_cloud, alamat_url_cloud in CLOUD_TARGET_API.items()}
|
|
590
|
+
for future in concurrent.futures.as_completed(kamus_cloud):
|
|
591
|
+
nama_situs, status_hasil, _ = future.result()
|
|
592
|
+
with print_lock:
|
|
593
|
+
if status_hasil == "TERDAFTAR":
|
|
594
|
+
print(f" {Colors.WHITE}[{Colors.GREEN}+{Colors.WHITE}] {nama_situs:<24} : {Colors.GREEN}Terdaftar (Valid & Aktif){Colors.RESET}")
|
|
595
|
+
logs_audit.append(f"[+] {nama_situs}: Terdaftar")
|
|
596
|
+
results_counter += 1
|
|
597
|
+
elif status_hasil == "KOSONG":
|
|
598
|
+
print(f" {Colors.WHITE}[{Colors.RED}-{Colors.WHITE}] {nama_situs:<24} : {Colors.RED}Tidak Terdaftar / Aman{Colors.RESET}")
|
|
599
|
+
else:
|
|
600
|
+
print(f" {Colors.WHITE}[{Colors.YELLOW}X{Colors.WHITE}] {nama_situs:<24} : {Colors.YELLOW}Timeout Jaringan{Colors.RESET}")
|
|
601
|
+
|
|
602
|
+
# 3. BAGIAN 3: Integrasi Hasil Log Mail-Tracker
|
|
603
|
+
print("\n" + "═"*75)
|
|
604
|
+
print(f" 📊 LOCAL MAIL-TRACKER ENGINE INTERACTION LOGS (SQLite Sync)")
|
|
605
|
+
print("═"*75)
|
|
606
|
+
if log_pelacak_lokal:
|
|
607
|
+
print(f" {Colors.RED}[!] TARGET TERDETEKSI PERNAH MEMBUKA EMAIL PELACAK!{Colors.RESET}")
|
|
608
|
+
for log in log_pelacak_lokal:
|
|
609
|
+
print(f" {Colors.WHITE}[+] Nama Pixel : {Colors.CYAN}{log['pixel_name']}{Colors.RESET}")
|
|
610
|
+
print(f" [+] Waktu Buka : {log['waktu']}")
|
|
611
|
+
print(f" [+] Alamat IP : {Colors.GREEN}{log['ip']}{Colors.RESET}")
|
|
612
|
+
print(f" [+] User-Agent : {Colors.YELLOW}{log['ua']}{Colors.RESET}")
|
|
613
|
+
print(" ---------------------------------------------------------------------")
|
|
614
|
+
logs_audit.append(f"[ALERT_OPEN] Pixel: {log['pixel_name']} | IP: {log['ip']} | Waktu: {log['waktu']}")
|
|
615
|
+
else:
|
|
616
|
+
print(f" {Colors.GREEN}[✓] Nihil. Target belum pernah memicu atau memuat tautan Tracker Pixel Anda.{Colors.RESET}")
|
|
617
|
+
|
|
618
|
+
print(f"\n{Colors.CYAN}═" * 75)
|
|
619
|
+
print(f" [✓] Pemindaian selesai. Berhasil memvalidasi {results_counter} entitas digital asli.")
|
|
620
|
+
simpan_hasil_laporan(email_target, logs_audit)
|
|
621
|
+
print(f" [+] Rekaman jejak digital intelijen disimpan di: {laporan_path}")
|
|
622
|
+
input("\nTekan ENTER untuk kembali...")
|
|
623
|
+
def menu_investigasi_ghosteye():
|
|
624
|
+
while True:
|
|
625
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
626
|
+
# PERBAIKAN UTAMA: Karakter '\_' ilegal pada banner ASCII telah dibersihkan total agar tidak memicu SyntaxWarning
|
|
627
|
+
print(r"""
|
|
628
|
+
('-. .-. .-') .-') _ ('-. ('-.
|
|
629
|
+
( OO ) / Ghost ( OO ). ( OO) ) _( OO) Eye _( OO)
|
|
630
|
+
,----. ,--. ,--. .-'),-----. (--)---\_)/ '._ (,------. ,--. ,--.(,------.
|
|
631
|
+
' .-./-') | | | |( OO' .-. '/ _ | |'--...__) | .---' \ `.' / | .---'
|
|
632
|
+
|
|
633
|
+
| |_( O- )| .| |/ | | | |/ :` `. '--. .--' | | .-') /) | |
|
|
634
|
+
| | .--, \| |/_) | |/| | '..`''.) | | (| '--.(OO \ /. (| '--.
|
|
635
|
+
(| | '. (_/| .-. | \ | | | |.-._) \ | | | .--' | / / | .--'
|
|
636
|
+
|
|
637
|
+
| '--' | | | | | `' '-' '\ / | | | `---.`-./ / | `---.
|
|
638
|
+
`------' `--' `--' `-----' `-----' `--' V3 `------' `--' `------'
|
|
639
|
+
""")
|
|
640
|
+
print(" [ PANEL INVESTIGASI GHOSTEYE PERMANEN v3 ]\n" + "═"*75)
|
|
641
|
+
print(" 1. Whois Domain Lookup 2. DNS Resolver Any Trace")
|
|
642
|
+
print(" 3. Nmap Port Scan Profile 4. HTTP Header Grabber")
|
|
643
|
+
print(" 5. Clickjacking Options Header 6. Robots.txt Core Scanner")
|
|
644
|
+
print(" 7. Cloudflare Cookie Scraper 8. Deep Web Link Grabber")
|
|
645
|
+
print(" 9. CMS Identified Technologies 10. MTR Traceroute Target")
|
|
646
|
+
print(" 11. Crawler URL + Robots.txt 12. SSL Transparency Log Monitor")
|
|
647
|
+
print(" 0. Kembali Ke Menu Navigasi Utama")
|
|
648
|
+
|
|
649
|
+
p = input(r"\n oint_combo:ghosteye_panel~\$ ").strip()
|
|
650
|
+
if p == "0": break
|
|
651
|
+
else: memproses_opsi_ghosteye(p)
|
|
652
|
+
# OPTIMASI FITUR 5 (BAGIAN 1): Alokasi Perintah Native Windows untuk Panel GhostEye
|
|
653
|
+
def memproses_opsi_ghosteye(p):
|
|
654
|
+
if p in ["1", "2", "3", "4", "6", "9", "10", "11", "12"]:
|
|
655
|
+
target = input("\033[1;91m[+] Enter Domain or IP Address Target: \033[1;m").lower().strip()
|
|
656
|
+
if not target: return
|
|
657
|
+
# Bersihkan domain dari protokol jika user memasukkan http://
|
|
658
|
+
target_clean = target.replace("https://", "").replace("http://", "").split("/")[0]
|
|
659
|
+
|
|
660
|
+
if p == "1":
|
|
661
|
+
print(f"\033[34m[~] Searching for Whois Lookup via Python Native: \033[0m{target_clean}")
|
|
662
|
+
try:
|
|
663
|
+
from ipwhois import IPWhois
|
|
664
|
+
ip_target = socket.gethostbyname(target_clean)
|
|
665
|
+
obj = IPWhois(ip_target)
|
|
666
|
+
results = obj.lookup_rdap()
|
|
667
|
+
for k, v in results.items():
|
|
668
|
+
if isinstance(v, dict) or isinstance(v, list): continue
|
|
669
|
+
print(f" {k.upper()}: {v}")
|
|
670
|
+
except Exception as e:
|
|
671
|
+
print(f"[-] Gagal melakukan Whois online: {e}. Pastikan target adalah IP atau Domain valid.")
|
|
672
|
+
elif p == "2":
|
|
673
|
+
print(f"\033[34m[~] Searching for DNS Lookup (A/MX/TXT Records): \033[0m{target_clean}")
|
|
674
|
+
for record_type in ['A', 'MX', 'TXT']:
|
|
675
|
+
try:
|
|
676
|
+
answers = dns.resolver.resolve(target_clean, record_type)
|
|
677
|
+
print(f"\n [*] Record {record_type}:")
|
|
678
|
+
for rdata in answers: print(f" └─> {rdata.to_text()}")
|
|
679
|
+
except: print(f" [-] No {record_type} records found.")
|
|
680
|
+
elif p == "3":
|
|
681
|
+
print(f"\033[34m[~] Scanning Nmap Port Scan (Windows Driver Safe): \033[0m{target_clean}\n")
|
|
682
|
+
try:
|
|
683
|
+
nm = nmap.PortScanner()
|
|
684
|
+
print(" [*] Memulai pemindaian port populer (21,22,23,25,53,80,443)...")
|
|
685
|
+
nm.scan(target_clean, '21,22,23,25,53,80,443', arguments='-Pn')
|
|
686
|
+
for host in nm.all_hosts():
|
|
687
|
+
print(f" Host: {host} ({nm[host].hostname()}) | Status: {nm[host].state()}")
|
|
688
|
+
for proto in nm[host].all_protocols():
|
|
689
|
+
ports = sorted(nm[host][proto].keys())
|
|
690
|
+
for port in ports:
|
|
691
|
+
print(f" └─> Port: {port} | State: {nm[host][proto][port]['state']} | Service: {nm[host][proto][port]['name']}")
|
|
692
|
+
except Exception as e:
|
|
693
|
+
print(f"[-] Nmap Core Engine tidak ditemukan di Windows PATH Anda. \n [!] Solusi: Instal Nmap untuk Windows atau jalankan CMD sebagai Administrator.")
|
|
694
|
+
elif p == "4":
|
|
695
|
+
print(f"\033[34m[~] Scanning HTTP Header Grabber: \033[0m{target_clean}")
|
|
696
|
+
try:
|
|
697
|
+
url = f"https://{target_clean}"
|
|
698
|
+
res = requests.get(url, timeout=5.0, headers={"User-Agent": "Mozilla/5.0"})
|
|
699
|
+
for k, v in res.headers.items(): print(f" {k}: {v}")
|
|
700
|
+
except:
|
|
701
|
+
try:
|
|
702
|
+
res = requests.get(f"http://{target_clean}", timeout=5.0)
|
|
703
|
+
for k, v in res.headers.items(): print(f" {k}: {v}")
|
|
704
|
+
except Exception as e: print(f"[-] Gagal mengambil HTTP Header: {e}")
|
|
705
|
+
else:
|
|
706
|
+
memproses_opsi_ghosteye_lanjutan(p, target_clean)
|
|
707
|
+
input("\nTekan ENTER untuk melanjutkan...")
|
|
708
|
+
else:
|
|
709
|
+
memproses_opsi_ghosteye_cookies_web(p)
|
|
710
|
+
|
|
711
|
+
def memproses_opsi_ghosteye_lanjutan(p, target):
|
|
712
|
+
if p == "6":
|
|
713
|
+
url = target if target.startswith("http") else f"http://{target}"
|
|
714
|
+
try:
|
|
715
|
+
res = requests.get(url + "/robots.txt", timeout=4.0)
|
|
716
|
+
print(f"\n[ Status Code: {res.status_code} ]\n" + res.text)
|
|
717
|
+
except: print("[-] Gagal menarik file robots.txt dari server target.")
|
|
718
|
+
elif p == "9":
|
|
719
|
+
url = target if target.startswith("http") else f"https://{target}"
|
|
720
|
+
try:
|
|
721
|
+
obj = webtech.WebTech()
|
|
722
|
+
print(obj.start_from_url(url, timeout=10))
|
|
723
|
+
except Exception as e: print(f"[-] Webtech Python Engine error: {e}")
|
|
724
|
+
elif p == "10":
|
|
725
|
+
print(f"\033[34m[~] Searching for Traceroute via ICMP Echo Node: \033[0m{target}")
|
|
726
|
+
from urllib.parse import urlparse
|
|
727
|
+
host_sanitized = target.replace("https://", "").replace("http://", "").split('/')[0].split(':')[0]
|
|
728
|
+
try:
|
|
729
|
+
output_riil = subprocess.check_output(f"tracert -d -h 15 {host_sanitized}", shell=True, text=True)
|
|
730
|
+
print(output_riil)
|
|
731
|
+
except Exception as e: print(f"[-] Perintah bawaan host Windows gagal dieksekusi: {e}")
|
|
732
|
+
elif p == "11":
|
|
733
|
+
url = target if target.startswith("http") else f"http://{target}"
|
|
734
|
+
try:
|
|
735
|
+
content = requests.get(url, timeout=5.0).text
|
|
736
|
+
title = re.findall(r"<title>(.*?)<\/title>", content)
|
|
737
|
+
print("[+] Title: ", "".join(title))
|
|
738
|
+
links = re.findall(r"http[s]?://(?:[a-zA-Z]|[0-9]|[\$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", content)
|
|
739
|
+
print("[+] Extract links (Max 15 ditampilkan): \n", "\n".join(links[:15]))
|
|
740
|
+
except Exception as e: print(f"[-] Gagal melakukan crawling link: {e}")
|
|
741
|
+
elif p == "12":
|
|
742
|
+
try:
|
|
743
|
+
# PERBAIKAN FATAL: Menambahkan parameter query kueri '?q=' dan slash '/' yang valid untuk API crt.sh
|
|
744
|
+
res_ssl = requests.get(f'https://crt.sh{target}&output=json', timeout=15).json()
|
|
745
|
+
names = set()
|
|
746
|
+
for cert in res_ssl:
|
|
747
|
+
if 'name_value' in cert:
|
|
748
|
+
for name in cert['name_value'].splitlines():
|
|
749
|
+
name = name.lstrip('*.')
|
|
750
|
+
if target in name: names.add(name)
|
|
751
|
+
for name in sorted(names): print(f" └─> {name}")
|
|
752
|
+
print(f"\n[+] Berhasil menemukan {len(names)} sub-domain unik dari SSL Log.")
|
|
753
|
+
except Exception as e: print(f"[-] Gagal menjangkau server API crt.sh: {e}")
|
|
754
|
+
def memproses_opsi_ghosteye_cookies_web(p):
|
|
755
|
+
if p == "5":
|
|
756
|
+
target = input("\033[1;91m[+] Enter Domain to test Clickjacking: \033[1;m").lower().strip()
|
|
757
|
+
if not target: return
|
|
758
|
+
if not (target.startswith("http://") or target.startswith("https://")): target = "http://" + target
|
|
759
|
+
try:
|
|
760
|
+
headers = requests.get(target).headers
|
|
761
|
+
if "X-Frame-Options" in headers: print("\n[+] \033[1;34mClick Jacking Header is present (SAFE)\033[1;m")
|
|
762
|
+
else: print("\n[*] \033[1;34mX-Frame-Options-Header is missing! (VULNERABLE)\033[1;m")
|
|
763
|
+
except: pass
|
|
764
|
+
input("\nTekan ENTER...")
|
|
765
|
+
elif p == "7":
|
|
766
|
+
target = input("\033[1;91m[+] Enter Cloudflare Domain: \033[1;m").lower().strip()
|
|
767
|
+
if not target: return
|
|
768
|
+
if not (target.startswith("http://") or target.startswith("https://")): target = "http://" + target
|
|
769
|
+
try:
|
|
770
|
+
sess = cfscrape.create_scraper()
|
|
771
|
+
cookie_value, user_agent = cfscrape.get_cookie_string(target)
|
|
772
|
+
print(f"[+] Cookie: {cookie_value}\n[+] UA: {user_agent}")
|
|
773
|
+
data = sess.get(target)
|
|
774
|
+
out = BeautifulSoup(data.content, 'html.parser')
|
|
775
|
+
print(out)
|
|
776
|
+
except: print("[-] Gagal membongkar token IUAM Cloudflare.")
|
|
777
|
+
input("\nTekan ENTER...")
|
|
778
|
+
elif p == "8": jalankan_link_grabber_crawler()
|
|
779
|
+
|
|
780
|
+
def jalankan_link_grabber_crawler():
|
|
781
|
+
target = input("\033[1;91m[+] Enter Target Domain Link Grabber: \033[1;m").lower().strip()
|
|
782
|
+
if not target: return
|
|
783
|
+
if not (target.startswith("http://") or target.startswith("https://")): target = "http://" + target
|
|
784
|
+
deq = deque([target]); pro = set()
|
|
785
|
+
try:
|
|
786
|
+
while len(deq) and len(pro) < 50:
|
|
787
|
+
url = deq.popleft(); pro.add(url)
|
|
788
|
+
print("[+] Crawling Link -> " + url)
|
|
789
|
+
try:
|
|
790
|
+
soup = BeautifulSoup(requests.get(url, timeout=3.0).text, "lxml")
|
|
791
|
+
for anchor in soup.find_all("a"):
|
|
792
|
+
link = anchor.attrs.get("href", "")
|
|
793
|
+
if link.startswith("/"): link = "{0.scheme}://{0.netloc}".format(urllib.parse.urlsplit(url)) + link
|
|
794
|
+
if link not in deq and link not in pro: deq.append(link)
|
|
795
|
+
except: continue
|
|
796
|
+
except KeyboardInterrupt: pass
|
|
797
|
+
input("\nCrawling Berhenti. Tekan ENTER...")
|
|
798
|
+
def menu_audit_wifi_sub():
|
|
799
|
+
while True:
|
|
800
|
+
print(f"\n{Colors.CYAN}--- HARDWARE NETWORK & DUMP LOCAL PROFILE ---{Colors.RESET}")
|
|
801
|
+
print(" 1. Pindai Radar WiFi Sekitar (BSSID/SSID)\n 2. Bongkar Wi-Fi Profiles & Password Yang Tertinggal\n 3. Kembali Ke Navigasi Utama")
|
|
802
|
+
p = input(" osint_hardware:~$ pilih_opsi> ").strip()
|
|
803
|
+
if p == "1":
|
|
804
|
+
try: print(subprocess.check_output("netsh wlan show networks mode=bssid", shell=True, text=True))
|
|
805
|
+
except: print("[-] Hanya didukung pada OS Windows dengan adapter aktif.")
|
|
806
|
+
input("\nENTER...")
|
|
807
|
+
elif p == "2":
|
|
808
|
+
try:
|
|
809
|
+
data = subprocess.check_output("netsh wlan show profiles", shell=True, text=True)
|
|
810
|
+
profiles = re.findall(r"All User Profile\s*:\s*(.*)", data)
|
|
811
|
+
print(f"\n{Colors.WHITE}┌────────────────────────────────────────────────────────┐{Colors.RESET}")
|
|
812
|
+
for name in profiles:
|
|
813
|
+
name = name.strip().replace("\r", "")
|
|
814
|
+
try:
|
|
815
|
+
detail = subprocess.check_output(f'netsh wlan show profile "{name}" key=clear', shell=True, text=True)
|
|
816
|
+
passwords = re.findall(r"Key Content\s*:\s*(.*)", detail)
|
|
817
|
+
pw = passwords.strip().replace("\r", "") if passwords else "(Open Connection)"
|
|
818
|
+
print(f" [+] SSID: {Colors.GREEN}{name:<20}{Colors.RESET} | Sandi: {Colors.WHITE}{pw}{Colors.RESET}")
|
|
819
|
+
except: pass
|
|
820
|
+
print(f"{Colors.WHITE}└────────────────────────────────────────────────────────┘{Colors.RESET}")
|
|
821
|
+
except: print("[-] Hanya didukung pada sistem host Windows.")
|
|
822
|
+
input("\nENTER...")
|
|
823
|
+
elif p == "3": break
|
|
824
|
+
|
|
825
|
+
def menu_eksternal_cmd_tools():
|
|
826
|
+
while True:
|
|
827
|
+
print(f"\n{Colors.CYAN}--- EXECUTE EXTERNAL INTERFACE TOOLS ---{Colors.RESET}")
|
|
828
|
+
print(" 1. Panggil PhoneInfoga Command Scanner\n 2. Download & Deploy GhostEye Lokal\n 3. Panggil Holehe Command Line Interface\n 4. Kembali")
|
|
829
|
+
p = input(" osint_external:~$ pilih_opsi> ").strip()
|
|
830
|
+
if p == "1":
|
|
831
|
+
target = input(" Masukkan nomor target (+62xxx) > ").strip()
|
|
832
|
+
if target:
|
|
833
|
+
exe = "phoneinfoga.exe" if platform.system().lower() == "windows" else "./phoneinfoga"
|
|
834
|
+
if os.path.exists(exe) or shutil.which("phoneinfoga"):
|
|
835
|
+
cmd = "phoneinfoga" if shutil.which("phoneinfoga") else exe
|
|
836
|
+
subprocess.run(f"{cmd} scan -n {target}", shell=True)
|
|
837
|
+
else:
|
|
838
|
+
print(" [!] Biner PhoneInfoga tidak ditemukan lokal. Menjalankan auto-download...")
|
|
839
|
+
if unduh_phoneinfoga_otomatis(): subprocess.run(f"{exe} scan -n {target}", shell=True)
|
|
840
|
+
input("\nENTER...")
|
|
841
|
+
elif p == "2":
|
|
842
|
+
unduh_ghosteye_otomatis(); input("\nENTER...")
|
|
843
|
+
elif p == "3":
|
|
844
|
+
target_mail = input(" Masukkan email sasaran dork holehe > ").strip()
|
|
845
|
+
if target_mail:
|
|
846
|
+
print(f" [*] Mengeksekusi biner perintah shell holehe cli...")
|
|
847
|
+
subprocess.run(f"holehe {target_mail}", shell=True)
|
|
848
|
+
input("\nENTER...")
|
|
849
|
+
elif p == "4": break
|
|
850
|
+
def f2_lacak_ip_konsensus():
|
|
851
|
+
ip_input = input(" Masukkan Alamat IP Target > ").strip()
|
|
852
|
+
if not ip_input: return
|
|
853
|
+
print(f"\n{Colors.YELLOW}[*] Menghitung konsensus geolokasi IP multi-provider...{Colors.RESET}")
|
|
854
|
+
|
|
855
|
+
# Memanggil sistem consensus engine bawaan skrip Anda yang asli
|
|
856
|
+
hasil = lacak_ip_multi_web_consensus(ip_input)
|
|
857
|
+
|
|
858
|
+
print("\n" + "═"*75)
|
|
859
|
+
print(f" [+] Target IP Address : {hasil.get('ip')}")
|
|
860
|
+
print(f" [+] ISP / Organization: {hasil.get('isp')}")
|
|
861
|
+
print(f" [+] Negara / Country : {hasil.get('country')}")
|
|
862
|
+
print(f" [+] Wilayah / Region : {hasil.get('region')}")
|
|
863
|
+
print(f" [+] Kota / City : {hasil.get('city')}")
|
|
864
|
+
print(f" [+] Koordinat Konsensus: LAT {hasil.get('lat')} / LON {hasil.get('lon')}")
|
|
865
|
+
print(f" [+] Tautan Google Maps: {buat_tautan_peta(hasil.get('lat'), hasil.get('lon'))}")
|
|
866
|
+
print(f" [+] Resolusi Provider : {hasil.get('providers_success')} Web API Merespons")
|
|
867
|
+
print("═"*75)
|
|
868
|
+
|
|
869
|
+
logs = [f"IP Target: {ip_input}", f"City: {hasil.get('city')}", f"Maps: {buat_tautan_peta(hasil.get('lat'), hasil.get('lon'))}"]
|
|
870
|
+
simpan_hasil_laporan(ip_input, logs)
|
|
871
|
+
input("\nTekan ENTER untuk kembali...")
|
|
872
|
+
def tampilkan_banner_panel(geo_data):
|
|
873
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
874
|
+
status_cyber = periksa_kebocoran_proxy_investigator(geo_data.get("ip"))
|
|
875
|
+
width = get_terminal_width()
|
|
876
|
+
ascii_banner = r"""
|
|
877
|
+
____ _____ _____ _ _ _____ _____ ____ __ __ ____ ____
|
|
878
|
+
/ __ \ / ____|_ _| \ | |_ _| / ____/ __ \| \/ | _ \ / __ \
|
|
879
|
+
| | | | (___ | | | \| | | | | | | | | | \ / | |_) | | | |
|
|
880
|
+
| | | |\___ \ | | | . ` | | | | | | | | | |\/| | _ <| | | |
|
|
881
|
+
| |__| |____) |_| |_| |\ |_| |_ | |___| |__| | | | | |_) | |__| |
|
|
882
|
+
\____/|_____/|_____|_| \_|_____| \_____\____/|_| |_|____/ \____/ """
|
|
883
|
+
print(Fore.CYAN + center_text(wrap_banner_lines(ascii_banner, width), width))
|
|
884
|
+
print(Fore.RED + center_text("Framework Intelijen Siber Gabungan v4.5 MODULAR", width) + "\n")
|
|
885
|
+
print(f" {Colors.CYAN}[*] TERMINAL IP :{Colors.RESET} {geo_data.get('ip')} ({status_cyber})")
|
|
886
|
+
print(f" {Colors.CYAN}[*] LOKASI CORE HOST :{Colors.RESET} {geo_data.get('city').upper()}, {geo_data.get('country')} (LAT {geo_data.get('lat')} / LON {geo_data.get('lon')})")
|
|
887
|
+
print(f"{Colors.CYAN}" + "═" * width + f"{Colors.RESET}")
|
|
888
|
+
|
|
889
|
+
def jalan_program():
|
|
890
|
+
perangkat = dapatkan_geolokan_perangkat_riil()
|
|
891
|
+
while True:
|
|
892
|
+
tampilkan_banner_panel(perangkat)
|
|
893
|
+
print(" 1. Sherlock Audit Footprint Scanner (username)")
|
|
894
|
+
print(" 2. Cross-Platform Social Media Auth Tracker (Email Profile Check)")
|
|
895
|
+
print(" 3. Phone Intel - Informasi Registrasi Jaringan & Jejak Publik")
|
|
896
|
+
print(" 4. Deep IP Tracer Matrix (Konsensus Multi-API & Geolocation)")
|
|
897
|
+
print(" 5. Konsol Investigasi Khusus Jaringan Web (Panel GhostEye)")
|
|
898
|
+
print(" 6. Hardware & Local Network Control Panel (WiFi Password Dump)")
|
|
899
|
+
print(" 7. Panggil Subsistem Eksternal CMD Suite Tools (Holehe CLI)")
|
|
900
|
+
print(" 0. Keluar / Exit Framework")
|
|
901
|
+
pilih = input("\noint_combo:~$ pilih_panel> ").strip()
|
|
902
|
+
if pilih == "1": menu_sherlock_audit_email()
|
|
903
|
+
elif pilih == "2": menu_email_silent_scan() # <--- GANTI MENJADI NAMA BARU INI
|
|
904
|
+
elif pilih == "3": f1_audit_nomor_telepon()
|
|
905
|
+
elif pilih == "4": f2_lacak_ip_konsensus()
|
|
906
|
+
elif pilih == "5": menu_investigasi_ghosteye()
|
|
907
|
+
elif pilih == "6": menu_audit_wifi_sub()
|
|
908
|
+
elif pilih == "7": menu_eksternal_cmd_tools()
|
|
909
|
+
elif pilih == "0":
|
|
910
|
+
print(f"\n{Colors.GREEN}[+] Memutus tautan core framework... Bersih! Sampai jumpa.{Colors.RESET}"); sys.exit(0)
|
|
911
|
+
else:
|
|
912
|
+
print(f"\n{Colors.RED}[!] Input salah. Silakan masukkan menu utama yang valid.{Colors.RESET}"); time.sleep(1.2)
|
|
913
|
+
|
|
914
|
+
if __name__ == "__main__":
|
|
915
|
+
try: jalan_program()
|
|
916
|
+
except KeyboardInterrupt: print(f"\n\n{Colors.RED}[!] Sesi diputus secara paksa oleh user (Ctrl+C).{Colors.RESET}")
|