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.
- {bhp_pro-1.3.1.dist-info → bhp_pro-1.3.2.dist-info}/METADATA +1 -1
- bhp_pro-1.3.2.dist-info/RECORD +6 -0
- bhp_pro.py +561 -429
- bhp_pro-1.3.1.dist-info/RECORD +0 -6
- {bhp_pro-1.3.1.dist-info → bhp_pro-1.3.2.dist-info}/WHEEL +0 -0
- {bhp_pro-1.3.1.dist-info → bhp_pro-1.3.2.dist-info}/entry_points.txt +0 -0
- {bhp_pro-1.3.1.dist-info → bhp_pro-1.3.2.dist-info}/top_level.txt +0 -0
|
@@ -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
|
-
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
"
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
"
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
"
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
"
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
"
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
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
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
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
|
-
|
|
17039
|
+
|
|
17040
|
+
@staticmethod
|
|
17041
|
+
def save_results(results, filename, status_filter='All'):
|
|
17042
|
+
if not results:
|
|
17043
|
+
return 0
|
|
17004
17044
|
|
|
17005
|
-
|
|
17006
|
-
|
|
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
|
|
17048
|
+
# Total Configs: {len(results)}
|
|
17049
|
+
# Status Filter: {status_filter}
|
|
17016
17050
|
#
|
|
17017
17051
|
# HOW TO USE:
|
|
17018
|
-
# 1. Copy each [CONFIG] section
|
|
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
|
-
|
|
17028
|
-
|
|
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
|
-
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
17080
|
-
|
|
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
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
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
|
-
|
|
17101
|
-
|
|
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(
|
|
17091
|
+
network = ipaddress.ip_network(ip_part, strict=False)
|
|
17104
17092
|
for ip in network.hosts():
|
|
17105
|
-
|
|
17106
|
-
proxies.append((str(ip), port))
|
|
17093
|
+
proxies.append((str(ip), port))
|
|
17107
17094
|
except:
|
|
17108
17095
|
pass
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
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
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
self.
|
|
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
|
-
|
|
17141
|
-
|
|
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
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
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
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
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
|
-
|
|
17224
|
-
|
|
17225
|
-
indicators.append(meaning)
|
|
17199
|
+
if status_code == 0:
|
|
17200
|
+
return {'success': False, 'error': 'No HTTP response'}
|
|
17226
17201
|
|
|
17227
|
-
|
|
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
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
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
|
-
|
|
17238
|
-
self.
|
|
17275
|
+
if result['success']:
|
|
17276
|
+
self.successful += 1
|
|
17277
|
+
self.working_configs.append(result)
|
|
17239
17278
|
|
|
17240
|
-
if result['
|
|
17241
|
-
|
|
17242
|
-
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
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
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17286
|
-
|
|
17287
|
-
|
|
17288
|
-
|
|
17289
|
-
|
|
17290
|
-
|
|
17291
|
-
|
|
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(
|
|
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
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
17304
|
-
|
|
17305
|
-
|
|
17306
|
-
|
|
17307
|
-
|
|
17308
|
-
|
|
17309
|
-
|
|
17310
|
-
|
|
17311
|
-
|
|
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
|
-
|
|
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']}
|
|
17372
|
+
print(f"{key:>2}. {info['name']:25} [{info['type']:6}]")
|
|
17319
17373
|
|
|
17320
|
-
selection = input("\nSelect payloads (
|
|
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
|
-
|
|
17335
|
-
|
|
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
|
|
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
|
|
17350
|
-
print("2. Direct connection
|
|
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
|
|
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)}
|
|
17420
|
+
print(f"✅ Loaded {len(config.proxies)} proxies")
|
|
17370
17421
|
|
|
17371
|
-
|
|
17372
|
-
|
|
17373
|
-
|
|
17374
|
-
|
|
17375
|
-
|
|
17376
|
-
|
|
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"
|
|
17531
|
+
print(f"Targets: {len(config.targets)}")
|
|
17384
17532
|
print(f"Proxies: {len(config.proxies) if config.proxies else 'Direct'}")
|
|
17385
|
-
print(f"
|
|
17533
|
+
print(f"Estimated Tests: {estimated_tests}")
|
|
17386
17534
|
print(f"{'='*60}")
|
|
17387
17535
|
|
|
17388
|
-
|
|
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
|
-
|
|
17545
|
+
status_filter = show_status_distribution(working_configs)
|
|
17401
17546
|
|
|
17402
|
-
|
|
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
|
-
|
|
17405
|
-
|
|
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
|
-
|
|
17413
|
-
|
|
17414
|
-
|
|
17415
|
-
|
|
17416
|
-
|
|
17417
|
-
|
|
17418
|
-
|
|
17419
|
-
|
|
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.
|
|
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,
|
bhp_pro-1.3.1.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|