bhp-pro 1.3.0__py3-none-any.whl → 1.3.1__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.
- {bhp_pro-1.3.0.dist-info → bhp_pro-1.3.1.dist-info}/METADATA +1 -1
- bhp_pro-1.3.1.dist-info/RECORD +6 -0
- {bhp_pro-1.3.0.dist-info → bhp_pro-1.3.1.dist-info}/WHEEL +1 -1
- bhp_pro.py +553 -78
- bhp_pro-1.3.0.dist-info/RECORD +0 -6
- {bhp_pro-1.3.0.dist-info → bhp_pro-1.3.1.dist-info}/entry_points.txt +0 -0
- {bhp_pro-1.3.0.dist-info → bhp_pro-1.3.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
bhp_pro.py,sha256=GGMBJqGY4Iq_tvfOx8CvjlMDFwfiAmkkZ1vkCDyiLxo,772565
|
|
2
|
+
bhp_pro-1.3.1.dist-info/METADATA,sha256=CxccyEJF5lcdMjCpVWa1Dq3YCjrXtcsn3YDD10T9mYQ,600
|
|
3
|
+
bhp_pro-1.3.1.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
4
|
+
bhp_pro-1.3.1.dist-info/entry_points.txt,sha256=Yn3HpraGX3lXX4FPq3Gm-lHh3SwQA-5rtgPWNWMFXkw,41
|
|
5
|
+
bhp_pro-1.3.1.dist-info/top_level.txt,sha256=1xjbIaVM77UJz9Tsi1JjILgE0YDG7iLhY6KSMNEi9zM,8
|
|
6
|
+
bhp_pro-1.3.1.dist-info/RECORD,,
|
bhp_pro.py
CHANGED
|
@@ -16875,89 +16875,564 @@ def menu3():
|
|
|
16875
16875
|
#===SUBDOmain TAKEOVER===#
|
|
16876
16876
|
def access_control():
|
|
16877
16877
|
|
|
16878
|
-
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
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
|
+
}
|
|
16890
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
|
+
# ====================================================
|
|
16891
17001
|
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
print(f"⚠️ {url} - None of the desired X-* headers allowed.")
|
|
16915
|
-
|
|
16916
|
-
except requests.exceptions.RequestException as e:
|
|
16917
|
-
print(f"❌ {url} - Request failed: {e}")
|
|
16918
|
-
finally:
|
|
16919
|
-
with LOCK:
|
|
16920
|
-
progress.update(1)
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
def worker(domain_queue, progress):
|
|
16924
|
-
while not domain_queue.empty():
|
|
16925
|
-
domain = domain_queue.get()
|
|
16926
|
-
check_domain(domain, progress)
|
|
16927
|
-
domain_queue.task_done()
|
|
16928
|
-
|
|
16929
|
-
def access_main():
|
|
16930
|
-
|
|
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
|
+
# ====================================================
|
|
16931
17024
|
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
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())
|
|
16935
17324
|
else:
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
if
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
for
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16946
|
-
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
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!")
|
|
16958
17433
|
|
|
16959
17434
|
|
|
16960
|
-
|
|
17435
|
+
xhttp_payload_validator()
|
|
16961
17436
|
|
|
16962
17437
|
|
|
16963
17438
|
def x_menu():
|
|
@@ -17058,7 +17533,7 @@ def banner():
|
|
|
17058
17533
|
MAGENTA + "██╔═══╝ ██╔══██╗██║ ██║" + LIME + "user should understand that useage of this script may be" + ENDC,
|
|
17059
17534
|
MAGENTA + "██║ ██║ ██║╚██████╔╝" + LIME + "concidered an attack on a data network, and may violate terms" + ENDC,
|
|
17060
17535
|
MAGENTA + "╚═╝ ╚═╝ ╚═╝ ╚═════╝" + LIME + "of service, use on your own network or get permission first" + ENDC,
|
|
17061
|
-
PURPLE + "script_version@ 1.3.
|
|
17536
|
+
PURPLE + "script_version@ 1.3.1 ®" + ENDC,
|
|
17062
17537
|
ORANGE + "All rights reserved 2022-2026 ♛: ®" + ENDC,
|
|
17063
17538
|
MAGENTA + "In Collaboration whit Ayan Rajpoot ® " + ENDC,
|
|
17064
17539
|
BLUE + "Support: https://t.me/BugScanX 💬" + ENDC,
|
bhp_pro-1.3.0.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
bhp_pro.py,sha256=WJ2J94cH1-qKf3AynRr8Q4t0GhzNxs2VunaQip0T7zA,748620
|
|
2
|
-
bhp_pro-1.3.0.dist-info/METADATA,sha256=t7JildGhotdLKQG8WAcZWV-rFl9R6FhukOP2UhCNEMs,600
|
|
3
|
-
bhp_pro-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
-
bhp_pro-1.3.0.dist-info/entry_points.txt,sha256=Yn3HpraGX3lXX4FPq3Gm-lHh3SwQA-5rtgPWNWMFXkw,41
|
|
5
|
-
bhp_pro-1.3.0.dist-info/top_level.txt,sha256=1xjbIaVM77UJz9Tsi1JjILgE0YDG7iLhY6KSMNEi9zM,8
|
|
6
|
-
bhp_pro-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|