bhp-pro 1.3.1__py3-none-any.whl → 1.3.2__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.1
3
+ Version: 1.3.2
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=i5J-aBNaC14n76DYyym6cs2BBkHF7kT_cLImMl1zb38,777565
2
+ bhp_pro-1.3.2.dist-info/METADATA,sha256=p5i7atVTfveV5iPPzgiUMtczuAsgD6xN-sDAzPCGT_E,600
3
+ bhp_pro-1.3.2.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
4
+ bhp_pro-1.3.2.dist-info/entry_points.txt,sha256=Yn3HpraGX3lXX4FPq3Gm-lHh3SwQA-5rtgPWNWMFXkw,41
5
+ bhp_pro-1.3.2.dist-info/top_level.txt,sha256=1xjbIaVM77UJz9Tsi1JjILgE0YDG7iLhY6KSMNEi9zM,8
6
+ bhp_pro-1.3.2.dist-info/RECORD,,
bhp_pro.py CHANGED
@@ -16875,95 +16875,133 @@ def menu3():
16875
16875
  #===SUBDOmain TAKEOVER===#
16876
16876
  def access_control():
16877
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
- }
16878
+ import os
16879
+ import re
16880
+ import socket
16881
+ import time
16882
+ import threading
16883
+ import ipaddress
16884
+ from queue import Queue
16885
+ from tqdm import tqdm
16886
+
16887
+ FREE_SERVERS = {
16888
+ 'google': 'www.google.com',
16889
+ 'cloudflare': '1.1.1.1',
16890
+ 'open_dns': '208.67.222.222',
16891
+ 'quad9': '9.9.9.9',
16892
+ 'example': 'example.com',
16893
+ 'test_server': 'test.server.com'
16894
+ }
16895
+
16896
+ XHTTP_PAYLOADS = {
16897
+ "1": {
16898
+ "name": "Standard HTTP/1.1",
16899
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n",
16900
+ "type": "XHTTP"
16901
+ },
16902
+ "2": {
16903
+ "name": "HTTP/1.1 Keep-Alive",
16904
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nConnection: Keep-Alive\r\nKeep-Alive: timeout=30\r\n\r\n",
16905
+ "type": "XHTTP"
16906
+ },
16907
+ "3": {
16908
+ "name": "Chrome User-Agent",
16909
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n",
16910
+ "type": "XHTTP"
16911
+ },
16912
+ "4": {
16913
+ "name": "CONNECT Method",
16914
+ "payload": "CONNECT [HOST]:443 HTTP/1.1\r\nHost: [HOST]:443\r\nUser-Agent: [UA]\r\nProxy-Connection: Keep-Alive\r\n\r\n",
16915
+ "type": "XHTTP"
16916
+ },
16917
+ "5": {
16918
+ "name": "X-Online-Host Injection",
16919
+ "payload": f"GET / HTTP/1.1\r\nHost: [HOST]\r\nX-Online-Host: {FREE_SERVERS['google']}\r\nUser-Agent: [UA]\r\n\r\n",
16920
+ "type": "XHTTP"
16921
+ },
16922
+ "6": {
16923
+ "name": "X-Forwarded-Host Injection",
16924
+ "payload": f"GET / HTTP/1.1\r\nHost: [HOST]\r\nX-Forwarded-Host: {FREE_SERVERS['example']}\r\nUser-Agent: [UA]\r\n\r\n",
16925
+ "type": "XHTTP"
16926
+ },
16927
+ "7": {
16928
+ "name": "Simple POST Request",
16929
+ "payload": "POST / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 0\r\n\r\n",
16930
+ "type": "XHTTP"
16931
+ },
16932
+ "8": {
16933
+ "name": "HTTP/2 Preface",
16934
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nUpgrade: h2c\r\nHTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA\r\nConnection: Upgrade, HTTP2-Settings\r\n\r\n",
16935
+ "type": "XHTTP"
16936
+ },
16937
+ "9": {
16938
+ "name": "Mobile Safari UA",
16939
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.9\r\n\r\n",
16940
+ "type": "XHTTP"
16941
+ },
16942
+ "10": {
16943
+ "name": "No Cache Headers",
16944
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nCache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: 0\r\n\r\n",
16945
+ "type": "XHTTP"
16946
+ },
16947
+ "11": {
16948
+ "name": "Double Host Header",
16949
+ "payload": f"GET / HTTP/1.1\r\nHost: [HOST]\r\nHost: {FREE_SERVERS['example']}\r\nUser-Agent: [UA]\r\n\r\n",
16950
+ "type": "XHTTP"
16951
+ },
16952
+ "12": {
16953
+ "name": "WebSocket Upgrade",
16954
+ "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\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n",
16955
+ "type": "WS"
16956
+ },
16957
+ "13": {
16958
+ "name": "Google Bot UA",
16959
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Chrome/120.0.0.0 Safari/537.36\r\n\r\n",
16960
+ "type": "XHTTP"
16961
+ },
16962
+ "14": {
16963
+ "name": "Forwarded Headers",
16964
+ "payload": f"GET / HTTP/1.1\r\nHost: [HOST]\r\nUser-Agent: [UA]\r\nForwarded: for=192.168.1.1;proto=http;host={FREE_SERVERS['test_server']}\r\nX-Forwarded-For: 192.168.1.1\r\nX-Real-IP: 192.168.1.1\r\n\r\n",
16965
+ "type": "XHTTP"
16966
+ },
16967
+ "15": {
16968
+ "name": "Pipelined Request",
16969
+ "payload": "GET / HTTP/1.1\r\nHost: [HOST]\r\n\r\nGET /favicon.ico HTTP/1.1\r\nHost: [HOST]\r\n\r\n",
16970
+ "type": "XHTTP"
16924
16971
  }
16972
+ }
16973
+
16974
+ class Config:
16975
+ def __init__(self):
16976
+ self.payloads = []
16977
+ self.targets = []
16978
+ self.proxies = []
16979
+ self.output_file = "working_configs.txt"
16980
+ self.timeout = 3
16981
+ self.threads = 50
16982
+
16983
+ class PayloadManager:
16984
+ @staticmethod
16985
+ def generate_websocket_key():
16986
+ import base64, os
16987
+ return base64.b64encode(os.urandom(16)).decode()
16925
16988
 
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"""# ====================================================
16989
+ @staticmethod
16990
+ def prepare_payload(payload_template, target_domain):
16991
+ replacements = {
16992
+ '[HOST]': target_domain,
16993
+ '[UA]': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
16994
+ '[KEY]': PayloadManager.generate_websocket_key()
16995
+ }
16996
+ payload = payload_template
16997
+ for placeholder, value in replacements.items():
16998
+ payload = payload.replace(placeholder, value)
16999
+ return payload
17000
+
17001
+ @staticmethod
17002
+ def format_config(result):
17003
+ escaped_payload = result['sent_payload'].replace('\r\n', '[crlf]')
17004
+ return f"""# ====================================================
16967
17005
  # CONFIG #{result['config_id']}
16968
17006
  # ====================================================
16969
17007
  [CONFIG]
@@ -16978,7 +17016,7 @@ def menu3():
16978
17016
  {escaped_payload}
16979
17017
 
16980
17018
  [HEADERS]
16981
- User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
17019
+ 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
16982
17020
  Accept=*/*
16983
17021
  Accept-Language=en-US,en;q=0.9
16984
17022
  Accept-Encoding=gzip, deflate
@@ -16995,329 +17033,345 @@ def menu3():
16995
17033
  Response_Time={result['response_time']:.2f}s
16996
17034
  Server={result['server']}
16997
17035
  Bypass_Indicators={','.join(result['bypass_indicators'])}
16998
- Payload_Sent={result['sent_payload'][:1000].replace(chr(10), ' ').replace(chr(103), '')}...
16999
-
17000
17036
  # ====================================================
17001
17037
 
17002
17038
  """
17003
- return config
17039
+
17040
+ @staticmethod
17041
+ def save_results(results, filename, status_filter='All'):
17042
+ if not results:
17043
+ return 0
17004
17044
 
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
17045
+ with open(filename, 'w', encoding='utf-8') as f:
17046
+ f.write(f"""# HTTP Injector Configurations
17014
17047
  # Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}
17015
- # Total Working Configs: {len(results)}
17048
+ # Total Configs: {len(results)}
17049
+ # Status Filter: {status_filter}
17016
17050
  #
17017
17051
  # HOW TO USE:
17018
- # 1. Copy each [CONFIG] section below
17052
+ # 1. Copy each [CONFIG] section
17019
17053
  # 2. Create new config in HTTP Injector
17020
17054
  # 3. Paste the settings
17021
- # 4. Use with the specified proxy: {results[0]['proxy_host']}:{results[0]['proxy_port']}
17022
- #
17023
17055
  # ====================================================
17024
17056
 
17025
17057
  """)
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)
17058
+ f.write("[SUMMARY]\n")
17059
+ f.write(f"Total_Configs={len(results)}\n")
17060
+ f.write(f"Status_Filter={status_filter}\n")
17075
17061
 
17076
- return len(results)
17077
-
17078
- class ProxyManager:
17079
- @staticmethod
17080
- def parse_proxy_input(proxy_input, ports):
17081
- proxies = []
17062
+ status_stats = {}
17063
+ for result in results:
17064
+ status = result['status_code']
17065
+ status_category = f"{status//100}xx"
17066
+ status_stats[status_category] = status_stats.get(status_category, 0) + 1
17082
17067
 
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
17068
+ f.write("\n[STATUS_DISTRIBUTION]\n")
17069
+ for status, count in sorted(status_stats.items()):
17070
+ f.write(f"{status}={count}\n")
17071
+
17072
+ f.write(f"\n#{'='*50}\n# WORKING CONFIGURATIONS\n#{'='*50}\n\n")
17099
17073
 
17100
- # CIDR without port
17101
- if '/' in proxy_input:
17074
+ for i, result in enumerate(results, 1):
17075
+ result['config_id'] = i
17076
+ f.write(PayloadManager.format_config(result))
17077
+
17078
+ return len(results)
17079
+
17080
+ class ProxyManager:
17081
+ @staticmethod
17082
+ def parse_proxy_input(proxy_input, ports):
17083
+ proxies = []
17084
+
17085
+ if ':' in proxy_input:
17086
+ ip_part, port = proxy_input.split(':', 1)
17087
+ port = int(port)
17088
+
17089
+ if '/' in ip_part:
17102
17090
  try:
17103
- network = ipaddress.ip_network(proxy_input, strict=False)
17091
+ network = ipaddress.ip_network(ip_part, strict=False)
17104
17092
  for ip in network.hosts():
17105
- for port in ports:
17106
- proxies.append((str(ip), port))
17093
+ proxies.append((str(ip), port))
17107
17094
  except:
17108
17095
  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
-
17096
+ else:
17097
+ proxies.append((ip_part, port))
17098
+ return proxies
17099
+
17100
+ if '/' in proxy_input:
17101
+ try:
17102
+ network = ipaddress.ip_network(proxy_input, strict=False)
17103
+ for ip in network.hosts():
17104
+ for port in ports:
17105
+ proxies.append((str(ip), port))
17106
+ except:
17107
+ pass
17129
17108
  return proxies
17109
+
17110
+ if '-' in proxy_input:
17111
+ parts = proxy_input.split('-')
17112
+ if len(parts) == 2:
17113
+ base_ip = parts[0].rsplit('.', 1)[0]
17114
+ start = int(parts[0].rsplit('.', 1)[1])
17115
+ end = int(parts[1])
17116
+
17117
+ for i in range(start, end + 1):
17118
+ ip = f"{base_ip}.{i}"
17119
+ for port in ports:
17120
+ proxies.append((ip, port))
17121
+ return proxies
17122
+
17123
+ for port in ports:
17124
+ proxies.append((proxy_input.strip(), port))
17125
+
17126
+ return proxies
17127
+
17128
+ class NetworkTester:
17129
+ def __init__(self, config):
17130
+ self.config = config
17131
+ self.working_configs = []
17132
+ self.lock = threading.Lock()
17133
+ self.queue = Queue()
17134
+ self.tested = 0
17135
+ self.successful = 0
17136
+ self.failed = 0
17137
+
17138
+ def detect_provider(self, response_text, target):
17139
+ provider_indicators = {
17140
+ 'Google': ['Google', 'gws', 'GSE', 'YouTube'],
17141
+ 'Microsoft': ['Microsoft', 'IIS', 'Azure', 'Office'],
17142
+ 'Facebook': ['Facebook', 'fb', 'Instagram'],
17143
+ 'Cloudflare': ['Cloudflare', 'CF-RAY', 'cf-cache-status'],
17144
+ 'Akamai': ['Akamai', 'Akamai-Ghost'],
17145
+ 'Amazon': ['Amazon', 'AWS', 'CloudFront', 'S3'],
17146
+ 'Alibaba': ['Alibaba', 'Aliyun', 'EMAS', 'AlibabaCloud'],
17147
+ 'Tencent': ['Tencent', 'QCloud', 'TCB'],
17148
+ 'Baidu': ['Baidu', 'baidu.com'],
17149
+ 'Fastly': ['Fastly', 'Fastly error'],
17150
+ 'CDN77': ['CDN77', 'NetDNA'],
17151
+ 'Cloudflare': ['Cloudflare', 'CF-RAY'],
17152
+ 'Nginx': ['nginx'],
17153
+ 'Apache': ['Apache', 'httpd'],
17154
+ 'LiteSpeed': ['LiteSpeed', 'LSWS'],
17155
+ 'Varnish': ['Varnish'],
17156
+ 'Sucuri': ['Sucuri'],
17157
+ 'Imperva': ['Imperva', 'Imperva Incapsula']
17158
+ }
17159
+
17160
+ for provider, indicators in provider_indicators.items():
17161
+ for indicator in indicators:
17162
+ if indicator.lower() in response_text.lower():
17163
+ return provider
17164
+
17165
+ return 'Unknown'
17130
17166
 
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
17167
+ def test_connection(self, payload_info, target, proxy_host, proxy_port):
17168
+ try:
17169
+ sent_payload = PayloadManager.prepare_payload(payload_info['payload'], target)
17170
+
17171
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
17172
+ sock.settimeout(self.config.timeout)
17139
17173
 
17140
- def test_connection(self, payload_info, target_domain, proxy_host, proxy_port):
17141
- """Test payload with target domain through proxy"""
17174
+ start_time = time.time()
17175
+ sock.connect((proxy_host, proxy_port))
17176
+ sock.send(sent_payload.encode())
17177
+
17178
+ response = b""
17142
17179
  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
17180
  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:
17181
+ while True:
17182
+ chunk = sock.recv(1024)
17183
+ if not chunk:
17165
17184
  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
- ]
17185
+ response += chunk
17186
+ if len(response) > 8192:
17187
+ break
17188
+ except socket.timeout:
17189
+ pass
17190
+
17191
+ sock.close()
17192
+ response_time = time.time() - start_time
17193
+
17194
+ response_text = response.decode('utf-8', errors='ignore')
17195
+
17196
+ status_match = re.search(r'HTTP/\d\.\d\s+(\d{3})', response_text)
17197
+ status_code = int(status_match.group(1)) if status_match else 0
17222
17198
 
17223
- for pattern, meaning in checks:
17224
- if re.search(pattern, response_text, re.IGNORECASE | re.DOTALL):
17225
- indicators.append(meaning)
17199
+ if status_code == 0:
17200
+ return {'success': False, 'error': 'No HTTP response'}
17226
17201
 
17227
- return indicators
17202
+ server_match = re.search(r'Server:\s*([^\r\n]+)', response_text, re.IGNORECASE)
17203
+ server_info = server_match.group(1) if server_match else "Unknown"
17204
+
17205
+ bypass_indicators = self._check_bypass_indicators(response_text)
17206
+ provider = self.detect_provider(response_text, target)
17207
+
17208
+ return {
17209
+ 'payload_name': payload_info['name'],
17210
+ 'payload_template': payload_info['payload'],
17211
+ 'sent_payload': sent_payload,
17212
+ 'target': target,
17213
+ 'proxy_host': proxy_host,
17214
+ 'proxy_port': proxy_port,
17215
+ 'status_code': status_code,
17216
+ 'response_time': response_time,
17217
+ 'server': server_info,
17218
+ 'bypass_indicators': bypass_indicators,
17219
+ 'provider': provider,
17220
+ 'success': True
17221
+ }
17222
+
17223
+ except socket.timeout:
17224
+ return {'success': False, 'error': 'Connection timeout'}
17225
+ except ConnectionRefusedError:
17226
+ return {'success': False, 'error': 'Connection refused'}
17227
+ except Exception as e:
17228
+ return {'success': False, 'error': str(e)}
17229
+
17230
+ def _check_bypass_indicators(self, response_text):
17231
+ indicators = []
17232
+ checks = [
17233
+ (r'CF-RAY', 'Cloudflare Proxy'),
17234
+ (r'X-Cache', 'Caching Proxy'),
17235
+ (r'Connection established', 'CONNECT Successful'),
17236
+ (r'101 Switching Protocols', 'WebSocket Upgrade'),
17237
+ (r'HTTP/1.1 200.*HTTP/1.1', 'Request Smuggling'),
17238
+ (r'Upgrade:', 'Protocol Upgrade'),
17239
+ (r'Keep-Alive', 'Connection Persistence'),
17240
+ (r'X-Forwarded-For', 'Forwarded Request'),
17241
+ (r'X-Real-IP', 'Real IP Header'),
17242
+ (r'X-Forwarded-Host', 'Host Bypass'),
17243
+ (r'X-Original-Host', 'Original Host'),
17244
+ (r'Via:', 'Proxy Chain'),
17245
+ (r'Proxy-Connection', 'Proxy Support'),
17246
+ (r'Transfer-Encoding: chunked', 'Chunked Encoding'),
17247
+ (r'Content-Encoding: gzip', 'Compression Support'),
17248
+ (r'Server:.*nginx', 'Nginx Server'),
17249
+ (r'Server:.*Apache', 'Apache Server'),
17250
+ (r'Set-Cookie', 'Session Cookie'),
17251
+ (r'Vary:', 'Cache Variation'),
17252
+ (r'Age:', 'Cache Age')
17253
+ ]
17228
17254
 
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)
17255
+ for pattern, meaning in checks:
17256
+ if re.search(pattern, response_text, re.IGNORECASE | re.DOTALL):
17257
+ indicators.append(meaning)
17258
+
17259
+ return indicators
17260
+
17261
+ def worker(self, progress_bar):
17262
+ while True:
17263
+ try:
17264
+ task = self.queue.get_nowait()
17265
+ except:
17266
+ break
17267
+
17268
+ try:
17269
+ payload_info, target, proxy_host, proxy_port = task
17270
+ result = self.test_connection(payload_info, target, proxy_host, proxy_port)
17271
+
17272
+ with self.lock:
17273
+ self.tested += 1
17236
17274
 
17237
- with self.lock:
17238
- self.tested += 1
17275
+ if result['success']:
17276
+ self.successful += 1
17277
+ self.working_configs.append(result)
17239
17278
 
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))
17279
+ icon = "✅" if 200 <= result['status_code'] < 300 else \
17280
+ "↪️" if 300 <= result['status_code'] < 400 else \
17281
+ "⚠️" if 400 <= result['status_code'] < 500 else "❌"
17282
+
17283
+ if result['bypass_indicators']:
17284
+ icon += "🚀"
17285
+
17286
+ provider_icon = {
17287
+ 'Google': '🔍',
17288
+ 'Microsoft': '🪟',
17289
+ 'Facebook': '👥',
17290
+ 'YouTube': '📺',
17291
+ 'Amazon': '📦',
17292
+ 'Cloudflare': '🛡️'
17293
+ }.get(result['provider'], '🌐')
17294
+
17295
+ print(f"\r{icon}{provider_icon} {result['payload_name'][:20]:20} → "
17296
+ f"{target[:15]:15} HTTP {result['status_code']:3} via {proxy_host}:{proxy_port}")
17274
17297
  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
17298
+ self.failed += 1
17299
+
17300
+ progress_bar.update(1)
17301
+ self.queue.task_done()
17302
+
17303
+ except Exception as e:
17304
+ with self.lock:
17305
+ self.tested += 1
17306
+ self.failed += 1
17307
+ progress_bar.update(1)
17308
+ self.queue.task_done()
17309
+
17310
+ def run_tests(self):
17311
+ tasks = []
17312
+ for payload_info in self.config.payloads:
17313
+ for target in self.config.targets:
17314
+ if self.config.proxies:
17315
+ for proxy_host, proxy_port in self.config.proxies:
17316
+ tasks.append((payload_info, target, proxy_host, proxy_port))
17317
+ else:
17318
+ tasks.append((payload_info, target, target, 80))
17319
+
17320
+ for task in tasks:
17321
+ self.queue.put(task)
17322
+
17323
+ total_tests = len(tasks)
17324
+
17325
+ print(f"\n{'='*60}")
17326
+ print(f"🧪 TESTING CONFIGURATION")
17327
+ print(f"{'='*60}")
17328
+ print(f"Payloads: {len(self.config.payloads)}")
17329
+ print(f"Targets: {len(self.config.targets)}")
17330
+ print(f"Proxies: {len(self.config.proxies) if self.config.proxies else 'Direct'}")
17331
+ print(f"Total Tests: {total_tests}")
17332
+ print(f"Threads: {min(self.config.threads, total_tests)}")
17333
+ print(f"{'='*60}")
17334
+
17335
+ print("\n📡 TESTING IN PROGRESS...\n")
17336
+
17337
+ thread_count = min(self.config.threads, total_tests, 100)
17338
+
17339
+ self.working_configs = []
17340
+ self.tested = 0
17341
+ self.successful = 0
17342
+ self.failed = 0
17343
+
17344
+ with tqdm(total=total_tests, desc="Testing", unit="test", ncols=80) as progress_bar:
17292
17345
  threads = []
17293
- for _ in range(min(self.config.threads, total_tests)):
17294
- t = threading.Thread(target=self.worker)
17346
+ for _ in range(thread_count):
17347
+ t = threading.Thread(target=self.worker, args=(progress_bar,))
17295
17348
  t.daemon = True
17296
17349
  t.start()
17297
17350
  threads.append(t)
17298
17351
 
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
17352
+ for t in threads:
17353
+ t.join()
17354
+
17355
+ print("\r" + " " * 80 + "\r", end="")
17356
+
17357
+ print(f"\n{'='*60}")
17358
+ print(f" TESTING COMPLETE")
17359
+ print(f"{'='*60}")
17360
+ print(f"Tests Completed: {self.tested}")
17361
+ print(f"Successful: {self.successful}")
17362
+ print(f"Failed: {self.failed}")
17363
+ print(f"Configs Found: {len(self.working_configs)}")
17364
+
17365
+ return self.working_configs
17366
+
17367
+ def get_user_input():
17312
17368
  config = Config()
17313
17369
 
17314
- # Select payloads
17315
- print("\n📋 AVAILABLE PAYLOAD TEMPLATES:")
17316
- print("-" * 55)
17370
+ print("\n📋 AVAILABLE PAYLOADS:")
17317
17371
  for key, info in XHTTP_PAYLOADS.items():
17318
- print(f"{key}. {info['name']} ({info['type']})")
17372
+ print(f"{key:>2}. {info['name']:25} [{info['type']:6}]")
17319
17373
 
17320
- selection = input("\nSelect payloads (numbers comma-separated, or 'all'): ").strip()
17374
+ selection = input("\nSelect payloads (comma-separated, or 'all'): ").strip()
17321
17375
 
17322
17376
  if selection.lower() == 'all':
17323
17377
  selected_keys = list(XHTTP_PAYLOADS.keys())
@@ -17326,13 +17380,14 @@ def menu3():
17326
17380
 
17327
17381
  if not selected_keys:
17328
17382
  print("❌ No payloads selected!")
17329
- return
17383
+ return None
17330
17384
 
17331
17385
  for key in selected_keys:
17332
17386
  config.payloads.append(XHTTP_PAYLOADS[key])
17333
17387
 
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()
17388
+ print(f"\n✅ Selected {len(config.payloads)} payloads")
17389
+
17390
+ targets_input = input("\nEnter target domain(s) (comma-separated or file): ").strip()
17336
17391
 
17337
17392
  if os.path.isfile(targets_input):
17338
17393
  with open(targets_input, 'r') as f:
@@ -17341,97 +17396,174 @@ def menu3():
17341
17396
  config.targets = [t.strip() for t in targets_input.split(',') if t.strip()]
17342
17397
 
17343
17398
  if not config.targets:
17344
- print("❌ No target domains specified!")
17345
- return
17399
+ print("❌ No targets specified!")
17400
+ return None
17346
17401
 
17347
- # Get proxies - THESE ARE THE PROXIES WE TEST THROUGH
17348
17402
  print("\n🔄 PROXY SETTINGS")
17349
- print("1. Use proxies (for tunneling)")
17350
- print("2. Direct connection (no proxy)")
17403
+ print("1. Use proxies")
17404
+ print("2. Direct connection")
17351
17405
 
17352
17406
  proxy_choice = input("\nSelect option (1-2): ").strip()
17353
17407
 
17354
17408
  if proxy_choice == '1':
17355
17409
  proxy_input = input("Enter proxy (IP, IP:PORT, CIDR, or IP range): ").strip()
17356
17410
 
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
17411
+ ports_input = input("Ports (default=80,443,8080,8443): ").strip()
17412
+ ports = [int(p.strip()) for p in ports_input.split(',') if p.strip().isdigit()] if ports_input else [80, 443, 8080, 8443]
17362
17413
 
17363
17414
  config.proxies = ProxyManager.parse_proxy_input(proxy_input, ports)
17364
17415
 
17365
17416
  if not config.proxies:
17366
17417
  print("❌ Invalid proxy input!")
17367
- return
17418
+ return None
17368
17419
 
17369
- print(f"✅ Loaded {len(config.proxies)} proxy endpoints")
17420
+ print(f"✅ Loaded {len(config.proxies)} proxies")
17370
17421
 
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
17422
+ return config
17423
+
17424
+ def show_status_distribution(working_configs):
17425
+ status_details = {}
17426
+ for config in working_configs:
17427
+ status = config['status_code']
17428
+ status_details[status] = status_details.get(status, 0) + 1
17429
+
17430
+ print(f"\n{'='*60}")
17431
+ print("📊 STATUS CODE DISTRIBUTION")
17432
+ print(f"{'='*60}")
17433
+
17434
+ for status, count in sorted(status_details.items()):
17435
+ print(f" HTTP {status}: {count} configs")
17436
+
17437
+ print(f"\n{'='*60}")
17438
+ print("💾 SAVE RESULTS")
17439
+ print(f"{'='*60}")
17440
+ print("Which status codes to save?")
17441
+ print("1. All status codes")
17442
+ print("2. Only 2xx (Success)")
17443
+ print("3. Only 3xx (Redirection)")
17444
+ print("4. Only 4xx (Client Error)")
17445
+ print("5. Only 5xx (Server Error)")
17446
+ print("6. Success (2xx and 3xx)")
17447
+
17448
+ while True:
17449
+ choice = input("\nSelect option (1-6): ").strip()
17450
+
17451
+ if choice in ['1', '2', '3', '4', '5', '6']:
17452
+ status_filter_map = {
17453
+ '1': 'all',
17454
+ '2': '2xx',
17455
+ '3': '3xx',
17456
+ '4': '4xx',
17457
+ '5': '5xx',
17458
+ '6': 'success'
17459
+ }
17460
+ status_filter = status_filter_map[choice]
17461
+
17462
+ if choice == '2' and not any(200 <= s < 300 for s in status_details.keys()):
17463
+ print("⚠️ No 2xx responses found!")
17464
+ continue
17465
+ elif choice == '3' and not any(300 <= s < 400 for s in status_details.keys()):
17466
+ print("⚠️ No 3xx responses found!")
17467
+ continue
17468
+ elif choice == '4' and not any(400 <= s < 500 for s in status_details.keys()):
17469
+ print("⚠️ No 4xx responses found!")
17470
+ continue
17471
+ elif choice == '5' and not any(500 <= s < 600 for s in status_details.keys()):
17472
+ print("⚠️ No 5xx responses found!")
17473
+ continue
17474
+ elif choice == '6' and not any(200 <= s < 400 for s in status_details.keys()):
17475
+ print("⚠️ No success responses found!")
17476
+ continue
17477
+ elif choice == '':
17478
+ print("⚠️ Back to main menu.")
17479
+ continue
17480
+
17481
+ return status_filter
17482
+ else:
17483
+ print("❌ Invalid option!")
17484
+
17485
+ def save_with_filter(results, filename, status_filter):
17486
+ if not results:
17487
+ return 0
17488
+
17489
+ if status_filter == 'all':
17490
+ filtered_results = results
17491
+ elif status_filter == '2xx':
17492
+ filtered_results = [r for r in results if 200 <= r['status_code'] < 300]
17493
+ elif status_filter == '3xx':
17494
+ filtered_results = [r for r in results if 300 <= r['status_code'] < 400]
17495
+ elif status_filter == '4xx':
17496
+ filtered_results = [r for r in results if 400 <= r['status_code'] < 500]
17497
+ elif status_filter == '5xx':
17498
+ filtered_results = [r for r in results if 500 <= r['status_code'] < 600]
17499
+ elif status_filter == 'success':
17500
+ filtered_results = [r for r in results if 200 <= r['status_code'] < 400]
17501
+ else:
17502
+ filtered_results = results
17503
+
17504
+ if not filtered_results:
17505
+ print(f"❌ No results matching filter: {status_filter}")
17506
+ return 0
17507
+
17508
+ return PayloadManager.save_results(filtered_results, filename, status_filter)
17509
+
17510
+ def xhttp_payload_validator():
17511
+ os.system('clear' if os.name == 'posix' else 'cls')
17512
+
17513
+ banner = """
17514
+ ╔══════════════════════════════════════════════════════════╗
17515
+ ║ XHTTP TUNNEL PAYLOAD TESTER ║
17516
+ ║ Generate HTTP Injector Configs from Live Tests ║
17517
+ ╚══════════════════════════════════════════════════════════╝
17518
+ """
17519
+ print(banner)
17520
+
17521
+ config = get_user_input()
17522
+ if not config:
17523
+ return
17524
+
17525
+ estimated_tests = len(config.payloads) * len(config.targets) * max(len(config.proxies), 1)
17377
17526
 
17378
- # Confirm
17379
17527
  print(f"\n{'='*60}")
17380
17528
  print("READY TO TEST")
17381
17529
  print(f"{'='*60}")
17382
17530
  print(f"Payloads: {len(config.payloads)}")
17383
- print(f"Target Domains: {', '.join(config.targets[:3])}{'...' if len(config.targets) > 3 else ''}")
17531
+ print(f"Targets: {len(config.targets)}")
17384
17532
  print(f"Proxies: {len(config.proxies) if config.proxies else 'Direct'}")
17385
- print(f"Output: {config.output_file}")
17533
+ print(f"Estimated Tests: {estimated_tests}")
17386
17534
  print(f"{'='*60}")
17387
17535
 
17388
- confirm = input("\nStart testing? (y/n): ").strip().lower()
17389
- if confirm != 'y':
17536
+ if input("\nStart testing? (y/n): ").strip().lower() != 'y':
17390
17537
  print("❌ Cancelled")
17391
17538
  return
17392
17539
 
17393
- # Run tests
17394
17540
  start_time = time.time()
17395
17541
  tester = NetworkTester(config)
17396
17542
  working_configs = tester.run_tests()
17397
17543
 
17398
- # Save results - SINGLE FILE ONLY
17399
17544
  if working_configs:
17400
- saved_count = PayloadGenerator.save_all_results(working_configs, config.output_file)
17545
+ status_filter = show_status_distribution(working_configs)
17401
17546
 
17402
- elapsed = time.time() - start_time
17547
+ output_file = input("\n💾 Output file (default=working_configs.txt): ").strip()
17548
+ if output_file:
17549
+ if not output_file.endswith('.txt'):
17550
+ output_file += '.txt'
17551
+ config.output_file = output_file
17403
17552
 
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}")
17553
+ saved_count = save_with_filter(working_configs, config.output_file, status_filter)
17554
+ elapsed = time.time() - start_time
17411
17555
 
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")
17556
+ if saved_count > 0:
17557
+ print(f"\n{'='*60}")
17558
+ print("📦 RESULTS SAVED")
17559
+ print(f"{'='*60}")
17560
+ print(f" Generated {saved_count} configs")
17561
+ print(f"📁 Output: {config.output_file}")
17562
+ print(f"⏱️ Time: {elapsed:.1f}s")
17563
+ print(f"{'='*60}")
17431
17564
  else:
17432
17565
  print("\n❌ No working configurations found!")
17433
17566
 
17434
-
17435
17567
  xhttp_payload_validator()
17436
17568
 
17437
17569
 
@@ -17533,7 +17665,7 @@ def banner():
17533
17665
  MAGENTA + "██╔═══╝ ██╔══██╗██║ ██║" + LIME + "user should understand that useage of this script may be" + ENDC,
17534
17666
  MAGENTA + "██║ ██║ ██║╚██████╔╝" + LIME + "concidered an attack on a data network, and may violate terms" + ENDC,
17535
17667
  MAGENTA + "╚═╝ ╚═╝ ╚═╝ ╚═════╝" + LIME + "of service, use on your own network or get permission first" + ENDC,
17536
- PURPLE + "script_version@ 1.3.1 ®" + ENDC,
17668
+ PURPLE + "script_version@ 1.3.2 ®" + ENDC,
17537
17669
  ORANGE + "All rights reserved 2022-2026 ♛: ®" + ENDC,
17538
17670
  MAGENTA + "In Collaboration whit Ayan Rajpoot ® " + ENDC,
17539
17671
  BLUE + "Support: https://t.me/BugScanX 💬" + ENDC,
@@ -1,6 +0,0 @@
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,,