souleyez 2.26.0__py3-none-any.whl → 2.27.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.
Potentially problematic release.
This version of souleyez might be problematic. Click here for more details.
- souleyez/__init__.py +1 -1
- souleyez/docs/README.md +1 -1
- souleyez/docs/user-guide/configuration.md +1 -1
- souleyez/engine/background.py +617 -167
- souleyez/engine/result_handler.py +173 -1
- souleyez/engine/worker_manager.py +98 -2
- souleyez/main.py +1 -1
- souleyez/plugins/http_fingerprint.py +8 -2
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/METADATA +3 -3
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/RECORD +14 -14
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/WHEEL +0 -0
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/entry_points.txt +0 -0
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.26.0.dist-info → souleyez-2.27.0.dist-info}/top_level.txt +0 -0
|
@@ -44,6 +44,7 @@ def handle_job_result(job: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
44
44
|
return None
|
|
45
45
|
|
|
46
46
|
if not log_path or not os.path.exists(log_path):
|
|
47
|
+
logger.error(f"Job {job.get('id')} parse failed: log file missing or does not exist (path={log_path})")
|
|
47
48
|
return None
|
|
48
49
|
|
|
49
50
|
# Get engagement ID from job or fall back to current engagement
|
|
@@ -56,10 +57,12 @@ def handle_job_result(job: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
56
57
|
engagement = em.get_current()
|
|
57
58
|
|
|
58
59
|
if not engagement:
|
|
60
|
+
logger.error(f"Job {job.get('id')} parse failed: no engagement_id and no current engagement")
|
|
59
61
|
return None
|
|
60
62
|
|
|
61
63
|
engagement_id = engagement['id']
|
|
62
|
-
except Exception:
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error(f"Job {job.get('id')} parse failed: engagement lookup error: {e}")
|
|
63
66
|
return None
|
|
64
67
|
|
|
65
68
|
# Route to appropriate parser
|
|
@@ -110,6 +113,13 @@ def handle_job_result(job: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
110
113
|
parse_result = parse_dalfox_job(engagement_id, log_path, job)
|
|
111
114
|
elif tool == 'http_fingerprint':
|
|
112
115
|
parse_result = parse_http_fingerprint_job(engagement_id, log_path, job)
|
|
116
|
+
elif tool == 'hashcat':
|
|
117
|
+
parse_result = parse_hashcat_job(engagement_id, log_path, job)
|
|
118
|
+
elif tool == 'john':
|
|
119
|
+
parse_result = parse_john_job(engagement_id, log_path, job)
|
|
120
|
+
else:
|
|
121
|
+
# No parser for this tool - log it so we know
|
|
122
|
+
logger.warning(f"Job {job.get('id')} has no parser for tool '{tool}' - results not extracted")
|
|
113
123
|
|
|
114
124
|
# NOTE: Auto-chaining is now handled in background.py after parsing completes
|
|
115
125
|
# This avoids duplicate job creation and gives better control over timing
|
|
@@ -3245,3 +3255,165 @@ def parse_dalfox_job(engagement_id: int, log_path: str, job: Dict[str, Any]) ->
|
|
|
3245
3255
|
except Exception as e:
|
|
3246
3256
|
logger.error(f"Error parsing dalfox job: {e}")
|
|
3247
3257
|
return {'error': str(e)}
|
|
3258
|
+
|
|
3259
|
+
|
|
3260
|
+
def parse_hashcat_job(engagement_id: int, log_path: str, job: Dict[str, Any]) -> Dict[str, Any]:
|
|
3261
|
+
"""Parse hashcat job results and extract cracked passwords."""
|
|
3262
|
+
try:
|
|
3263
|
+
from souleyez.parsers.hashcat_parser import parse_hashcat_output, map_to_credentials
|
|
3264
|
+
from souleyez.storage.credentials import CredentialsManager
|
|
3265
|
+
from souleyez.storage.findings import FindingsManager
|
|
3266
|
+
|
|
3267
|
+
# Read the log file
|
|
3268
|
+
with open(log_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
3269
|
+
log_content = f.read()
|
|
3270
|
+
|
|
3271
|
+
# Parse hashcat output
|
|
3272
|
+
hash_file = job.get('metadata', {}).get('hash_file', '')
|
|
3273
|
+
parsed = parse_hashcat_output(log_content, hash_file)
|
|
3274
|
+
|
|
3275
|
+
# Store credentials
|
|
3276
|
+
cm = CredentialsManager()
|
|
3277
|
+
creds_added = 0
|
|
3278
|
+
|
|
3279
|
+
for cracked in parsed.get('cracked', []):
|
|
3280
|
+
try:
|
|
3281
|
+
cm.add_credential(
|
|
3282
|
+
engagement_id=engagement_id,
|
|
3283
|
+
host_id=None, # Hash cracking typically not tied to a specific host
|
|
3284
|
+
username='', # Hashcat doesn't always know the username
|
|
3285
|
+
password=cracked['password'],
|
|
3286
|
+
service='cracked_hash',
|
|
3287
|
+
credential_type='password',
|
|
3288
|
+
tool='hashcat',
|
|
3289
|
+
status='cracked',
|
|
3290
|
+
notes=f"Cracked from hash: {cracked['hash'][:32]}..."
|
|
3291
|
+
)
|
|
3292
|
+
creds_added += 1
|
|
3293
|
+
except Exception:
|
|
3294
|
+
pass # Skip duplicates
|
|
3295
|
+
|
|
3296
|
+
# Create finding if we cracked passwords
|
|
3297
|
+
fm = FindingsManager()
|
|
3298
|
+
findings_added = 0
|
|
3299
|
+
|
|
3300
|
+
if parsed.get('cracked'):
|
|
3301
|
+
fm.add_finding(
|
|
3302
|
+
engagement_id=engagement_id,
|
|
3303
|
+
title=f"Password Hashes Cracked - {len(parsed['cracked'])} passwords recovered",
|
|
3304
|
+
finding_type='credential',
|
|
3305
|
+
severity='high',
|
|
3306
|
+
description=f"Hashcat successfully cracked {len(parsed['cracked'])} password hash(es).\n\n"
|
|
3307
|
+
f"Status: {parsed['stats'].get('status', 'unknown')}\n"
|
|
3308
|
+
f"Cracked: {parsed['stats'].get('cracked_count', len(parsed['cracked']))}",
|
|
3309
|
+
tool='hashcat'
|
|
3310
|
+
)
|
|
3311
|
+
findings_added += 1
|
|
3312
|
+
|
|
3313
|
+
# Determine status
|
|
3314
|
+
if creds_added > 0:
|
|
3315
|
+
status = STATUS_DONE
|
|
3316
|
+
elif parsed['stats'].get('status') == 'exhausted':
|
|
3317
|
+
status = STATUS_NO_RESULTS # Ran to completion but found nothing
|
|
3318
|
+
else:
|
|
3319
|
+
status = STATUS_NO_RESULTS
|
|
3320
|
+
|
|
3321
|
+
return {
|
|
3322
|
+
'tool': 'hashcat',
|
|
3323
|
+
'status': status,
|
|
3324
|
+
'cracked_count': len(parsed.get('cracked', [])),
|
|
3325
|
+
'credentials_added': creds_added,
|
|
3326
|
+
'findings_added': findings_added,
|
|
3327
|
+
'hashcat_status': parsed['stats'].get('status', 'unknown')
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
except Exception as e:
|
|
3331
|
+
logger.error(f"Error parsing hashcat job: {e}")
|
|
3332
|
+
return {'error': str(e)}
|
|
3333
|
+
|
|
3334
|
+
|
|
3335
|
+
def parse_john_job(engagement_id: int, log_path: str, job: Dict[str, Any]) -> Dict[str, Any]:
|
|
3336
|
+
"""Parse John the Ripper job results and extract cracked passwords."""
|
|
3337
|
+
try:
|
|
3338
|
+
from souleyez.parsers.john_parser import parse_john_output
|
|
3339
|
+
from souleyez.storage.credentials import CredentialsManager
|
|
3340
|
+
from souleyez.storage.findings import FindingsManager
|
|
3341
|
+
|
|
3342
|
+
# Read the log file
|
|
3343
|
+
with open(log_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
3344
|
+
log_content = f.read()
|
|
3345
|
+
|
|
3346
|
+
# Get hash file from job metadata if available
|
|
3347
|
+
hash_file = job.get('metadata', {}).get('hash_file', None)
|
|
3348
|
+
|
|
3349
|
+
# Parse john output
|
|
3350
|
+
parsed = parse_john_output(log_content, hash_file)
|
|
3351
|
+
|
|
3352
|
+
# Store credentials
|
|
3353
|
+
cm = CredentialsManager()
|
|
3354
|
+
creds_added = 0
|
|
3355
|
+
|
|
3356
|
+
for cred in parsed.get('cracked', []):
|
|
3357
|
+
username = cred.get('username', '')
|
|
3358
|
+
password = cred.get('password', '')
|
|
3359
|
+
|
|
3360
|
+
if password: # At minimum we need a password
|
|
3361
|
+
try:
|
|
3362
|
+
cm.add_credential(
|
|
3363
|
+
engagement_id=engagement_id,
|
|
3364
|
+
host_id=None, # Hash cracking typically not tied to a specific host
|
|
3365
|
+
username=username if username != 'unknown' else '',
|
|
3366
|
+
password=password,
|
|
3367
|
+
service='cracked_hash',
|
|
3368
|
+
credential_type='password',
|
|
3369
|
+
tool='john',
|
|
3370
|
+
status='cracked',
|
|
3371
|
+
notes=f"Cracked by John the Ripper"
|
|
3372
|
+
)
|
|
3373
|
+
creds_added += 1
|
|
3374
|
+
except Exception:
|
|
3375
|
+
pass # Skip duplicates
|
|
3376
|
+
|
|
3377
|
+
# Create finding if we cracked passwords
|
|
3378
|
+
fm = FindingsManager()
|
|
3379
|
+
findings_added = 0
|
|
3380
|
+
|
|
3381
|
+
if parsed.get('cracked'):
|
|
3382
|
+
usernames = [c.get('username', 'unknown') for c in parsed['cracked'] if c.get('username')]
|
|
3383
|
+
usernames_str = ', '.join(usernames[:10]) # First 10
|
|
3384
|
+
if len(usernames) > 10:
|
|
3385
|
+
usernames_str += f" (+{len(usernames) - 10} more)"
|
|
3386
|
+
|
|
3387
|
+
fm.add_finding(
|
|
3388
|
+
engagement_id=engagement_id,
|
|
3389
|
+
title=f"Password Hashes Cracked - {len(parsed['cracked'])} passwords recovered",
|
|
3390
|
+
finding_type='credential',
|
|
3391
|
+
severity='high',
|
|
3392
|
+
description=f"John the Ripper successfully cracked {len(parsed['cracked'])} password hash(es).\n\n"
|
|
3393
|
+
f"Usernames: {usernames_str}\n"
|
|
3394
|
+
f"Session status: {parsed.get('session_status', 'unknown')}",
|
|
3395
|
+
tool='john'
|
|
3396
|
+
)
|
|
3397
|
+
findings_added += 1
|
|
3398
|
+
|
|
3399
|
+
# Determine status
|
|
3400
|
+
if creds_added > 0:
|
|
3401
|
+
status = STATUS_DONE
|
|
3402
|
+
elif parsed.get('session_status') == 'completed':
|
|
3403
|
+
status = STATUS_NO_RESULTS # Ran to completion but found nothing
|
|
3404
|
+
else:
|
|
3405
|
+
status = STATUS_NO_RESULTS
|
|
3406
|
+
|
|
3407
|
+
return {
|
|
3408
|
+
'tool': 'john',
|
|
3409
|
+
'status': status,
|
|
3410
|
+
'cracked_count': len(parsed.get('cracked', [])),
|
|
3411
|
+
'credentials_added': creds_added,
|
|
3412
|
+
'findings_added': findings_added,
|
|
3413
|
+
'session_status': parsed.get('session_status', 'unknown'),
|
|
3414
|
+
'total_loaded': parsed.get('total_loaded', 0)
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
except Exception as e:
|
|
3418
|
+
logger.error(f"Error parsing john job: {e}")
|
|
3419
|
+
return {'error': str(e)}
|
|
@@ -4,12 +4,13 @@ Worker health check and management utilities
|
|
|
4
4
|
"""
|
|
5
5
|
import psutil
|
|
6
6
|
import time
|
|
7
|
-
from typing import Optional, Tuple
|
|
7
|
+
from typing import Optional, Tuple, Dict, Any
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def is_worker_running() -> Tuple[bool, Optional[int]]:
|
|
11
11
|
"""
|
|
12
|
-
Check if background worker is running
|
|
12
|
+
Check if background worker is running.
|
|
13
|
+
|
|
13
14
|
Returns: (is_running, pid)
|
|
14
15
|
"""
|
|
15
16
|
for proc in psutil.process_iter(['pid', 'cmdline']):
|
|
@@ -29,6 +30,40 @@ def is_worker_running() -> Tuple[bool, Optional[int]]:
|
|
|
29
30
|
return False, None
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def is_worker_healthy() -> Tuple[bool, Optional[int], Optional[str]]:
|
|
34
|
+
"""
|
|
35
|
+
Check if background worker is running AND healthy (responding).
|
|
36
|
+
|
|
37
|
+
Uses heartbeat file to verify worker is actively processing.
|
|
38
|
+
A worker process may exist but be frozen/hung - heartbeat detects this.
|
|
39
|
+
|
|
40
|
+
Returns: (is_healthy, pid, issue)
|
|
41
|
+
- is_healthy: True if worker is running and heartbeat is fresh
|
|
42
|
+
- pid: Worker PID if found, None otherwise
|
|
43
|
+
- issue: Description of issue if not healthy, None otherwise
|
|
44
|
+
"""
|
|
45
|
+
from souleyez.engine.background import (
|
|
46
|
+
get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
is_running, pid = is_worker_running()
|
|
50
|
+
|
|
51
|
+
if not is_running:
|
|
52
|
+
return False, None, "Worker process not found"
|
|
53
|
+
|
|
54
|
+
# Check heartbeat
|
|
55
|
+
heartbeat_age = get_heartbeat_age()
|
|
56
|
+
|
|
57
|
+
if heartbeat_age is None:
|
|
58
|
+
# No heartbeat file - worker may have just started
|
|
59
|
+
return True, pid, "No heartbeat yet (may be starting)"
|
|
60
|
+
|
|
61
|
+
if heartbeat_age > HEARTBEAT_STALE_THRESHOLD:
|
|
62
|
+
return False, pid, f"Heartbeat stale ({int(heartbeat_age)}s old, threshold: {HEARTBEAT_STALE_THRESHOLD}s)"
|
|
63
|
+
|
|
64
|
+
return True, pid, None
|
|
65
|
+
|
|
66
|
+
|
|
32
67
|
def start_worker_if_needed() -> bool:
|
|
33
68
|
"""
|
|
34
69
|
Start worker if not running
|
|
@@ -107,3 +142,64 @@ def get_worker_status() -> dict:
|
|
|
107
142
|
pass
|
|
108
143
|
|
|
109
144
|
return status
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def get_worker_health() -> Dict[str, Any]:
|
|
148
|
+
"""
|
|
149
|
+
Get detailed worker health status including heartbeat info.
|
|
150
|
+
|
|
151
|
+
Returns dict with:
|
|
152
|
+
- running: Whether worker process exists
|
|
153
|
+
- healthy: Whether worker is running AND responsive
|
|
154
|
+
- pid: Worker PID if running
|
|
155
|
+
- uptime: Seconds since worker started
|
|
156
|
+
- heartbeat_age: Seconds since last heartbeat
|
|
157
|
+
- heartbeat_stale: Whether heartbeat is stale
|
|
158
|
+
- issue: Description of any health issue
|
|
159
|
+
- cpu_percent: CPU usage percentage
|
|
160
|
+
- memory_mb: Memory usage in MB
|
|
161
|
+
"""
|
|
162
|
+
from souleyez.engine.background import (
|
|
163
|
+
get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
is_running, pid = is_worker_running()
|
|
167
|
+
heartbeat_age = get_heartbeat_age()
|
|
168
|
+
|
|
169
|
+
health = {
|
|
170
|
+
'running': is_running,
|
|
171
|
+
'healthy': False,
|
|
172
|
+
'pid': pid,
|
|
173
|
+
'uptime': None,
|
|
174
|
+
'heartbeat_age': heartbeat_age,
|
|
175
|
+
'heartbeat_stale': heartbeat_age is None or heartbeat_age > HEARTBEAT_STALE_THRESHOLD,
|
|
176
|
+
'issue': None,
|
|
177
|
+
'cpu_percent': None,
|
|
178
|
+
'memory_mb': None
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if not is_running:
|
|
182
|
+
health['issue'] = "Worker process not found"
|
|
183
|
+
return health
|
|
184
|
+
|
|
185
|
+
# Get process info
|
|
186
|
+
try:
|
|
187
|
+
proc = psutil.Process(pid)
|
|
188
|
+
health['uptime'] = int(time.time() - proc.create_time())
|
|
189
|
+
health['cpu_percent'] = proc.cpu_percent(interval=0.1)
|
|
190
|
+
health['memory_mb'] = round(proc.memory_info().rss / 1024 / 1024, 1)
|
|
191
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
192
|
+
health['issue'] = "Cannot access worker process"
|
|
193
|
+
return health
|
|
194
|
+
|
|
195
|
+
# Check heartbeat
|
|
196
|
+
if heartbeat_age is None:
|
|
197
|
+
health['issue'] = "No heartbeat yet (worker may be starting)"
|
|
198
|
+
health['healthy'] = True # Give benefit of doubt for new workers
|
|
199
|
+
elif heartbeat_age > HEARTBEAT_STALE_THRESHOLD:
|
|
200
|
+
health['issue'] = f"Worker unresponsive (heartbeat {int(heartbeat_age)}s old)"
|
|
201
|
+
health['healthy'] = False
|
|
202
|
+
else:
|
|
203
|
+
health['healthy'] = True
|
|
204
|
+
|
|
205
|
+
return health
|
souleyez/main.py
CHANGED
|
@@ -173,7 +173,7 @@ def _check_privileged_tools():
|
|
|
173
173
|
|
|
174
174
|
|
|
175
175
|
@click.group()
|
|
176
|
-
@click.version_option(version='2.
|
|
176
|
+
@click.version_option(version='2.27.0')
|
|
177
177
|
def cli():
|
|
178
178
|
"""SoulEyez - AI-Powered Pentesting Platform by CyberSoul Security"""
|
|
179
179
|
from souleyez.log_config import init_logging
|
|
@@ -326,6 +326,12 @@ class HttpFingerprintPlugin(PluginBase):
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
parsed = urlparse(url)
|
|
329
|
+
|
|
330
|
+
# Security: Only allow http/https schemes (B310 - prevent file:// or custom schemes)
|
|
331
|
+
if parsed.scheme not in ('http', 'https'):
|
|
332
|
+
result['error'] = f"Invalid URL scheme: {parsed.scheme}. Only http/https allowed."
|
|
333
|
+
return result
|
|
334
|
+
|
|
329
335
|
is_https = parsed.scheme == 'https'
|
|
330
336
|
|
|
331
337
|
# Create request with common browser headers
|
|
@@ -362,9 +368,9 @@ class HttpFingerprintPlugin(PluginBase):
|
|
|
362
368
|
except Exception:
|
|
363
369
|
pass # TLS info is optional
|
|
364
370
|
|
|
365
|
-
response = urllib.request.urlopen(req, timeout=timeout, context=ctx)
|
|
371
|
+
response = urllib.request.urlopen(req, timeout=timeout, context=ctx) # nosec B310 - scheme validated above
|
|
366
372
|
else:
|
|
367
|
-
response = urllib.request.urlopen(req, timeout=timeout)
|
|
373
|
+
response = urllib.request.urlopen(req, timeout=timeout) # nosec B310 - scheme validated above
|
|
368
374
|
|
|
369
375
|
result['status_code'] = response.getcode()
|
|
370
376
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: souleyez
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.27.0
|
|
4
4
|
Summary: AI-Powered Penetration Testing Platform with 40+ integrated tools
|
|
5
5
|
Author-email: CyberSoul Security <contact@cybersoulsecurity.com>
|
|
6
6
|
Maintainer-email: CyberSoul Security <contact@cybersoulsecurity.com>
|
|
@@ -72,7 +72,7 @@ Welcome to the SoulEyez beta! Thank you for helping us test and improve this pen
|
|
|
72
72
|
|
|
73
73
|
> ⚠️ **Important**: Only use SoulEyez on systems you have explicit authorization to test.
|
|
74
74
|
|
|
75
|
-
## Version: 2.
|
|
75
|
+
## Version: 2.27.0
|
|
76
76
|
|
|
77
77
|
### What's Included
|
|
78
78
|
|
|
@@ -310,4 +310,4 @@ Happy hacking! 🛡️
|
|
|
310
310
|
|
|
311
311
|
---
|
|
312
312
|
|
|
313
|
-
**Version**: 2.
|
|
313
|
+
**Version**: 2.27.0 | **Release Date**: January 2026 | **Maintainer**: CyberSoul Security
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
souleyez/__init__.py,sha256=
|
|
1
|
+
souleyez/__init__.py,sha256=TXWDTbV0k4s5q6N3f2OyBp4G8i4-vO4HVgQITP7RmLg,23
|
|
2
2
|
souleyez/config.py,sha256=av357I3GYRWAklv8Dto-9-5Db699Wq5znez7zo7241Q,11595
|
|
3
3
|
souleyez/devtools.py,sha256=rptmUY4a5eVvYjdEc6273MSagL-D9xibPOFgohVqUno,3508
|
|
4
4
|
souleyez/feature_flags.py,sha256=mo6YAq07lc6sR3lEFKmIwTKxXZ2JPxwa5X97uR_mu50,4642
|
|
5
5
|
souleyez/history.py,sha256=gzs5I_j-3OigIP6yfmBChdqxaFmyUIxvTpzWUPe_Q6c,2853
|
|
6
6
|
souleyez/log_config.py,sha256=MMhPAJOqgXDfuE-xm5g0RxAfWndcmbhFHvIEMm1a_Wo,5830
|
|
7
|
-
souleyez/main.py,sha256=
|
|
7
|
+
souleyez/main.py,sha256=78BAKCcgpw3eUx1Uhxn3BlaP9YbigjZOjpbwTZS4zGE,122774
|
|
8
8
|
souleyez/scanner.py,sha256=U3IWHRrJ5aQ32dSHiVAHB60w1R_z0E0QxfM99msYNlw,3124
|
|
9
9
|
souleyez/security.py,sha256=S84m1QmnKz_6NgH2I6IBIAorMHxRPNYVFSnks5xjihQ,2479
|
|
10
10
|
souleyez/ui.py,sha256=15pfsqoDPnojAqr5S0TZHJE2ZkSHzkHpNVfVvsRj66A,34301
|
|
@@ -104,7 +104,7 @@ souleyez/detection/__init__.py,sha256=QIhvXjFdjrquQ6A0VQ7GZQkK_EXB59t8Dv9PKXhEUe
|
|
|
104
104
|
souleyez/detection/attack_signatures.py,sha256=akgWwiIkh6WYnghCuLhRV0y6FS0SQ0caGF8tZUc49oA,6965
|
|
105
105
|
souleyez/detection/mitre_mappings.py,sha256=xejE80YK-g8kKaeQoo-vBl8P3t8RTTItbfN0NaVZw6s,20558
|
|
106
106
|
souleyez/detection/validator.py,sha256=-AJ7QSJ3-6jFKLnPG_Rc34IXyF4JPyI82BFUgTA9zw0,15641
|
|
107
|
-
souleyez/docs/README.md,sha256=
|
|
107
|
+
souleyez/docs/README.md,sha256=3h0rS8Q7TVK5yYDP0X2MKR0C5j5xeUe55icS4T9eqsI,7183
|
|
108
108
|
souleyez/docs/api-reference/cli-commands.md,sha256=lTLFnILN3YRVdqCaag7WgsYXfDGglb1TuPexkxDsVdE,12917
|
|
109
109
|
souleyez/docs/api-reference/engagement-api.md,sha256=nd-EvQMtiJrobg2bzFEADp853HP1Uhb9dmgok0_-neE,11672
|
|
110
110
|
souleyez/docs/api-reference/integration-guide.md,sha256=c96uX79ukHyYotLa54wZ20Kx-EUZnrKegTeGkfLD-pw,16285
|
|
@@ -128,7 +128,7 @@ souleyez/docs/security/threat-model.md,sha256=JcR5AR-l977-7HTe5O2LULBikaxJovcxHE
|
|
|
128
128
|
souleyez/docs/user-guide/ai-integration.md,sha256=erC3Svg6XosKhT1BoHRQ98PUp71OdNQ6bkJIh7shN_Y,8859
|
|
129
129
|
souleyez/docs/user-guide/attack-surface.md,sha256=9QabVuuPkCNNDgAXx_Yerbtmnk61lPkU8Gjl_M6-rG8,12924
|
|
130
130
|
souleyez/docs/user-guide/auto-chaining.md,sha256=UjQ8J8rBgukQIikIrH3U7XoX0WF8EHO_a9i3qDomsXg,21144
|
|
131
|
-
souleyez/docs/user-guide/configuration.md,sha256=
|
|
131
|
+
souleyez/docs/user-guide/configuration.md,sha256=O2ZXyAAV6E41AHZuY2ZglZ20yBh5Gg-crElGFn6Ho6s,14650
|
|
132
132
|
souleyez/docs/user-guide/deliverables-screenshots.md,sha256=D5ATXKZRhwXu8OsGMEEUzbXW3hJl-qTh4wsUPx8gNUA,15148
|
|
133
133
|
souleyez/docs/user-guide/dependencies.md,sha256=WOPilg0W0U3KnsdGREkM5_gAG7Rr5P10oco7qDKkJEY,7475
|
|
134
134
|
souleyez/docs/user-guide/evidence-vault.md,sha256=PNg7cIUlVXr41iMJTi66j4qUV2fkrPATljunx0pD5sI,9454
|
|
@@ -145,14 +145,14 @@ souleyez/docs/user-guide/uninstall.md,sha256=gDknetFhjZ0tnYk4JqhLa369NT4bIRb50rm
|
|
|
145
145
|
souleyez/docs/user-guide/worker-management.md,sha256=hNu6eSTVb6XM4Zbb0I9Y5aL4AA2EiWOSFI6iGjn17kU,12035
|
|
146
146
|
souleyez/docs/user-guide/workflows.md,sha256=4EyZKWRyuWf9wrENJwtidWKN25PGis1Pk33HIHk5UHM,22261
|
|
147
147
|
souleyez/engine/__init__.py,sha256=THI_89hQfAPJDsfzDcur6H9sEGhGAnTxSNim7UOExYc,110
|
|
148
|
-
souleyez/engine/background.py,sha256=
|
|
148
|
+
souleyez/engine/background.py,sha256=HnzpN8P6TcDNxLW4R2re2cgBbBsEOfCdshiCOfJDx-g,83140
|
|
149
149
|
souleyez/engine/base.py,sha256=G35U1d-fygUvzmHH8zxLXw-vyQ9JzcfhGaSYOsHJtzQ,728
|
|
150
150
|
souleyez/engine/job_status.py,sha256=OAEf2rAzapm55m4tc3PSilotdA5ONX15JavUMLre0is,2685
|
|
151
151
|
souleyez/engine/loader.py,sha256=ke6QQVVWozDnqGNBotajC3RBYOa2_DZmv5DAnDZVgIc,2769
|
|
152
152
|
souleyez/engine/log_sanitizer.py,sha256=QHF6zSms-wHo6SbL6fHXIh1GG-8G34lE7kl45nbPn70,7130
|
|
153
153
|
souleyez/engine/manager.py,sha256=aBQMoib-VWNXtIp5Qn34tRj1P1jiLpwAIoo1fexAaLU,3629
|
|
154
|
-
souleyez/engine/result_handler.py,sha256=
|
|
155
|
-
souleyez/engine/worker_manager.py,sha256=
|
|
154
|
+
souleyez/engine/result_handler.py,sha256=IIESU1rGDR3W7yZcZzDyfBTCIVZtHifS8HQv5Ns0eoE,136657
|
|
155
|
+
souleyez/engine/worker_manager.py,sha256=B7b8RbkKTNofmiIyHTNgdikoZCLXpB-iIl1S4-U3q9o,6127
|
|
156
156
|
souleyez/export/__init__.py,sha256=2kFHftSqqrRUG6PhtfhCyhnkpkjc-8Zb4utGo-Nb6B4,61
|
|
157
157
|
souleyez/export/evidence_bundle.py,sha256=hqPn_h2CidhL-1VAT0qraZ8r1yfnUTnLZ3RfPPCK5Ds,9966
|
|
158
158
|
souleyez/feature_flags/__init__.py,sha256=shd9UIGrNh_1jnHhKeGxWpwbBnFxd-UjgVyOZPYE7DE,42
|
|
@@ -227,7 +227,7 @@ souleyez/plugins/ffuf.py,sha256=7c1-Q7xXTMmH_2wHXikjmZnSgZL13Hj5E_asBxZ6Y5U,1165
|
|
|
227
227
|
souleyez/plugins/firmware_extract.py,sha256=_hZXx6cHb9noM6uVgi3hwrJLw8hE9mDUelTEHwoIdCU,6460
|
|
228
228
|
souleyez/plugins/gobuster.py,sha256=GMTUyfkVnZ2gp3kh_R-KQ4EIGEBX5fxBIMfHZrwkVFo,29285
|
|
229
229
|
souleyez/plugins/hashcat.py,sha256=aigfwBu9IorXKgbyEIWx0qOCEdr1wnZaPqdYwh0PITc,10381
|
|
230
|
-
souleyez/plugins/http_fingerprint.py,sha256=
|
|
230
|
+
souleyez/plugins/http_fingerprint.py,sha256=_D5UVAtDC0f-uy4pQcBI43c4jnsJ5wyvCIvttUiVurw,21202
|
|
231
231
|
souleyez/plugins/hydra.py,sha256=kfVJwgh3x1DC0wEtA-lkoY7qhQH1qKViYexUECZSPY4,29520
|
|
232
232
|
souleyez/plugins/impacket_getnpusers.py,sha256=6TBxVTO9NGUbn5ShV-dCxPP11CFqf-Y3lAgt8_oP2Vg,8652
|
|
233
233
|
souleyez/plugins/impacket_psexec.py,sha256=gU_MDSazDMj1TeWm5V9cD6wrLe3ULwbDv4jhg3Vm2rQ,8813
|
|
@@ -365,9 +365,9 @@ souleyez/ui/tutorial_state.py,sha256=Thf7_qCj4VKjG7UqgJqa9kjIqiFUU-7Q7kG4v-u2B4A
|
|
|
365
365
|
souleyez/ui/wazuh_vulns_view.py,sha256=3vJJEmrjgS2wD6EDB7ZV7WxgytBHTm-1WqNDjp7lVEI,21830
|
|
366
366
|
souleyez/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
367
367
|
souleyez/utils/tool_checker.py,sha256=kQcXJVY5NiO-orQAUnpHhpQvR5UOBNHJ0PaT0fBxYoQ,30782
|
|
368
|
-
souleyez-2.
|
|
369
|
-
souleyez-2.
|
|
370
|
-
souleyez-2.
|
|
371
|
-
souleyez-2.
|
|
372
|
-
souleyez-2.
|
|
373
|
-
souleyez-2.
|
|
368
|
+
souleyez-2.27.0.dist-info/licenses/LICENSE,sha256=J7vDD5QMF4w2oSDm35eBgosATE70ah1M40u9W4EpTZs,1090
|
|
369
|
+
souleyez-2.27.0.dist-info/METADATA,sha256=rb4LyNfy5hw_BtcKYyApY8MIKrZ4mdHqJZTbZiF1gCA,10691
|
|
370
|
+
souleyez-2.27.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
371
|
+
souleyez-2.27.0.dist-info/entry_points.txt,sha256=bN5W1dhjDZJl3TKclMjRpfQvGPmyrJLwwDuCj_X39HE,48
|
|
372
|
+
souleyez-2.27.0.dist-info/top_level.txt,sha256=afAMzS9p4lcdBNxhGo6jl3ipQE9HUvvNIPOdjtPjr_Q,9
|
|
373
|
+
souleyez-2.27.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|