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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bhp_pro
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: Web Enumeration Tool
5
5
  Author: ssskingsss12
6
6
  Author-email: smalls3000i@gmail.com
@@ -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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
bhp_pro.py CHANGED
@@ -16875,89 +16875,564 @@ def menu3():
16875
16875
  #===SUBDOmain TAKEOVER===#
16876
16876
  def access_control():
16877
16877
 
16878
- generate_ascii_banner("ACCESS", "CONTROL")
16879
- THREAD_COUNT = 100
16880
-
16881
- LOCK = threading.Lock()
16882
- user_input = input("Enter a domain or .txt file: ").strip()
16883
- OUTPUT_FILE = input("Enter output file name (default is x_requested_with_results.txt): ").strip() or "x_requested_with_results.txt"
16884
- def check_domain(domain, progress):
16885
- preflight_headers = {
16886
- 'Origin': 'https://yahoo.com/',
16887
- 'Access-Control-Request-Method': 'GET',
16888
- 'Access-Control-Request-Headers': 'X-Requested-With, X-Online-Host, X-Forwarded-For',
16889
- 'User-Agent': 'Mozilla/5.0'
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
- for protocol in ['http://', 'https://']:
16893
- url = protocol + domain
16894
- try:
16895
- response = requests.options(url, headers=preflight_headers, timeout=5)
16896
- status = response.status_code
16897
- allowed_headers = response.headers.get('Access-Control-Allow-Headers', '').lower()
16898
-
16899
- allowed = []
16900
- if 'x-requested-with' in allowed_headers:
16901
- allowed.append('X-Requested-With')
16902
- if 'x-online-host' in allowed_headers:
16903
- allowed.append('X-Online-Host')
16904
- if 'x-forwarded-for' in allowed_headers:
16905
- allowed.append('X-Forwarded-For')
16906
-
16907
- if allowed:
16908
- server = response.headers.get('Server', 'Unknown')
16909
- print(f"✅ {url} - ALLOWS: {', '.join(allowed)} | Status: {status}")
16910
- with LOCK:
16911
- with open(OUTPUT_FILE, "a") as f:
16912
- f.write(f"{url} | Status: {status} | Server: {server} | Allowed Headers: {', '.join(allowed)}\n")
16913
- else:
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
- if os.path.isfile(user_input) and user_input.endswith('.txt'):
16933
- with open(user_input, 'r') as file:
16934
- domains = [line.strip() for line in file if line.strip()]
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
- domains = [user_input]
16937
-
16938
- if os.path.exists(OUTPUT_FILE):
16939
- os.remove(OUTPUT_FILE)
16940
-
16941
- domain_queue = Queue()
16942
- for domain in domains:
16943
- domain_queue.put(domain)
16944
-
16945
- progress = tqdm(total=len(domains) * 2, desc="Checking", ncols=80)
16946
-
16947
- threads = []
16948
- for _ in range(THREAD_COUNT):
16949
- t = threading.Thread(target=worker, args=(domain_queue, progress))
16950
- t.start()
16951
- threads.append(t)
16952
-
16953
- for t in threads:
16954
- t.join()
16955
-
16956
- progress.close()
16957
- print(f"\n✅ Finished checking. Results saved to {OUTPUT_FILE}")
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
- access_main()
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.0 ®" + ENDC,
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,
@@ -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,,