aiptx 2.0.2__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.

Potentially problematic release.


This version of aiptx might be problematic. Click here for more details.

Files changed (165) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +24 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/ptt.py +406 -0
  8. aipt_v2/agents/state.py +168 -0
  9. aipt_v2/app.py +960 -0
  10. aipt_v2/browser/__init__.py +31 -0
  11. aipt_v2/browser/automation.py +458 -0
  12. aipt_v2/browser/crawler.py +453 -0
  13. aipt_v2/cli.py +321 -0
  14. aipt_v2/compliance/__init__.py +71 -0
  15. aipt_v2/compliance/compliance_report.py +449 -0
  16. aipt_v2/compliance/framework_mapper.py +424 -0
  17. aipt_v2/compliance/nist_mapping.py +345 -0
  18. aipt_v2/compliance/owasp_mapping.py +330 -0
  19. aipt_v2/compliance/pci_mapping.py +297 -0
  20. aipt_v2/config.py +288 -0
  21. aipt_v2/core/__init__.py +43 -0
  22. aipt_v2/core/agent.py +630 -0
  23. aipt_v2/core/llm.py +395 -0
  24. aipt_v2/core/memory.py +305 -0
  25. aipt_v2/core/ptt.py +329 -0
  26. aipt_v2/database/__init__.py +14 -0
  27. aipt_v2/database/models.py +232 -0
  28. aipt_v2/database/repository.py +384 -0
  29. aipt_v2/docker/__init__.py +23 -0
  30. aipt_v2/docker/builder.py +260 -0
  31. aipt_v2/docker/manager.py +222 -0
  32. aipt_v2/docker/sandbox.py +371 -0
  33. aipt_v2/evasion/__init__.py +58 -0
  34. aipt_v2/evasion/request_obfuscator.py +272 -0
  35. aipt_v2/evasion/tls_fingerprint.py +285 -0
  36. aipt_v2/evasion/ua_rotator.py +301 -0
  37. aipt_v2/evasion/waf_bypass.py +439 -0
  38. aipt_v2/execution/__init__.py +23 -0
  39. aipt_v2/execution/executor.py +302 -0
  40. aipt_v2/execution/parser.py +544 -0
  41. aipt_v2/execution/terminal.py +337 -0
  42. aipt_v2/health.py +437 -0
  43. aipt_v2/intelligence/__init__.py +85 -0
  44. aipt_v2/intelligence/auth.py +520 -0
  45. aipt_v2/intelligence/chaining.py +775 -0
  46. aipt_v2/intelligence/cve_aipt.py +334 -0
  47. aipt_v2/intelligence/cve_info.py +1111 -0
  48. aipt_v2/intelligence/rag.py +239 -0
  49. aipt_v2/intelligence/scope.py +442 -0
  50. aipt_v2/intelligence/searchers/__init__.py +5 -0
  51. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  52. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  53. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  54. aipt_v2/intelligence/tools.json +443 -0
  55. aipt_v2/intelligence/triage.py +670 -0
  56. aipt_v2/interface/__init__.py +5 -0
  57. aipt_v2/interface/cli.py +230 -0
  58. aipt_v2/interface/main.py +501 -0
  59. aipt_v2/interface/tui.py +1276 -0
  60. aipt_v2/interface/utils.py +583 -0
  61. aipt_v2/llm/__init__.py +39 -0
  62. aipt_v2/llm/config.py +26 -0
  63. aipt_v2/llm/llm.py +514 -0
  64. aipt_v2/llm/memory.py +214 -0
  65. aipt_v2/llm/request_queue.py +89 -0
  66. aipt_v2/llm/utils.py +89 -0
  67. aipt_v2/models/__init__.py +15 -0
  68. aipt_v2/models/findings.py +295 -0
  69. aipt_v2/models/phase_result.py +224 -0
  70. aipt_v2/models/scan_config.py +207 -0
  71. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  72. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  73. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  74. aipt_v2/monitoring/prometheus.yml +60 -0
  75. aipt_v2/orchestration/__init__.py +52 -0
  76. aipt_v2/orchestration/pipeline.py +398 -0
  77. aipt_v2/orchestration/progress.py +300 -0
  78. aipt_v2/orchestration/scheduler.py +296 -0
  79. aipt_v2/orchestrator.py +2284 -0
  80. aipt_v2/payloads/__init__.py +27 -0
  81. aipt_v2/payloads/cmdi.py +150 -0
  82. aipt_v2/payloads/sqli.py +263 -0
  83. aipt_v2/payloads/ssrf.py +204 -0
  84. aipt_v2/payloads/templates.py +222 -0
  85. aipt_v2/payloads/traversal.py +166 -0
  86. aipt_v2/payloads/xss.py +204 -0
  87. aipt_v2/prompts/__init__.py +60 -0
  88. aipt_v2/proxy/__init__.py +29 -0
  89. aipt_v2/proxy/history.py +352 -0
  90. aipt_v2/proxy/interceptor.py +452 -0
  91. aipt_v2/recon/__init__.py +44 -0
  92. aipt_v2/recon/dns.py +241 -0
  93. aipt_v2/recon/osint.py +367 -0
  94. aipt_v2/recon/subdomain.py +372 -0
  95. aipt_v2/recon/tech_detect.py +311 -0
  96. aipt_v2/reports/__init__.py +17 -0
  97. aipt_v2/reports/generator.py +313 -0
  98. aipt_v2/reports/html_report.py +378 -0
  99. aipt_v2/runtime/__init__.py +44 -0
  100. aipt_v2/runtime/base.py +30 -0
  101. aipt_v2/runtime/docker.py +401 -0
  102. aipt_v2/runtime/local.py +346 -0
  103. aipt_v2/runtime/tool_server.py +205 -0
  104. aipt_v2/scanners/__init__.py +28 -0
  105. aipt_v2/scanners/base.py +273 -0
  106. aipt_v2/scanners/nikto.py +244 -0
  107. aipt_v2/scanners/nmap.py +402 -0
  108. aipt_v2/scanners/nuclei.py +273 -0
  109. aipt_v2/scanners/web.py +454 -0
  110. aipt_v2/scripts/security_audit.py +366 -0
  111. aipt_v2/telemetry/__init__.py +7 -0
  112. aipt_v2/telemetry/tracer.py +347 -0
  113. aipt_v2/terminal/__init__.py +28 -0
  114. aipt_v2/terminal/executor.py +400 -0
  115. aipt_v2/terminal/sandbox.py +350 -0
  116. aipt_v2/tools/__init__.py +44 -0
  117. aipt_v2/tools/active_directory/__init__.py +78 -0
  118. aipt_v2/tools/active_directory/ad_config.py +238 -0
  119. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  120. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  121. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  122. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  123. aipt_v2/tools/agents_graph/__init__.py +19 -0
  124. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  125. aipt_v2/tools/api_security/__init__.py +76 -0
  126. aipt_v2/tools/api_security/api_discovery.py +608 -0
  127. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  128. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  129. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  130. aipt_v2/tools/browser/__init__.py +5 -0
  131. aipt_v2/tools/browser/browser_actions.py +238 -0
  132. aipt_v2/tools/browser/browser_instance.py +535 -0
  133. aipt_v2/tools/browser/tab_manager.py +344 -0
  134. aipt_v2/tools/cloud/__init__.py +70 -0
  135. aipt_v2/tools/cloud/cloud_config.py +273 -0
  136. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  137. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  138. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  139. aipt_v2/tools/executor.py +307 -0
  140. aipt_v2/tools/parser.py +408 -0
  141. aipt_v2/tools/proxy/__init__.py +5 -0
  142. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  143. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  144. aipt_v2/tools/registry.py +196 -0
  145. aipt_v2/tools/scanners/__init__.py +343 -0
  146. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  147. aipt_v2/tools/scanners/burp_tool.py +631 -0
  148. aipt_v2/tools/scanners/config.py +156 -0
  149. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  150. aipt_v2/tools/scanners/zap_tool.py +612 -0
  151. aipt_v2/tools/terminal/__init__.py +5 -0
  152. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  153. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  154. aipt_v2/tools/terminal/terminal_session.py +449 -0
  155. aipt_v2/tools/tool_processing.py +108 -0
  156. aipt_v2/utils/__init__.py +17 -0
  157. aipt_v2/utils/logging.py +201 -0
  158. aipt_v2/utils/model_manager.py +187 -0
  159. aipt_v2/utils/searchers/__init__.py +269 -0
  160. aiptx-2.0.2.dist-info/METADATA +324 -0
  161. aiptx-2.0.2.dist-info/RECORD +165 -0
  162. aiptx-2.0.2.dist-info/WHEEL +5 -0
  163. aiptx-2.0.2.dist-info/entry_points.txt +7 -0
  164. aiptx-2.0.2.dist-info/licenses/LICENSE +21 -0
  165. aiptx-2.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,447 @@
1
+ """
2
+ BloodHound Integration
3
+
4
+ Wrapper for BloodHound Python ingestor (bloodhound-python).
5
+ Collects Active Directory data for attack path analysis:
6
+ - Users, Groups, Computers
7
+ - ACLs and permissions
8
+ - Sessions and logged-on users
9
+ - Trust relationships
10
+ - Group Policy Objects
11
+
12
+ Usage:
13
+ from aipt_v2.tools.active_directory import BloodHoundWrapper
14
+
15
+ bh = BloodHoundWrapper(config)
16
+ result = await bh.collect()
17
+ """
18
+
19
+ import asyncio
20
+ import json
21
+ from dataclasses import dataclass, field
22
+ from datetime import datetime, timezone
23
+ from pathlib import Path
24
+ from typing import List, Dict, Any, Optional
25
+
26
+ from aipt_v2.tools.active_directory.ad_config import ADConfig, get_ad_config
27
+
28
+
29
+ @dataclass
30
+ class BloodHoundResult:
31
+ """Result of BloodHound collection."""
32
+ domain: str
33
+ status: str
34
+ started_at: str
35
+ finished_at: str
36
+ duration: float
37
+ output_files: List[str]
38
+ collection_methods: List[str]
39
+ statistics: Dict[str, int]
40
+ attack_paths: List[Dict] # Parsed attack paths if available
41
+ metadata: Dict[str, Any] = field(default_factory=dict)
42
+
43
+
44
+ @dataclass
45
+ class BloodHoundConfig:
46
+ """BloodHound collection configuration."""
47
+ # Collection methods
48
+ collect_all: bool = True
49
+ collect_users: bool = True
50
+ collect_groups: bool = True
51
+ collect_computers: bool = True
52
+ collect_sessions: bool = True
53
+ collect_acls: bool = True
54
+ collect_trusts: bool = True
55
+ collect_gpos: bool = True
56
+
57
+ # Output options
58
+ output_dir: str = "./bloodhound_output"
59
+ output_prefix: str = ""
60
+ compress: bool = True # Create ZIP file
61
+
62
+ # Performance
63
+ threads: int = 10
64
+ dns_tcp: bool = False
65
+ dns_timeout: int = 3
66
+
67
+
68
+ class BloodHoundWrapper:
69
+ """
70
+ BloodHound Python Ingestor Wrapper.
71
+
72
+ Collects Active Directory data for BloodHound
73
+ attack path analysis.
74
+ """
75
+
76
+ COLLECTION_METHODS = {
77
+ "all": "All collection methods",
78
+ "default": "Users, Groups, Computers, Sessions, Trusts, ACL",
79
+ "users": "User enumeration",
80
+ "groups": "Group enumeration",
81
+ "computers": "Computer enumeration",
82
+ "sessions": "Session enumeration",
83
+ "acl": "ACL enumeration",
84
+ "trusts": "Trust enumeration",
85
+ "gpo": "GPO enumeration",
86
+ "container": "Container enumeration"
87
+ }
88
+
89
+ def __init__(
90
+ self,
91
+ ad_config: Optional[ADConfig] = None,
92
+ bh_config: Optional[BloodHoundConfig] = None
93
+ ):
94
+ """
95
+ Initialize BloodHound wrapper.
96
+
97
+ Args:
98
+ ad_config: AD configuration
99
+ bh_config: BloodHound collection configuration
100
+ """
101
+ self.ad_config = ad_config or ADConfig()
102
+ self.bh_config = bh_config or BloodHoundConfig()
103
+ self.output_files: List[str] = []
104
+ self._installed = None
105
+
106
+ async def check_installed(self) -> bool:
107
+ """Check if bloodhound-python is installed."""
108
+ if self._installed is not None:
109
+ return self._installed
110
+
111
+ try:
112
+ process = await asyncio.create_subprocess_shell(
113
+ "bloodhound-python --help",
114
+ stdout=asyncio.subprocess.PIPE,
115
+ stderr=asyncio.subprocess.PIPE
116
+ )
117
+ await process.communicate()
118
+ self._installed = process.returncode == 0
119
+ except Exception:
120
+ self._installed = False
121
+
122
+ return self._installed
123
+
124
+ def _build_command(self) -> List[str]:
125
+ """Build bloodhound-python command."""
126
+ cmd = ["bloodhound-python"]
127
+
128
+ # Domain and credentials
129
+ cmd.extend(["-d", self.ad_config.domain])
130
+ cmd.extend(["-u", self.ad_config.credentials.username])
131
+
132
+ if self.ad_config.credentials.password:
133
+ cmd.extend(["-p", self.ad_config.credentials.password])
134
+ elif self.ad_config.credentials.ntlm_hash:
135
+ # Use hash auth
136
+ hashes = self.ad_config.credentials.ntlm_hash
137
+ if ":" not in hashes:
138
+ hashes = f"aad3b435b51404eeaad3b435b51404ee:{hashes}"
139
+ cmd.extend(["--hashes", hashes])
140
+
141
+ # Target DC
142
+ if self.ad_config.dc_ip:
143
+ cmd.extend(["-dc", self.ad_config.dc_ip])
144
+ cmd.extend(["-ns", self.ad_config.dc_ip])
145
+
146
+ # Collection methods
147
+ if self.bh_config.collect_all:
148
+ cmd.extend(["-c", "all"])
149
+ else:
150
+ methods = []
151
+ if self.bh_config.collect_users:
152
+ methods.append("users")
153
+ if self.bh_config.collect_groups:
154
+ methods.append("groups")
155
+ if self.bh_config.collect_computers:
156
+ methods.append("computers")
157
+ if self.bh_config.collect_sessions:
158
+ methods.append("sessions")
159
+ if self.bh_config.collect_acls:
160
+ methods.append("acl")
161
+ if self.bh_config.collect_trusts:
162
+ methods.append("trusts")
163
+ if self.bh_config.collect_gpos:
164
+ methods.append("gpo")
165
+
166
+ if methods:
167
+ cmd.extend(["-c", ",".join(methods)])
168
+
169
+ # Output options
170
+ output_dir = Path(self.bh_config.output_dir)
171
+ output_dir.mkdir(parents=True, exist_ok=True)
172
+ cmd.extend(["--outputdir", str(output_dir)])
173
+
174
+ if self.bh_config.output_prefix:
175
+ cmd.extend(["--prefix", self.bh_config.output_prefix])
176
+
177
+ if self.bh_config.compress:
178
+ cmd.append("--zip")
179
+
180
+ # Performance options
181
+ cmd.extend(["--workers", str(self.bh_config.threads)])
182
+
183
+ if self.bh_config.dns_tcp:
184
+ cmd.append("--dns-tcp")
185
+
186
+ cmd.extend(["--dns-timeout", str(self.bh_config.dns_timeout)])
187
+
188
+ return cmd
189
+
190
+ async def collect(self, timeout: int = 3600) -> BloodHoundResult:
191
+ """
192
+ Run BloodHound collection.
193
+
194
+ Args:
195
+ timeout: Collection timeout in seconds
196
+
197
+ Returns:
198
+ BloodHoundResult with collection results
199
+ """
200
+ if not await self.check_installed():
201
+ raise RuntimeError(
202
+ "bloodhound-python is not installed. "
203
+ "Install with: pip install bloodhound"
204
+ )
205
+
206
+ started_at = datetime.now(timezone.utc).isoformat()
207
+ start_time = asyncio.get_event_loop().time()
208
+
209
+ cmd = self._build_command()
210
+ print(f"[*] Running: {' '.join(cmd)}")
211
+
212
+ process = await asyncio.create_subprocess_exec(
213
+ *cmd,
214
+ stdout=asyncio.subprocess.PIPE,
215
+ stderr=asyncio.subprocess.PIPE
216
+ )
217
+
218
+ try:
219
+ stdout, stderr = await asyncio.wait_for(
220
+ process.communicate(),
221
+ timeout=timeout
222
+ )
223
+ except asyncio.TimeoutError:
224
+ process.kill()
225
+ raise TimeoutError(f"BloodHound collection timed out after {timeout}s")
226
+
227
+ finished_at = datetime.now(timezone.utc).isoformat()
228
+ duration = asyncio.get_event_loop().time() - start_time
229
+
230
+ # Find output files
231
+ output_dir = Path(self.bh_config.output_dir)
232
+ output_files = []
233
+
234
+ # Look for JSON files
235
+ json_files = list(output_dir.glob("*.json"))
236
+ output_files.extend([str(f) for f in json_files])
237
+
238
+ # Look for ZIP files
239
+ zip_files = list(output_dir.glob("*.zip"))
240
+ output_files.extend([str(f) for f in zip_files])
241
+
242
+ self.output_files = output_files
243
+
244
+ # Parse statistics from output
245
+ statistics = self._parse_statistics(stdout.decode() + stderr.decode())
246
+
247
+ # Determine collection methods used
248
+ methods = []
249
+ if self.bh_config.collect_all:
250
+ methods = ["all"]
251
+ else:
252
+ if self.bh_config.collect_users:
253
+ methods.append("users")
254
+ if self.bh_config.collect_groups:
255
+ methods.append("groups")
256
+ if self.bh_config.collect_computers:
257
+ methods.append("computers")
258
+ if self.bh_config.collect_sessions:
259
+ methods.append("sessions")
260
+ if self.bh_config.collect_acls:
261
+ methods.append("acl")
262
+ if self.bh_config.collect_trusts:
263
+ methods.append("trusts")
264
+
265
+ status = "completed" if process.returncode == 0 else "failed"
266
+
267
+ return BloodHoundResult(
268
+ domain=self.ad_config.domain,
269
+ status=status,
270
+ started_at=started_at,
271
+ finished_at=finished_at,
272
+ duration=duration,
273
+ output_files=output_files,
274
+ collection_methods=methods,
275
+ statistics=statistics,
276
+ attack_paths=[], # Would need BloodHound DB analysis
277
+ metadata={
278
+ "return_code": process.returncode,
279
+ "output": stdout.decode()[:1000],
280
+ "errors": stderr.decode() if process.returncode != 0 else ""
281
+ }
282
+ )
283
+
284
+ def _parse_statistics(self, output: str) -> Dict[str, int]:
285
+ """Parse collection statistics from output."""
286
+ stats = {
287
+ "users": 0,
288
+ "groups": 0,
289
+ "computers": 0,
290
+ "sessions": 0,
291
+ "acls": 0,
292
+ "trusts": 0
293
+ }
294
+
295
+ import re
296
+
297
+ # Parse common output patterns
298
+ patterns = {
299
+ "users": r"(\d+)\s+users",
300
+ "groups": r"(\d+)\s+groups",
301
+ "computers": r"(\d+)\s+computers",
302
+ "sessions": r"(\d+)\s+sessions",
303
+ "acls": r"(\d+)\s+acls?",
304
+ "trusts": r"(\d+)\s+trusts?"
305
+ }
306
+
307
+ for stat_name, pattern in patterns.items():
308
+ match = re.search(pattern, output, re.IGNORECASE)
309
+ if match:
310
+ stats[stat_name] = int(match.group(1))
311
+
312
+ return stats
313
+
314
+ def parse_json_output(self) -> Dict[str, List[Dict]]:
315
+ """
316
+ Parse collected JSON files.
317
+
318
+ Returns:
319
+ Dict with parsed data by type
320
+ """
321
+ data = {
322
+ "users": [],
323
+ "groups": [],
324
+ "computers": [],
325
+ "domains": [],
326
+ "gpos": [],
327
+ "ous": []
328
+ }
329
+
330
+ for file_path in self.output_files:
331
+ if not file_path.endswith(".json"):
332
+ continue
333
+
334
+ try:
335
+ with open(file_path, "r") as f:
336
+ content = json.load(f)
337
+
338
+ # Determine type from filename or content
339
+ file_name = Path(file_path).name.lower()
340
+
341
+ if "users" in file_name:
342
+ data["users"].extend(content.get("data", []))
343
+ elif "groups" in file_name:
344
+ data["groups"].extend(content.get("data", []))
345
+ elif "computers" in file_name:
346
+ data["computers"].extend(content.get("data", []))
347
+ elif "domains" in file_name:
348
+ data["domains"].extend(content.get("data", []))
349
+ elif "gpos" in file_name:
350
+ data["gpos"].extend(content.get("data", []))
351
+ elif "ous" in file_name:
352
+ data["ous"].extend(content.get("data", []))
353
+
354
+ except Exception as e:
355
+ print(f"[!] Error parsing {file_path}: {e}")
356
+
357
+ return data
358
+
359
+ def identify_high_value_targets(self) -> List[Dict]:
360
+ """
361
+ Identify high-value targets from collected data.
362
+
363
+ Returns:
364
+ List of high-value targets
365
+ """
366
+ targets = []
367
+ data = self.parse_json_output()
368
+
369
+ # Look for Domain Admins members
370
+ for group in data.get("groups", []):
371
+ props = group.get("Properties", {})
372
+ name = props.get("name", "")
373
+
374
+ if "DOMAIN ADMINS" in name.upper():
375
+ members = group.get("Members", [])
376
+ for member in members:
377
+ targets.append({
378
+ "type": "user",
379
+ "name": member.get("MemberId", ""),
380
+ "reason": "Domain Admin member",
381
+ "priority": "critical"
382
+ })
383
+
384
+ # Look for computers with unconstrained delegation
385
+ for computer in data.get("computers", []):
386
+ props = computer.get("Properties", {})
387
+ if props.get("unconstraineddelegation", False):
388
+ targets.append({
389
+ "type": "computer",
390
+ "name": props.get("name", ""),
391
+ "reason": "Unconstrained delegation",
392
+ "priority": "high"
393
+ })
394
+
395
+ # Look for users with admincount
396
+ for user in data.get("users", []):
397
+ props = user.get("Properties", {})
398
+ if props.get("admincount", False):
399
+ targets.append({
400
+ "type": "user",
401
+ "name": props.get("name", ""),
402
+ "reason": "Admin count set",
403
+ "priority": "medium"
404
+ })
405
+
406
+ return targets
407
+
408
+
409
+ # Convenience function
410
+ async def run_bloodhound(
411
+ domain: str,
412
+ dc_ip: str,
413
+ username: str,
414
+ password: str,
415
+ output_dir: str = "./bloodhound_output",
416
+ collect_all: bool = True,
417
+ **kwargs
418
+ ) -> BloodHoundResult:
419
+ """
420
+ Quick BloodHound collection.
421
+
422
+ Args:
423
+ domain: AD domain
424
+ dc_ip: Domain Controller IP
425
+ username: Username
426
+ password: Password
427
+ output_dir: Output directory
428
+ collect_all: Collect all data
429
+
430
+ Returns:
431
+ BloodHoundResult
432
+ """
433
+ ad_config = get_ad_config(
434
+ domain=domain,
435
+ dc_ip=dc_ip,
436
+ username=username,
437
+ password=password
438
+ )
439
+
440
+ bh_config = BloodHoundConfig(
441
+ collect_all=collect_all,
442
+ output_dir=output_dir,
443
+ compress=True
444
+ )
445
+
446
+ wrapper = BloodHoundWrapper(ad_config, bh_config)
447
+ return await wrapper.collect()