zen-ai-pentest 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. agents/__init__.py +28 -0
  2. agents/agent_base.py +239 -0
  3. agents/agent_orchestrator.py +346 -0
  4. agents/analysis_agent.py +225 -0
  5. agents/cli.py +258 -0
  6. agents/exploit_agent.py +224 -0
  7. agents/integration.py +211 -0
  8. agents/post_scan_agent.py +937 -0
  9. agents/react_agent.py +384 -0
  10. agents/react_agent_enhanced.py +616 -0
  11. agents/react_agent_vm.py +298 -0
  12. agents/research_agent.py +176 -0
  13. api/__init__.py +11 -0
  14. api/auth.py +123 -0
  15. api/main.py +1027 -0
  16. api/schemas.py +357 -0
  17. api/websocket.py +97 -0
  18. autonomous/__init__.py +122 -0
  19. autonomous/agent.py +253 -0
  20. autonomous/agent_loop.py +1370 -0
  21. autonomous/exploit_validator.py +1537 -0
  22. autonomous/memory.py +448 -0
  23. autonomous/react.py +339 -0
  24. autonomous/tool_executor.py +488 -0
  25. backends/__init__.py +16 -0
  26. backends/chatgpt_direct.py +133 -0
  27. backends/claude_direct.py +130 -0
  28. backends/duckduckgo.py +138 -0
  29. backends/openrouter.py +120 -0
  30. benchmarks/__init__.py +149 -0
  31. benchmarks/benchmark_engine.py +904 -0
  32. benchmarks/ci_benchmark.py +785 -0
  33. benchmarks/comparison.py +729 -0
  34. benchmarks/metrics.py +553 -0
  35. benchmarks/run_benchmarks.py +809 -0
  36. ci_cd/__init__.py +2 -0
  37. core/__init__.py +17 -0
  38. core/async_pool.py +282 -0
  39. core/asyncio_fix.py +222 -0
  40. core/cache.py +472 -0
  41. core/container.py +277 -0
  42. core/database.py +114 -0
  43. core/input_validator.py +353 -0
  44. core/models.py +288 -0
  45. core/orchestrator.py +611 -0
  46. core/plugin_manager.py +571 -0
  47. core/rate_limiter.py +405 -0
  48. core/secure_config.py +328 -0
  49. core/shield_integration.py +296 -0
  50. modules/__init__.py +46 -0
  51. modules/cve_database.py +362 -0
  52. modules/exploit_assist.py +330 -0
  53. modules/nuclei_integration.py +480 -0
  54. modules/osint.py +604 -0
  55. modules/protonvpn.py +554 -0
  56. modules/recon.py +165 -0
  57. modules/sql_injection_db.py +826 -0
  58. modules/tool_orchestrator.py +498 -0
  59. modules/vuln_scanner.py +292 -0
  60. modules/wordlist_generator.py +566 -0
  61. risk_engine/__init__.py +99 -0
  62. risk_engine/business_impact.py +267 -0
  63. risk_engine/business_impact_calculator.py +563 -0
  64. risk_engine/cvss.py +156 -0
  65. risk_engine/epss.py +190 -0
  66. risk_engine/example_usage.py +294 -0
  67. risk_engine/false_positive_engine.py +1073 -0
  68. risk_engine/scorer.py +304 -0
  69. web_ui/backend/main.py +471 -0
  70. zen_ai_pentest-2.0.0.dist-info/METADATA +795 -0
  71. zen_ai_pentest-2.0.0.dist-info/RECORD +75 -0
  72. zen_ai_pentest-2.0.0.dist-info/WHEEL +5 -0
  73. zen_ai_pentest-2.0.0.dist-info/entry_points.txt +2 -0
  74. zen_ai_pentest-2.0.0.dist-info/licenses/LICENSE +21 -0
  75. zen_ai_pentest-2.0.0.dist-info/top_level.txt +10 -0
modules/protonvpn.py ADDED
@@ -0,0 +1,554 @@
1
+ """
2
+ Proton VPN Integration Module for Zen AI Pentest
3
+
4
+ Provides secure VPN connectivity for penetration testing operations:
5
+ - Anonymous reconnaissance
6
+ - Geo-location bypassing
7
+ - Secure C2 communications
8
+ - Traffic encryption
9
+
10
+ Author: SHAdd0WTAka
11
+ """
12
+
13
+ import asyncio
14
+ import json
15
+ import logging
16
+ import random
17
+ import subprocess
18
+ from dataclasses import dataclass, field
19
+ from enum import Enum
20
+ from pathlib import Path
21
+ from typing import Any, Dict, List, Optional, Tuple
22
+
23
+ logger = logging.getLogger("ZenAI.ProtonVPN")
24
+
25
+
26
+ class VPNProtocol(Enum):
27
+ """Supported VPN protocols"""
28
+
29
+ WIREGUARD = "wireguard"
30
+ OPENVPN_TCP = "openvpn-tcp"
31
+ OPENVPN_UDP = "openvpn-udp"
32
+
33
+
34
+ class VPNSecurityLevel(Enum):
35
+ """Proton VPN security levels"""
36
+
37
+ STANDARD = "standard" # Regular servers
38
+ SECURE_CORE = "secure-core" # Multi-hop ( entry -> secure country -> exit)
39
+ TOR = "tor" # VPN over Tor
40
+ P2P = "p2p" # P2P optimized
41
+
42
+
43
+ @dataclass
44
+ class VPNStatus:
45
+ """Current VPN connection status"""
46
+
47
+ connected: bool = False
48
+ server_ip: Optional[str] = None
49
+ server_location: Optional[str] = None
50
+ protocol: Optional[str] = None
51
+ public_ip: Optional[str] = None
52
+ original_ip: Optional[str] = None
53
+ connection_time: Optional[str] = None
54
+ kill_switch: bool = False
55
+
56
+ def to_dict(self) -> Dict[str, Any]:
57
+ return {
58
+ "connected": self.connected,
59
+ "server_ip": self.server_ip,
60
+ "server_location": self.server_location,
61
+ "protocol": self.protocol,
62
+ "public_ip": self.public_ip,
63
+ "original_ip": self.original_ip,
64
+ "connection_time": self.connection_time,
65
+ "kill_switch": self.kill_switch,
66
+ }
67
+
68
+
69
+ @dataclass
70
+ class VPNServer:
71
+ """Proton VPN server information"""
72
+
73
+ name: str
74
+ country: str
75
+ city: Optional[str] = None
76
+ ip: Optional[str] = None
77
+ load: int = 0 # Server load percentage
78
+ features: List[str] = field(default_factory=list)
79
+ tier: int = 0 # 0=Free, 1=Basic, 2=Plus, 3=Visionary
80
+
81
+ def __str__(self) -> str:
82
+ return f"{self.name} ({self.city}, {self.country}) - Load: {self.load}%"
83
+
84
+
85
+ class ProtonVPNManager:
86
+ """
87
+ Manager for Proton VPN integration
88
+
89
+ Features:
90
+ - Connect/disconnect to VPN servers
91
+ - Rotate IP addresses
92
+ - Secure Core (multi-hop) connections
93
+ - Kill switch management
94
+ - Country/region selection
95
+ - Automatic server selection (least load)
96
+ """
97
+
98
+ # Proton VPN countries optimized for pentesting
99
+ RECOMMENDED_COUNTRIES = [
100
+ "CH", # Switzerland - Strong privacy laws
101
+ "IS", # Iceland - Data protection
102
+ "SE", # Sweden - Good connectivity
103
+ "NL", # Netherlands - Fast servers
104
+ "DE", # Germany - Good infrastructure
105
+ "SG", # Singapore - Asia coverage
106
+ "JP", # Japan - Asia coverage
107
+ "CA", # Canada - North America
108
+ ]
109
+
110
+ # Countries with P2P support
111
+ P2P_COUNTRIES = ["NL", "CH", "IS", "SE", "DE", "SG"]
112
+
113
+ def __init__(self, config_path: Optional[str] = None):
114
+ self.config_path = config_path or "config/protonvpn.json"
115
+ self.status = VPNStatus()
116
+ self.connected = False
117
+ self.current_server: Optional[VPNServer] = None
118
+ self._original_ip: Optional[str] = None
119
+ self._connection_history: List[Dict] = []
120
+
121
+ async def get_public_ip(self) -> str:
122
+ """Get current public IP address"""
123
+ try:
124
+ # Multiple services for redundancy
125
+ services = [
126
+ "https://ip.me",
127
+ "https://api.ipify.org",
128
+ "https://icanhazip.com",
129
+ ]
130
+
131
+ for service in services:
132
+ try:
133
+ proc = await asyncio.create_subprocess_exec(
134
+ "curl",
135
+ "-s",
136
+ "--max-time",
137
+ "5",
138
+ service,
139
+ stdout=asyncio.subprocess.PIPE,
140
+ stderr=asyncio.subprocess.PIPE,
141
+ )
142
+ stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=6)
143
+ ip = stdout.decode().strip()
144
+ if ip and self._is_valid_ip(ip):
145
+ return ip
146
+ except:
147
+ continue
148
+
149
+ return "unknown"
150
+ except Exception as e:
151
+ logger.error(f"Failed to get public IP: {e}")
152
+ return "unknown"
153
+
154
+ def _is_valid_ip(self, ip: str) -> bool:
155
+ """Validate IP address format"""
156
+ import re
157
+
158
+ pattern = r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$"
159
+ return bool(re.match(pattern, ip))
160
+
161
+ async def connect(
162
+ self,
163
+ country: Optional[str] = None,
164
+ city: Optional[str] = None,
165
+ protocol: VPNProtocol = VPNProtocol.WIREGUARD,
166
+ security_level: VPNSecurityLevel = VPNSecurityLevel.STANDARD,
167
+ p2p: bool = False,
168
+ kill_switch: bool = True,
169
+ ) -> VPNStatus:
170
+ """
171
+ Connect to Proton VPN
172
+
173
+ Args:
174
+ country: ISO country code (e.g., 'CH', 'NL')
175
+ city: City name for specific location
176
+ protocol: VPN protocol to use
177
+ security_level: Security/Feature level
178
+ p2p: Use P2P-optimized servers
179
+ kill_switch: Enable kill switch
180
+ """
181
+ logger.info(f"Connecting to Proton VPN...")
182
+
183
+ # Save original IP
184
+ if not self._original_ip:
185
+ self._original_ip = await self.get_public_ip()
186
+ self.status.original_ip = self._original_ip
187
+
188
+ # Select server
189
+ if not country:
190
+ country = random.choice(self.RECOMMENDED_COUNTRIES)
191
+
192
+ if p2p and country not in self.P2P_COUNTRIES:
193
+ country = random.choice(self.P2P_COUNTRIES)
194
+
195
+ # Build connection command
196
+ server_name = self._get_server_name(country, city, p2p)
197
+
198
+ try:
199
+ # Check if protonvpn-cli is available
200
+ proc = await asyncio.create_subprocess_exec(
201
+ "protonvpn-cli",
202
+ "connect",
203
+ "--help",
204
+ stdout=asyncio.subprocess.PIPE,
205
+ stderr=asyncio.subprocess.PIPE,
206
+ )
207
+ await proc.communicate()
208
+
209
+ if proc.returncode != 0:
210
+ logger.warning("protonvpn-cli not found, using mock mode")
211
+ return await self._mock_connect(country, protocol)
212
+
213
+ # Real Proton VPN connection
214
+ cmd = ["protonvpn-cli", "connect", "--cc", country.lower()]
215
+
216
+ if protocol == VPNProtocol.WIREGUARD:
217
+ cmd.extend(["--protocol", "wireguard"])
218
+ elif protocol == VPNProtocol.OPENVPN_TCP:
219
+ cmd.extend(["--protocol", "tcp"])
220
+ elif protocol == VPNProtocol.OPENVPN_UDP:
221
+ cmd.extend(["--protocol", "udp"])
222
+
223
+ if security_level == VPNSecurityLevel.SECURE_CORE:
224
+ cmd.append("--sc")
225
+ elif security_level == VPNSecurityLevel.TOR:
226
+ cmd.append("--tor")
227
+
228
+ if kill_switch:
229
+ subprocess.run(["protonvpn-cli", "ks", "--on"], check=False)
230
+
231
+ proc = await asyncio.create_subprocess_exec(
232
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
233
+ )
234
+ stdout, stderr = await proc.communicate()
235
+
236
+ if proc.returncode == 0:
237
+ self.connected = True
238
+ self.status.connected = True
239
+ self.status.server_location = (
240
+ f"{city or 'Auto'}, {country}" if city else country
241
+ )
242
+ self.status.protocol = protocol.value
243
+ self.status.kill_switch = kill_switch
244
+ self.status.connection_time = self._get_timestamp()
245
+
246
+ # Get new public IP
247
+ await asyncio.sleep(3) # Wait for connection
248
+ self.status.public_ip = await self.get_public_ip()
249
+
250
+ logger.info(f"Connected to {self.status.server_location}")
251
+ logger.info(f"New IP: {self.status.public_ip}")
252
+
253
+ self._log_connection()
254
+
255
+ else:
256
+ error = stderr.decode() if stderr else "Unknown error"
257
+ logger.error(f"Connection failed: {error}")
258
+
259
+ except Exception as e:
260
+ logger.error(f"Connection error: {e}")
261
+ return await self._mock_connect(country, protocol)
262
+
263
+ return self.status
264
+
265
+ async def disconnect(self) -> VPNStatus:
266
+ """Disconnect from VPN"""
267
+ logger.info("Disconnecting from Proton VPN...")
268
+
269
+ try:
270
+ proc = await asyncio.create_subprocess_exec(
271
+ "protonvpn-cli",
272
+ "disconnect",
273
+ stdout=asyncio.subprocess.PIPE,
274
+ stderr=asyncio.subprocess.PIPE,
275
+ )
276
+ await proc.communicate()
277
+
278
+ self.connected = False
279
+ self.status.connected = False
280
+ self.status.server_ip = None
281
+ self.status.server_location = None
282
+ self.status.protocol = None
283
+ self.status.public_ip = await self.get_public_ip()
284
+
285
+ logger.info("Disconnected from VPN")
286
+
287
+ except Exception as e:
288
+ logger.error(f"Disconnect error: {e}")
289
+
290
+ return self.status
291
+
292
+ async def rotate_ip(
293
+ self,
294
+ country: Optional[str] = None,
295
+ protocol: VPNProtocol = VPNProtocol.WIREGUARD,
296
+ ) -> VPNStatus:
297
+ """
298
+ Rotate VPN IP address
299
+ Disconnect and reconnect to get new IP
300
+ """
301
+ logger.info("Rotating VPN IP...")
302
+
303
+ await self.disconnect()
304
+ await asyncio.sleep(2)
305
+
306
+ # Select different country if not specified
307
+ if not country:
308
+ available = [
309
+ c
310
+ for c in self.RECOMMENDED_COUNTRIES
311
+ if c != self.status.server_location
312
+ ]
313
+ country = random.choice(available)
314
+
315
+ return await self.connect(country=country, protocol=protocol)
316
+
317
+ def _get_server_name(self, country: str, city: Optional[str], p2p: bool) -> str:
318
+ """Generate server name based on parameters"""
319
+ if p2p:
320
+ return f"{country}-P2P"
321
+ if city:
322
+ return f"{country}-{city}"
323
+ return country
324
+
325
+ async def _mock_connect(self, country: str, protocol: VPNProtocol) -> VPNStatus:
326
+ """Mock connection for testing without real VPN"""
327
+ logger.info(f"[MOCK] Connecting to {country} via {protocol.value}")
328
+
329
+ self.connected = True
330
+ self.status.connected = True
331
+ self.status.server_location = f"MOCK-{country}"
332
+ self.status.protocol = protocol.value
333
+ self.status.server_ip = f"10.{random.randint(0,255)}.{random.randint(0,255)}.1"
334
+ self.status.public_ip = f"185.{random.randint(0,255)}.{random.randint(0,255)}.{random.randint(0,255)}"
335
+ self.status.connection_time = self._get_timestamp()
336
+
337
+ if not self._original_ip:
338
+ self._original_ip = "192.168.1.100"
339
+ self.status.original_ip = self._original_ip
340
+
341
+ return self.status
342
+
343
+ def get_status(self) -> VPNStatus:
344
+ """Get current VPN status"""
345
+ return self.status
346
+
347
+ def is_connected(self) -> bool:
348
+ """Check if VPN is connected"""
349
+ return self.connected
350
+
351
+ async def get_server_list(self, country: Optional[str] = None) -> List[VPNServer]:
352
+ """Get list of available VPN servers"""
353
+ servers = []
354
+
355
+ # Mock server list (in real implementation, fetch from Proton API)
356
+ mock_servers = [
357
+ VPNServer("CH-01", "CH", "Zurich", "185.159.158.1", 45, ["secure-core"], 2),
358
+ VPNServer(
359
+ "CH-02", "CH", "Geneva", "185.159.158.2", 30, ["secure-core", "p2p"], 2
360
+ ),
361
+ VPNServer(
362
+ "NL-01", "NL", "Amsterdam", "185.107.56.1", 60, ["p2p", "tor"], 2
363
+ ),
364
+ VPNServer("NL-02", "NL", "Amsterdam", "185.107.56.2", 25, ["p2p"], 2),
365
+ VPNServer(
366
+ "SE-01", "SE", "Stockholm", "185.210.217.1", 40, ["secure-core"], 2
367
+ ),
368
+ VPNServer(
369
+ "IS-01", "IS", "Reykjavik", "37.235.49.1", 20, ["secure-core"], 2
370
+ ),
371
+ VPNServer("DE-01", "DE", "Frankfurt", "185.104.63.1", 55, [], 1),
372
+ VPNServer("SG-01", "SG", "Singapore", "103.125.234.1", 70, ["p2p"], 2),
373
+ ]
374
+
375
+ if country:
376
+ servers = [s for s in mock_servers if s.country == country.upper()]
377
+ else:
378
+ servers = mock_servers
379
+
380
+ return sorted(servers, key=lambda x: x.load)
381
+
382
+ async def recommend_server(
383
+ self,
384
+ purpose: str = "general",
385
+ require_p2p: bool = False,
386
+ require_secure_core: bool = False,
387
+ ) -> Optional[VPNServer]:
388
+ """
389
+ Recommend best server for specific purpose
390
+
391
+ Args:
392
+ purpose: 'general', 'pentest', 'c2', 'fileshare'
393
+ require_p2p: Need P2P support
394
+ require_secure_core: Need multi-hop
395
+ """
396
+ servers = await self.get_server_list()
397
+
398
+ # Filter by requirements
399
+ if require_p2p:
400
+ servers = [s for s in servers if "p2p" in s.features]
401
+ if require_secure_core:
402
+ servers = [s for s in servers if "secure-core" in s.features]
403
+
404
+ # Purpose-based selection
405
+ if purpose == "pentest":
406
+ # Low load, secure core for anonymity
407
+ candidates = [s for s in servers if "secure-core" in s.features]
408
+ return min(candidates, key=lambda x: x.load) if candidates else None
409
+
410
+ elif purpose == "c2":
411
+ # Stable, low latency
412
+ return min(servers, key=lambda x: x.load)
413
+
414
+ elif purpose == "fileshare":
415
+ # P2P optimized
416
+ candidates = [s for s in servers if "p2p" in s.features]
417
+ return min(candidates, key=lambda x: x.load) if candidates else None
418
+
419
+ # General purpose - lowest load
420
+ return min(servers, key=lambda x: x.load) if servers else None
421
+
422
+ def get_connection_history(self) -> List[Dict]:
423
+ """Get history of VPN connections"""
424
+ return self._connection_history
425
+
426
+ def _log_connection(self):
427
+ """Log connection to history"""
428
+ self._connection_history.append(
429
+ {
430
+ "timestamp": self._get_timestamp(),
431
+ "server": self.status.server_location,
432
+ "protocol": self.status.protocol,
433
+ "public_ip": self.status.public_ip,
434
+ }
435
+ )
436
+
437
+ def _get_timestamp(self) -> str:
438
+ """Get current timestamp"""
439
+ from datetime import datetime
440
+
441
+ return datetime.now().isoformat()
442
+
443
+ def check_ip_leak(self) -> Dict[str, Any]:
444
+ """
445
+ Check for IP/DNS leaks
446
+ Returns leak test results
447
+ """
448
+ results = {
449
+ "dns_leak": False,
450
+ "webrtc_leak": False,
451
+ "ipv6_leak": False,
452
+ "recommendations": [],
453
+ }
454
+
455
+ # In real implementation, perform actual leak tests
456
+ # For now, return mock results
457
+
458
+ results["dns_servers"] = [
459
+ "10.8.8.1 (Proton VPN DNS)",
460
+ "10.8.8.2 (Proton VPN DNS)",
461
+ ]
462
+
463
+ results["recommendations"] = [
464
+ "IPv6 is disabled - Good for privacy",
465
+ "DNS queries go through VPN tunnel",
466
+ "No WebRTC leaks detected",
467
+ ]
468
+
469
+ return results
470
+
471
+ async def speed_test(self) -> Dict[str, Any]:
472
+ """Test VPN connection speed"""
473
+ logger.info("Running speed test...")
474
+
475
+ try:
476
+ # Simple curl-based speed test
477
+ proc = await asyncio.create_subprocess_exec(
478
+ "curl",
479
+ "-o",
480
+ "/dev/null",
481
+ "-w",
482
+ "%{time_total},%{speed_download}",
483
+ "https://speed.cloudflare.com/__down?bytes=10000000",
484
+ stdout=asyncio.subprocess.PIPE,
485
+ stderr=asyncio.subprocess.PIPE,
486
+ )
487
+ stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=30)
488
+
489
+ result = stdout.decode().strip()
490
+ if "," in result:
491
+ time_total, speed = result.split(",")
492
+ return {
493
+ "download_mbps": round(float(speed) / 125000, 2),
494
+ "latency_ms": round(float(time_total) * 1000, 2),
495
+ "status": "success",
496
+ }
497
+ except Exception as e:
498
+ logger.error(f"Speed test failed: {e}")
499
+
500
+ return {"download_mbps": 0, "latency_ms": 0, "status": "failed"}
501
+
502
+
503
+ # Convenience functions
504
+ async def quick_connect(country: Optional[str] = None) -> VPNStatus:
505
+ """Quick connect to Proton VPN"""
506
+ vpn = ProtonVPNManager()
507
+ return await vpn.connect(country=country)
508
+
509
+
510
+ async def secure_connect() -> VPNStatus:
511
+ """Connect with maximum security (Secure Core)"""
512
+ vpn = ProtonVPNManager()
513
+ return await vpn.connect(
514
+ country="CH", security_level=VPNSecurityLevel.SECURE_CORE, kill_switch=True
515
+ )
516
+
517
+
518
+ if __name__ == "__main__":
519
+ # Test
520
+ async def test():
521
+ vpn = ProtonVPNManager()
522
+
523
+ print("=== Proton VPN Manager Test ===")
524
+
525
+ # Get public IP
526
+ ip = await vpn.get_public_ip()
527
+ print(f"Current IP: {ip}")
528
+
529
+ # Connect
530
+ status = await vpn.connect(country="CH")
531
+ print(f"Connected: {status.connected}")
532
+ print(f"Location: {status.server_location}")
533
+ print(f"New IP: {status.public_ip}")
534
+
535
+ # Get servers
536
+ servers = await vpn.get_server_list()
537
+ print(f"\nAvailable servers: {len(servers)}")
538
+ for s in servers[:3]:
539
+ print(f" - {s}")
540
+
541
+ # Recommend server
542
+ recommended = await vpn.recommend_server(purpose="pentest")
543
+ if recommended:
544
+ print(f"\nRecommended for pentest: {recommended}")
545
+
546
+ # Speed test
547
+ speed = await vpn.speed_test()
548
+ print(f"\nSpeed: {speed['download_mbps']} Mbps")
549
+
550
+ # Disconnect
551
+ await vpn.disconnect()
552
+ print("\nDisconnected")
553
+
554
+ asyncio.run(test())