-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecon send telegram.py
More file actions
161 lines (137 loc) · 6.18 KB
/
Copy pathrecon send telegram.py
File metadata and controls
161 lines (137 loc) · 6.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import os
import time
import shutil
import requests
import subprocess
import configparser
import argparse
# Read settings from config.ini
config = configparser.ConfigParser()
config.read("config.ini")
BOT_TOKEN = config.get("Telegram", "BOT_TOKEN", fallback=os.getenv("TELEGRAM_BOT_TOKEN"))
CHAT_ID = config.get("Telegram", "CHAT_ID", fallback=os.getenv("TELEGRAM_CHAT_ID"))
SLEEP_TIME = config.getint("Settings", "SLEEP_TIME", fallback=60)
# Ensure results directory exists
RESULTS_DIR = "results"
os.makedirs(RESULTS_DIR, exist_ok=True)
HTTPX_RESULTS_FILE = os.path.join(RESULTS_DIR, "httpx_results.txt")
NUCLEI_RESULTS_FILE = os.path.join(RESULTS_DIR, "nuclei_results.txt")
SUBDOMAINS_FILE = os.path.join(RESULTS_DIR, "subdomains.txt")
def log_error(message):
with open("errors.log", "a") as f:
f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")
def read_previous_results(file_path):
"""Read previous results from a file."""
if os.path.exists(file_path):
with open(file_path, "r") as f:
return set(f.read().splitlines())
return set()
def append_new_results(file_path, new_results):
"""Append new results to the file without deleting old ones."""
with open(file_path, "a") as f:
f.write("\n".join(new_results) + "\n")
def send_telegram_message(message):
"""Send a message to Telegram with rate-limiting."""
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
for chunk in [message[i:i+4000] for i in range(0, len(message), 4000)]:
data = {"chat_id": CHAT_ID, "text": chunk, "parse_mode": "Markdown"}
try:
requests.post(url, data=data)
time.sleep(1)
except requests.RequestException as e:
log_error(f"Telegram error: {e}")
def tool_exists(tool_name):
"""Check if a tool is installed."""
return shutil.which(tool_name) is not None
def run_command(cmd, description):
"""Run a shell command safely and print status."""
print(f"[*] Running: {description}...")
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return set(result.stdout.splitlines())
except Exception as e:
log_error(f"Error running {cmd}: {e}")
return set()
def run_subdomain_enumeration(domain_file):
"""Run all subdomain enumeration tools and collect results."""
tools = [
f"subfinder -dL {domain_file}",
f"amass enum -passive -df {domain_file}",
f"amass enum -active -df {domain_file}",
f"amass enum -brute -df {domain_file}",
f"amass enum -df {domain_file} -src",
f"findomain -f {domain_file}",
f"cat {domain_file} | waybackurls | awk -F/ '{{print $3}}' | sort -u",
f"cat {domain_file} | gau | awk -F/ '{{print $3}}' | sort -u",
f"sublist3r -d $(cat {domain_file})"
]
all_results = set()
for tool in tools:
all_results |= run_command(tool, tool.split()[0])
with open(domain_file, "r") as f:
domains = [line.strip() for line in f if line.strip()]
for domain in domains:
response = requests.get(f"https://crt.sh/?q=%25.{domain}&output=json").text
try:
subdomains = subprocess.run(
"jq -r '.[].name_value'",
input=response,
shell=True,
capture_output=True,
text=True
).stdout.splitlines()
subdomains = {sub.replace("*.", "") for sub in subdomains if domain in sub}
all_results |= subdomains
except Exception as e:
log_error(f"Error fetching subdomains from crt.sh: {e}")
append_new_results(SUBDOMAINS_FILE, all_results)
return all_results
def run_httpx(input_file, output_file, previous_results):
new_results = run_command(f"httpx -l {input_file} -silent", "HTTPX")
new_entries = new_results - previous_results
if new_entries:
send_telegram_message("*New HTTPX results found:*\n" + "\n".join(new_entries))
append_new_results(output_file, new_entries)
return previous_results | new_results
def run_nuclei(input_file, output_file, previous_results):
new_results = run_command(f"nuclei -l {input_file} -severity low,medium,high,critical -silent", "Nuclei")
new_entries = new_results - previous_results
if new_entries:
send_telegram_message("*New Nuclei results found:*\n" + "\n".join(new_entries))
append_new_results(output_file, new_entries)
return previous_results | new_results
def run_tools(domains):
"""Run tools in sequence, comparing results each time."""
domain_file = "temp_domains.txt"
with open(domain_file, "w") as f:
f.write("\n".join(domains) + "\n")
subdomains = run_subdomain_enumeration(domain_file)
previous_httpx_results = read_previous_results(HTTPX_RESULTS_FILE)
previous_nuclei_results = read_previous_results(NUCLEI_RESULTS_FILE)
current_httpx_results = run_httpx(SUBDOMAINS_FILE, HTTPX_RESULTS_FILE, previous_httpx_results)
current_nuclei_results = run_nuclei(SUBDOMAINS_FILE, NUCLEI_RESULTS_FILE, previous_nuclei_results)
return current_httpx_results, current_nuclei_results
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-l", "--list", help="File containing a list of domains")
parser.add_argument("domains", nargs="*", help="Directly input domains")
args = parser.parse_args()
if args.list:
if not os.path.exists(args.list):
print("[!] File not found!")
exit(1)
with open(args.list, "r") as f:
domains = [line.strip() for line in f if line.strip()]
elif args.domains:
domains = args.domains
else:
print("[!] You must provide a domain list either via a file (-l) or direct input!")
exit(1)
try:
while True:
run_tools(domains)
print(f"[*] Sleeping for {SLEEP_TIME} seconds...")
time.sleep(SLEEP_TIME)
except KeyboardInterrupt:
print("\n[!] Stopping script safely.")
exit(0)