bhp-pro 1.2.9__tar.gz → 1.3.1__tar.gz
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.
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/PKG-INFO +1 -1
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.egg-info/PKG-INFO +1 -1
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.py +567 -2
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/setup.py +1 -1
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/README.md +0 -0
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.egg-info/SOURCES.txt +0 -0
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.egg-info/dependency_links.txt +0 -0
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.egg-info/entry_points.txt +0 -0
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/bhp_pro.egg-info/top_level.txt +0 -0
- {bhp_pro-1.2.9 → bhp_pro-1.3.1}/setup.cfg +0 -0
|
@@ -16872,6 +16872,569 @@ def menu3():
|
|
|
16872
16872
|
|
|
16873
16873
|
mainsee()
|
|
16874
16874
|
|
|
16875
|
+
#===SUBDOmain TAKEOVER===#
|
|
16876
|
+
def access_control():
|
|
16877
|
+
|
|
16878
|
+
def xhttp_payload_validator():
|
|
16879
|
+
os.system('clear' if os.name == 'posix' else 'cls')
|
|
16880
|
+
print("""
|
|
16881
|
+
╔══════════════════════════════════════════════════════════╗
|
|
16882
|
+
║ XHTTP TUNNEL PAYLOAD TESTER ║
|
|
16883
|
+
║ Generate HTTP Injector Configs from Live Tests ║
|
|
16884
|
+
╚══════════════════════════════════════════════════════════╝
|
|
16885
|
+
""")
|
|
16886
|
+
|
|
16887
|
+
# XHTTP payload templates
|
|
16888
|
+
XHTTP_PAYLOADS = {
|
|
16889
|
+
"1": {
|
|
16890
|
+
"name": "Basic HTTP Request",
|
|
16891
|
+
"payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\n\r\n",
|
|
16892
|
+
"type": "XHTTP"
|
|
16893
|
+
},
|
|
16894
|
+
"2": {
|
|
16895
|
+
"name": "CONNECT Tunnel",
|
|
16896
|
+
"payload": "CONNECT [HOST]:443 HTTP/1.1\r\nHost: [HOST]:443\r\nUser-Agent: [UA]\r\n\r\n",
|
|
16897
|
+
"type": "XHTTP"
|
|
16898
|
+
},
|
|
16899
|
+
"3": {
|
|
16900
|
+
"name": "WebSocket Upgrade",
|
|
16901
|
+
"payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: [KEY]\r\nSec-WebSocket-Version: 13\r\n\r\n",
|
|
16902
|
+
"type": "WS"
|
|
16903
|
+
},
|
|
16904
|
+
"4": {
|
|
16905
|
+
"name": "X-Online-Host Injection",
|
|
16906
|
+
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nX-Online-Host: [HOST]\r\nUser-Agent: [UA]\r\n\r\n",
|
|
16907
|
+
"type": "XHTTP"
|
|
16908
|
+
},
|
|
16909
|
+
"5": {
|
|
16910
|
+
"name": "Double Host Header",
|
|
16911
|
+
"payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\n\r\n",
|
|
16912
|
+
"type": "XHTTP"
|
|
16913
|
+
},
|
|
16914
|
+
"6": {
|
|
16915
|
+
"name": "POST Request Smuggling",
|
|
16916
|
+
"payload": "POST / HTTP/1.1\r\nHost: [HOST]\r\nContent-Length: 28\r\n\r\nGET / HTTP/1.1\r\nHost: [HOST]\r\n\r\n",
|
|
16917
|
+
"type": "XHTTP"
|
|
16918
|
+
},
|
|
16919
|
+
"7": {
|
|
16920
|
+
"name": "Cloudflare Trace + Smuggle",
|
|
16921
|
+
"payload": "GET /cdn-cgi/trace HTTP/1.1\r\nHost: [HOST]\r\n\r\nGET / HTTP/1.1\r\nHost: [HOST]\r\n\r\n",
|
|
16922
|
+
"type": "XHTTP"
|
|
16923
|
+
}
|
|
16924
|
+
}
|
|
16925
|
+
|
|
16926
|
+
class Config:
|
|
16927
|
+
def __init__(self):
|
|
16928
|
+
self.payloads = []
|
|
16929
|
+
self.targets = []
|
|
16930
|
+
self.proxies = []
|
|
16931
|
+
self.output_file = "working_configs.txt"
|
|
16932
|
+
self.timeout = 10
|
|
16933
|
+
self.threads = 100
|
|
16934
|
+
|
|
16935
|
+
class PayloadGenerator:
|
|
16936
|
+
@staticmethod
|
|
16937
|
+
def generate_websocket_key():
|
|
16938
|
+
import base64
|
|
16939
|
+
import os
|
|
16940
|
+
return base64.b64encode(os.urandom(16)).decode()
|
|
16941
|
+
|
|
16942
|
+
@staticmethod
|
|
16943
|
+
def prepare_payload(payload_template, target_domain):
|
|
16944
|
+
"""Replace [HOST] placeholder with actual target domain"""
|
|
16945
|
+
replacements = {
|
|
16946
|
+
'[HOST]': target_domain, # THIS IS CRITICAL - use the actual target
|
|
16947
|
+
'[UA]': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
16948
|
+
'[KEY]': PayloadGenerator.generate_websocket_key()
|
|
16949
|
+
}
|
|
16950
|
+
|
|
16951
|
+
payload = payload_template
|
|
16952
|
+
for placeholder, value in replacements.items():
|
|
16953
|
+
payload = payload.replace(placeholder, value)
|
|
16954
|
+
|
|
16955
|
+
return payload
|
|
16956
|
+
|
|
16957
|
+
@staticmethod
|
|
16958
|
+
def format_for_http_injector(result):
|
|
16959
|
+
"""Format working config as HTTP Injector .ehi entry"""
|
|
16960
|
+
# Original payload template (with [HOST] placeholder)
|
|
16961
|
+
original_payload = result['payload_template']
|
|
16962
|
+
|
|
16963
|
+
# Convert payload to HTTP Injector format ([crlf] instead of \r\n)
|
|
16964
|
+
escaped_payload = original_payload.replace('\r\n', '[crlf]')
|
|
16965
|
+
|
|
16966
|
+
config = f"""# ====================================================
|
|
16967
|
+
# CONFIG #{result['config_id']}
|
|
16968
|
+
# ====================================================
|
|
16969
|
+
[CONFIG]
|
|
16970
|
+
Name={result['payload_name']} | {result['status_code']} | {result['proxy_host']}:{result['proxy_port']}
|
|
16971
|
+
Server={result['proxy_host']}
|
|
16972
|
+
Port={result['proxy_port']}
|
|
16973
|
+
Protocol=XHTTP
|
|
16974
|
+
SNI={result['target']}
|
|
16975
|
+
ProxyType=HTTP
|
|
16976
|
+
|
|
16977
|
+
[PAYLOAD]
|
|
16978
|
+
{escaped_payload}
|
|
16979
|
+
|
|
16980
|
+
[HEADERS]
|
|
16981
|
+
User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
|
|
16982
|
+
Accept=*/*
|
|
16983
|
+
Accept-Language=en-US,en;q=0.9
|
|
16984
|
+
Accept-Encoding=gzip, deflate
|
|
16985
|
+
Connection=keep-alive
|
|
16986
|
+
|
|
16987
|
+
[SETTINGS]
|
|
16988
|
+
ForwardHost=true
|
|
16989
|
+
UseSNI=true
|
|
16990
|
+
|
|
16991
|
+
[TEST_INFO]
|
|
16992
|
+
Date={time.strftime("%Y-%m-%d %H:%M:%S")}
|
|
16993
|
+
Target={result['target']}
|
|
16994
|
+
Status=HTTP {result['status_code']}
|
|
16995
|
+
Response_Time={result['response_time']:.2f}s
|
|
16996
|
+
Server={result['server']}
|
|
16997
|
+
Bypass_Indicators={','.join(result['bypass_indicators'])}
|
|
16998
|
+
Payload_Sent={result['sent_payload'][:1000].replace(chr(10), ' ').replace(chr(103), '')}...
|
|
16999
|
+
|
|
17000
|
+
# ====================================================
|
|
17001
|
+
|
|
17002
|
+
"""
|
|
17003
|
+
return config
|
|
17004
|
+
|
|
17005
|
+
@staticmethod
|
|
17006
|
+
def save_all_results(results, filename):
|
|
17007
|
+
"""Save all working configs in one file"""
|
|
17008
|
+
if not results:
|
|
17009
|
+
return 0
|
|
17010
|
+
|
|
17011
|
+
with open(filename, 'w', encoding='utf-8') as f:
|
|
17012
|
+
# Header
|
|
17013
|
+
f.write(f"""# HTTP Injector Configurations
|
|
17014
|
+
# Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}
|
|
17015
|
+
# Total Working Configs: {len(results)}
|
|
17016
|
+
#
|
|
17017
|
+
# HOW TO USE:
|
|
17018
|
+
# 1. Copy each [CONFIG] section below
|
|
17019
|
+
# 2. Create new config in HTTP Injector
|
|
17020
|
+
# 3. Paste the settings
|
|
17021
|
+
# 4. Use with the specified proxy: {results[0]['proxy_host']}:{results[0]['proxy_port']}
|
|
17022
|
+
#
|
|
17023
|
+
# ====================================================
|
|
17024
|
+
|
|
17025
|
+
""")
|
|
17026
|
+
|
|
17027
|
+
# Summary section
|
|
17028
|
+
f.write("[SUMMARY]\n")
|
|
17029
|
+
f.write(f"Total_Configs={len(results)}\n")
|
|
17030
|
+
f.write(f"Tested_Targets={len(set(r['target'] for r in results))}\n")
|
|
17031
|
+
working_proxies = len(set(f"{r['proxy_host']}:{r['proxy_port']}" for r in results))
|
|
17032
|
+
f.write(f"Working_Proxies={working_proxies}\n")
|
|
17033
|
+
f.write(f"Success_Rate={(len(results) / (len(results) + len([r for r in results if not r.get('success', True)]))) * 1000:.1f}%\n\n")
|
|
17034
|
+
|
|
17035
|
+
# Group by status code
|
|
17036
|
+
status_stats = {}
|
|
17037
|
+
for result in results:
|
|
17038
|
+
status = result['status_code']
|
|
17039
|
+
status_stats[status] = status_stats.get(status, 0) + 1
|
|
17040
|
+
|
|
17041
|
+
f.write("[STATUS_CODES]\n")
|
|
17042
|
+
for status, count in sorted(status_stats.items()):
|
|
17043
|
+
f.write(f"HTTP_{status}={count}\n")
|
|
17044
|
+
f.write("\n")
|
|
17045
|
+
|
|
17046
|
+
# Group by payload
|
|
17047
|
+
payload_stats = {}
|
|
17048
|
+
for result in results:
|
|
17049
|
+
payload = result['payload_name']
|
|
17050
|
+
if payload not in payload_stats:
|
|
17051
|
+
payload_stats[payload] = {
|
|
17052
|
+
'count': 0,
|
|
17053
|
+
'bypass': 0,
|
|
17054
|
+
'targets': set()
|
|
17055
|
+
}
|
|
17056
|
+
payload_stats[payload]['count'] += 1
|
|
17057
|
+
if result['bypass_indicators']:
|
|
17058
|
+
payload_stats[payload]['bypass'] += 1
|
|
17059
|
+
payload_stats[payload]['targets'].add(result['target'])
|
|
17060
|
+
|
|
17061
|
+
f.write("[PAYLOAD_STATS]\n")
|
|
17062
|
+
for payload, stats in sorted(payload_stats.items(), key=lambda x: x[1]['count'], reverse=True):
|
|
17063
|
+
f.write(f"{payload.replace(' ', '_')}={stats['count']}|{stats['bypass']}|{len(stats['targets'])}\n")
|
|
17064
|
+
f.write("\n")
|
|
17065
|
+
|
|
17066
|
+
# Now write each config
|
|
17067
|
+
f.write("# ====================================================\n")
|
|
17068
|
+
f.write("# WORKING CONFIGURATIONS\n")
|
|
17069
|
+
f.write("# ====================================================\n\n")
|
|
17070
|
+
|
|
17071
|
+
for i, result in enumerate(results, 1):
|
|
17072
|
+
result['config_id'] = i
|
|
17073
|
+
config_text = PayloadGenerator.format_for_http_injector(result)
|
|
17074
|
+
f.write(config_text)
|
|
17075
|
+
|
|
17076
|
+
return len(results)
|
|
17077
|
+
|
|
17078
|
+
class ProxyManager:
|
|
17079
|
+
@staticmethod
|
|
17080
|
+
def parse_proxy_input(proxy_input, ports):
|
|
17081
|
+
proxies = []
|
|
17082
|
+
|
|
17083
|
+
# Already has port
|
|
17084
|
+
if ':' in proxy_input:
|
|
17085
|
+
parts = proxy_input.split(':', 1)
|
|
17086
|
+
ip_part = parts[0]
|
|
17087
|
+
port = int(parts[1])
|
|
17088
|
+
|
|
17089
|
+
if '/' in ip_part: # CIDR with port
|
|
17090
|
+
try:
|
|
17091
|
+
network = ipaddress.ip_network(ip_part, strict=False)
|
|
17092
|
+
for ip in network.hosts():
|
|
17093
|
+
proxies.append((str(ip), port))
|
|
17094
|
+
except:
|
|
17095
|
+
pass
|
|
17096
|
+
else: # Single IP with port
|
|
17097
|
+
proxies.append((ip_part, port))
|
|
17098
|
+
return proxies
|
|
17099
|
+
|
|
17100
|
+
# CIDR without port
|
|
17101
|
+
if '/' in proxy_input:
|
|
17102
|
+
try:
|
|
17103
|
+
network = ipaddress.ip_network(proxy_input, strict=False)
|
|
17104
|
+
for ip in network.hosts():
|
|
17105
|
+
for port in ports:
|
|
17106
|
+
proxies.append((str(ip), port))
|
|
17107
|
+
except:
|
|
17108
|
+
pass
|
|
17109
|
+
return proxies
|
|
17110
|
+
|
|
17111
|
+
# IP range
|
|
17112
|
+
if '-' in proxy_input:
|
|
17113
|
+
parts = proxy_input.split('-')
|
|
17114
|
+
if len(parts) == 2:
|
|
17115
|
+
base_ip = parts[0].rsplit('.', 1)[0]
|
|
17116
|
+
start = int(parts[0].rsplit('.', 1)[1])
|
|
17117
|
+
end = int(parts[1])
|
|
17118
|
+
|
|
17119
|
+
for i in range(start, end + 1):
|
|
17120
|
+
ip = f"{base_ip}.{i}"
|
|
17121
|
+
for port in ports:
|
|
17122
|
+
proxies.append((ip, port))
|
|
17123
|
+
return proxies
|
|
17124
|
+
|
|
17125
|
+
# Single IP without port
|
|
17126
|
+
for port in ports:
|
|
17127
|
+
proxies.append((proxy_input.strip(), port))
|
|
17128
|
+
|
|
17129
|
+
return proxies
|
|
17130
|
+
|
|
17131
|
+
class NetworkTester:
|
|
17132
|
+
def __init__(self, config):
|
|
17133
|
+
self.config = config
|
|
17134
|
+
self.working_configs = []
|
|
17135
|
+
self.lock = threading.Lock()
|
|
17136
|
+
self.queue = Queue()
|
|
17137
|
+
self.tested = 0
|
|
17138
|
+
self.successful = 0
|
|
17139
|
+
|
|
17140
|
+
def test_connection(self, payload_info, target_domain, proxy_host, proxy_port):
|
|
17141
|
+
"""Test payload with target domain through proxy"""
|
|
17142
|
+
try:
|
|
17143
|
+
# CRITICAL FIX: Use target domain in payload, not proxy IP
|
|
17144
|
+
sent_payload = PayloadGenerator.prepare_payload(payload_info['payload'], target_domain)
|
|
17145
|
+
|
|
17146
|
+
# Connect to PROXY
|
|
17147
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
17148
|
+
sock.settimeout(self.config.timeout)
|
|
17149
|
+
sock.connect((proxy_host, proxy_port))
|
|
17150
|
+
|
|
17151
|
+
# Send payload (with target domain in Host header)
|
|
17152
|
+
start_time = time.time()
|
|
17153
|
+
sock.send(sent_payload.encode())
|
|
17154
|
+
|
|
17155
|
+
# Receive response FROM PROXY
|
|
17156
|
+
response = b""
|
|
17157
|
+
while time.time() - start_time < 5:
|
|
17158
|
+
try:
|
|
17159
|
+
sock.settimeout(1)
|
|
17160
|
+
chunk = sock.recv(4096)
|
|
17161
|
+
if not chunk:
|
|
17162
|
+
break
|
|
17163
|
+
response += chunk
|
|
17164
|
+
except socket.timeout:
|
|
17165
|
+
break
|
|
17166
|
+
|
|
17167
|
+
sock.close()
|
|
17168
|
+
response_time = time.time() - start_time
|
|
17169
|
+
|
|
17170
|
+
# Parse response
|
|
17171
|
+
response_text = response.decode('utf-8', errors='ignore')
|
|
17172
|
+
status_code = None
|
|
17173
|
+
server_info = "Unknown"
|
|
17174
|
+
|
|
17175
|
+
# Get status code
|
|
17176
|
+
status_match = re.search(r'HTTP/\d\.\d\s+(\d{3})', response_text)
|
|
17177
|
+
if status_match:
|
|
17178
|
+
status_code = int(status_match.group(1))
|
|
17179
|
+
else:
|
|
17180
|
+
return {'success': False, 'error': 'No HTTP response'}
|
|
17181
|
+
|
|
17182
|
+
# Get server header
|
|
17183
|
+
server_match = re.search(r'Server:\s*([^\r\n]+)', response_text, re.IGNORECASE)
|
|
17184
|
+
if server_match:
|
|
17185
|
+
server_info = server_match.group(1)
|
|
17186
|
+
|
|
17187
|
+
# Check bypass indicators
|
|
17188
|
+
bypass_indicators = self.check_bypass_indicators(response_text)
|
|
17189
|
+
|
|
17190
|
+
return {
|
|
17191
|
+
'payload_name': payload_info['name'],
|
|
17192
|
+
'payload_template': payload_info['payload'], # Original template
|
|
17193
|
+
'sent_payload': sent_payload, # Actual payload sent
|
|
17194
|
+
'target': target_domain, # The domain we're trying to reach
|
|
17195
|
+
'proxy_host': proxy_host,
|
|
17196
|
+
'proxy_port': proxy_port,
|
|
17197
|
+
'status_code': status_code,
|
|
17198
|
+
'response_time': response_time,
|
|
17199
|
+
'server': server_info,
|
|
17200
|
+
'bypass_indicators': bypass_indicators,
|
|
17201
|
+
'response_preview': response_text[:200],
|
|
17202
|
+
'success': True
|
|
17203
|
+
}
|
|
17204
|
+
|
|
17205
|
+
except Exception as e:
|
|
17206
|
+
return {'success': False, 'error': str(e)}
|
|
17207
|
+
|
|
17208
|
+
def check_bypass_indicators(self, response_text):
|
|
17209
|
+
indicators = []
|
|
17210
|
+
checks = [
|
|
17211
|
+
(r'CF-RAY', 'Cloudflare Proxy'),
|
|
17212
|
+
(r'X-Cache', 'Caching Proxy'),
|
|
17213
|
+
(r'Via:', 'Proxy Chain'),
|
|
17214
|
+
(r'squid/', 'Squid Proxy'),
|
|
17215
|
+
(r'varnish', 'Varnish Cache'),
|
|
17216
|
+
(r'nginx/', 'Nginx Proxy'),
|
|
17217
|
+
(r'Apache/', 'Apache Proxy'),
|
|
17218
|
+
(r'Connection established', 'CONNECT Successful'),
|
|
17219
|
+
(r'101 Switching Protocols', 'WebSocket Upgrade'),
|
|
17220
|
+
(r'HTTP/1.1 200.*HTTP/1.1', 'Request Smuggling')
|
|
17221
|
+
]
|
|
17222
|
+
|
|
17223
|
+
for pattern, meaning in checks:
|
|
17224
|
+
if re.search(pattern, response_text, re.IGNORECASE | re.DOTALL):
|
|
17225
|
+
indicators.append(meaning)
|
|
17226
|
+
|
|
17227
|
+
return indicators
|
|
17228
|
+
|
|
17229
|
+
def worker(self):
|
|
17230
|
+
while not self.queue.empty():
|
|
17231
|
+
try:
|
|
17232
|
+
task = self.queue.get()
|
|
17233
|
+
payload_info, target, proxy_host, proxy_port = task
|
|
17234
|
+
|
|
17235
|
+
result = self.test_connection(payload_info, target, proxy_host, proxy_port)
|
|
17236
|
+
|
|
17237
|
+
with self.lock:
|
|
17238
|
+
self.tested += 1
|
|
17239
|
+
|
|
17240
|
+
if result['success']:
|
|
17241
|
+
self.successful += 1
|
|
17242
|
+
self.working_configs.append(result)
|
|
17243
|
+
|
|
17244
|
+
# Live display
|
|
17245
|
+
status = result['status_code']
|
|
17246
|
+
proxy_display = f"{proxy_host}:{proxy_port}"
|
|
17247
|
+
|
|
17248
|
+
if 200 <= status < 300:
|
|
17249
|
+
icon = "✅"
|
|
17250
|
+
elif 300 <= status < 400:
|
|
17251
|
+
icon = "↪️"
|
|
17252
|
+
elif 400 <= status < 500:
|
|
17253
|
+
icon = "⚠️"
|
|
17254
|
+
else:
|
|
17255
|
+
icon = "❌"
|
|
17256
|
+
|
|
17257
|
+
if result['bypass_indicators']:
|
|
17258
|
+
icon += "🚀"
|
|
17259
|
+
|
|
17260
|
+
print(f"{icon} {result['payload_name']:25} → {target:20} HTTP {status:3} via {proxy_display:20}")
|
|
17261
|
+
|
|
17262
|
+
self.queue.task_done()
|
|
17263
|
+
|
|
17264
|
+
except Exception:
|
|
17265
|
+
self.queue.task_done()
|
|
17266
|
+
|
|
17267
|
+
def run_tests(self):
|
|
17268
|
+
# Build task queue
|
|
17269
|
+
for payload_info in self.config.payloads:
|
|
17270
|
+
for target in self.config.targets:
|
|
17271
|
+
if self.config.proxies:
|
|
17272
|
+
for proxy_host, proxy_port in self.config.proxies:
|
|
17273
|
+
self.queue.put((payload_info, target, proxy_host, proxy_port))
|
|
17274
|
+
else:
|
|
17275
|
+
# Direct connection (no proxy)
|
|
17276
|
+
self.queue.put((payload_info, target, target, 80))
|
|
17277
|
+
|
|
17278
|
+
total_tests = self.queue.qsize()
|
|
17279
|
+
|
|
17280
|
+
print(f"\n{'='*60}")
|
|
17281
|
+
print(f"🧪 TESTING CONFIGURATION")
|
|
17282
|
+
print(f"{'='*60}")
|
|
17283
|
+
print(f"Payloads: {len(self.config.payloads)}")
|
|
17284
|
+
print(f"Targets: {len(self.config.targets)}")
|
|
17285
|
+
print(f"Proxies: {len(self.config.proxies) if self.config.proxies else 'Direct'}")
|
|
17286
|
+
print(f"Total Tests: {total_tests}")
|
|
17287
|
+
print(f"Threads: {self.config.threads}")
|
|
17288
|
+
print(f"{'='*60}")
|
|
17289
|
+
print("\n📡 TESTING IN PROGRESS...\n")
|
|
17290
|
+
|
|
17291
|
+
# Start workers
|
|
17292
|
+
threads = []
|
|
17293
|
+
for _ in range(min(self.config.threads, total_tests)):
|
|
17294
|
+
t = threading.Thread(target=self.worker)
|
|
17295
|
+
t.daemon = True
|
|
17296
|
+
t.start()
|
|
17297
|
+
threads.append(t)
|
|
17298
|
+
|
|
17299
|
+
# Wait for completion
|
|
17300
|
+
self.queue.join()
|
|
17301
|
+
|
|
17302
|
+
print(f"\n{'='*60}")
|
|
17303
|
+
print(f"✅ TESTING COMPLETE")
|
|
17304
|
+
print(f"{'='*60}")
|
|
17305
|
+
print(f"Tests Completed: {self.tested}")
|
|
17306
|
+
print(f"Successful Responses: {self.successful}")
|
|
17307
|
+
print(f"Working Configs Found: {len(self.working_configs)}")
|
|
17308
|
+
|
|
17309
|
+
return self.working_configs
|
|
17310
|
+
|
|
17311
|
+
# Main execution
|
|
17312
|
+
config = Config()
|
|
17313
|
+
|
|
17314
|
+
# Select payloads
|
|
17315
|
+
print("\n📋 AVAILABLE PAYLOAD TEMPLATES:")
|
|
17316
|
+
print("-" * 55)
|
|
17317
|
+
for key, info in XHTTP_PAYLOADS.items():
|
|
17318
|
+
print(f"{key}. {info['name']} ({info['type']})")
|
|
17319
|
+
|
|
17320
|
+
selection = input("\nSelect payloads (numbers comma-separated, or 'all'): ").strip()
|
|
17321
|
+
|
|
17322
|
+
if selection.lower() == 'all':
|
|
17323
|
+
selected_keys = list(XHTTP_PAYLOADS.keys())
|
|
17324
|
+
else:
|
|
17325
|
+
selected_keys = [s.strip() for s in selection.split(',') if s.strip() in XHTTP_PAYLOADS]
|
|
17326
|
+
|
|
17327
|
+
if not selected_keys:
|
|
17328
|
+
print("❌ No payloads selected!")
|
|
17329
|
+
return
|
|
17330
|
+
|
|
17331
|
+
for key in selected_keys:
|
|
17332
|
+
config.payloads.append(XHTTP_PAYLOADS[key])
|
|
17333
|
+
|
|
17334
|
+
# Get targets - THESE ARE THE DOMAINS WE WANT TO REACH
|
|
17335
|
+
targets_input = input("\n🎯 Enter target domain(s) to test against (comma-separated or file): ").strip()
|
|
17336
|
+
|
|
17337
|
+
if os.path.isfile(targets_input):
|
|
17338
|
+
with open(targets_input, 'r') as f:
|
|
17339
|
+
config.targets = [line.strip() for line in f if line.strip()]
|
|
17340
|
+
else:
|
|
17341
|
+
config.targets = [t.strip() for t in targets_input.split(',') if t.strip()]
|
|
17342
|
+
|
|
17343
|
+
if not config.targets:
|
|
17344
|
+
print("❌ No target domains specified!")
|
|
17345
|
+
return
|
|
17346
|
+
|
|
17347
|
+
# Get proxies - THESE ARE THE PROXIES WE TEST THROUGH
|
|
17348
|
+
print("\n🔄 PROXY SETTINGS")
|
|
17349
|
+
print("1. Use proxies (for tunneling)")
|
|
17350
|
+
print("2. Direct connection (no proxy)")
|
|
17351
|
+
|
|
17352
|
+
proxy_choice = input("\nSelect option (1-2): ").strip()
|
|
17353
|
+
|
|
17354
|
+
if proxy_choice == '1':
|
|
17355
|
+
proxy_input = input("Enter proxy (IP, IP:PORT, CIDR, or IP range): ").strip()
|
|
17356
|
+
|
|
17357
|
+
ports_input = input("Ports to test (comma-separated, default=80,443): ").strip()
|
|
17358
|
+
if ports_input:
|
|
17359
|
+
ports = [int(p.strip()) for p in ports_input.split(',') if p.strip().isdigit()]
|
|
17360
|
+
else:
|
|
17361
|
+
ports = [80, 443] # Default to HTTP and HTTPS ports
|
|
17362
|
+
|
|
17363
|
+
config.proxies = ProxyManager.parse_proxy_input(proxy_input, ports)
|
|
17364
|
+
|
|
17365
|
+
if not config.proxies:
|
|
17366
|
+
print("❌ Invalid proxy input!")
|
|
17367
|
+
return
|
|
17368
|
+
|
|
17369
|
+
print(f"✅ Loaded {len(config.proxies)} proxy endpoints")
|
|
17370
|
+
|
|
17371
|
+
# Output file
|
|
17372
|
+
output_file = input("\n💾 Output file (default=working_configs.txt): ").strip()
|
|
17373
|
+
if output_file:
|
|
17374
|
+
if not output_file.endswith('.txt'):
|
|
17375
|
+
output_file += '.txt'
|
|
17376
|
+
config.output_file = output_file
|
|
17377
|
+
|
|
17378
|
+
# Confirm
|
|
17379
|
+
print(f"\n{'='*60}")
|
|
17380
|
+
print("READY TO TEST")
|
|
17381
|
+
print(f"{'='*60}")
|
|
17382
|
+
print(f"Payloads: {len(config.payloads)}")
|
|
17383
|
+
print(f"Target Domains: {', '.join(config.targets[:3])}{'...' if len(config.targets) > 3 else ''}")
|
|
17384
|
+
print(f"Proxies: {len(config.proxies) if config.proxies else 'Direct'}")
|
|
17385
|
+
print(f"Output: {config.output_file}")
|
|
17386
|
+
print(f"{'='*60}")
|
|
17387
|
+
|
|
17388
|
+
confirm = input("\nStart testing? (y/n): ").strip().lower()
|
|
17389
|
+
if confirm != 'y':
|
|
17390
|
+
print("❌ Cancelled")
|
|
17391
|
+
return
|
|
17392
|
+
|
|
17393
|
+
# Run tests
|
|
17394
|
+
start_time = time.time()
|
|
17395
|
+
tester = NetworkTester(config)
|
|
17396
|
+
working_configs = tester.run_tests()
|
|
17397
|
+
|
|
17398
|
+
# Save results - SINGLE FILE ONLY
|
|
17399
|
+
if working_configs:
|
|
17400
|
+
saved_count = PayloadGenerator.save_all_results(working_configs, config.output_file)
|
|
17401
|
+
|
|
17402
|
+
elapsed = time.time() - start_time
|
|
17403
|
+
|
|
17404
|
+
print(f"\n{'='*60}")
|
|
17405
|
+
print("📦 RESULTS SAVED")
|
|
17406
|
+
print(f"{'='*60}")
|
|
17407
|
+
print(f"✅ Generated {saved_count} HTTP Injector configs")
|
|
17408
|
+
print(f"📁 Single output file: {config.output_file}")
|
|
17409
|
+
print(f"⏱️ Total time: {elapsed:.1f} seconds")
|
|
17410
|
+
print(f"{'='*60}")
|
|
17411
|
+
|
|
17412
|
+
# Show what's in the file
|
|
17413
|
+
print("\n📋 FILE CONTENTS:")
|
|
17414
|
+
print(f"1. [SUMMARY] - Test statistics")
|
|
17415
|
+
print(f"2. [STATUS_CODES] - HTTP status breakdown")
|
|
17416
|
+
print(f"3. [PAYLOAD_STATS] - Success rate per payload")
|
|
17417
|
+
print(f"4. Multiple [CONFIG] sections - Ready for HTTP Injector")
|
|
17418
|
+
|
|
17419
|
+
# Show sample
|
|
17420
|
+
if working_configs:
|
|
17421
|
+
sample = working_configs[0]
|
|
17422
|
+
print(f"\n🎯 SAMPLE CONFIG #{1}:")
|
|
17423
|
+
print(f" Payload: {sample['payload_name']}")
|
|
17424
|
+
print(f" Target: {sample['target']}")
|
|
17425
|
+
print(f" Proxy: {sample['proxy_host']}:{sample['proxy_port']}")
|
|
17426
|
+
print(f" Status: HTTP {sample['status_code']}")
|
|
17427
|
+
print(f" Payload sent: {sample['sent_payload'][:800]}...")
|
|
17428
|
+
|
|
17429
|
+
print(f"\n💡 Import {config.output_file} into HTTP Injector")
|
|
17430
|
+
print(f" Each [CONFIG] section is a separate tunnel config")
|
|
17431
|
+
else:
|
|
17432
|
+
print("\n❌ No working configurations found!")
|
|
17433
|
+
|
|
17434
|
+
|
|
17435
|
+
xhttp_payload_validator()
|
|
17436
|
+
|
|
17437
|
+
|
|
16875
17438
|
def x_menu():
|
|
16876
17439
|
|
|
16877
17440
|
def return_to_menu():
|
|
@@ -16901,6 +17464,7 @@ def menu3():
|
|
|
16901
17464
|
"3. INFO",
|
|
16902
17465
|
"4. Wif Abomination",
|
|
16903
17466
|
"5. KPROXY_SCANNER" ,
|
|
17467
|
+
"6. ACCESS CONTROL" ,
|
|
16904
17468
|
|
|
16905
17469
|
]
|
|
16906
17470
|
|
|
@@ -16925,7 +17489,8 @@ def menu3():
|
|
|
16925
17489
|
"2": ipcam,
|
|
16926
17490
|
"3": info,
|
|
16927
17491
|
"4": wifi_deauth,
|
|
16928
|
-
"5": prox
|
|
17492
|
+
"5": prox,
|
|
17493
|
+
"6": access_control,
|
|
16929
17494
|
|
|
16930
17495
|
|
|
16931
17496
|
}
|
|
@@ -16968,7 +17533,7 @@ def banner():
|
|
|
16968
17533
|
MAGENTA + "██╔═══╝ ██╔══██╗██║ ██║" + LIME + "user should understand that useage of this script may be" + ENDC,
|
|
16969
17534
|
MAGENTA + "██║ ██║ ██║╚██████╔╝" + LIME + "concidered an attack on a data network, and may violate terms" + ENDC,
|
|
16970
17535
|
MAGENTA + "╚═╝ ╚═╝ ╚═╝ ╚═════╝" + LIME + "of service, use on your own network or get permission first" + ENDC,
|
|
16971
|
-
PURPLE + "script_version@ 1.
|
|
17536
|
+
PURPLE + "script_version@ 1.3.1 ®" + ENDC,
|
|
16972
17537
|
ORANGE + "All rights reserved 2022-2026 ♛: ®" + ENDC,
|
|
16973
17538
|
MAGENTA + "In Collaboration whit Ayan Rajpoot ® " + ENDC,
|
|
16974
17539
|
BLUE + "Support: https://t.me/BugScanX 💬" + ENDC,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|