itteration

This commit is contained in:
overcuriousity 2025-09-14 17:18:56 +02:00
parent 689e8c00d4
commit 949fbdbb45
9 changed files with 32 additions and 27 deletions

View File

@ -19,7 +19,7 @@ class Config:
# --- General Settings --- # --- General Settings ---
self.default_recursion_depth = 2 self.default_recursion_depth = 2
self.default_timeout = 10 self.default_timeout = 15
self.max_concurrent_requests = 5 self.max_concurrent_requests = 5
self.large_entity_threshold = 100 self.large_entity_threshold = 100
self.max_retries_per_target = 3 self.max_retries_per_target = 3
@ -27,7 +27,7 @@ class Config:
# --- Rate Limiting (requests per minute) --- # --- Rate Limiting (requests per minute) ---
self.rate_limits = { self.rate_limits = {
'crtsh': 60, 'crtsh': 30,
'shodan': 60, 'shodan': 60,
'dns': 100 'dns': 100
} }

View File

@ -80,8 +80,8 @@ class GraphManager:
return return
if len(value) < 4 or value.lower() in ['true', 'false', 'unknown', 'none', 'crt.sh']: if len(value) < 4 or value.lower() in ['true', 'false', 'unknown', 'none', 'crt.sh']:
return return
elif isinstance(value, int) and abs(value) < 9999: elif isinstance(value, int) and (abs(value) < 1024 or abs(value) > 65535):
return # Ignore small integers return # Ignore small integers and common port numbers
elif isinstance(value, bool): elif isinstance(value, bool):
return # Ignore boolean values return # Ignore boolean values
@ -421,10 +421,14 @@ class GraphManager:
def _get_confidence_distribution(self) -> Dict[str, int]: def _get_confidence_distribution(self) -> Dict[str, int]:
"""Get distribution of edge confidence scores.""" """Get distribution of edge confidence scores."""
distribution = {'high': 0, 'medium': 0, 'low': 0} distribution = {'high': 0, 'medium': 0, 'low': 0}
for _, _, confidence in self.graph.edges(data='confidence_score', default=0): for _, _, data in self.graph.edges(data=True):
if confidence >= 0.8: distribution['high'] += 1 confidence = data.get('confidence_score', 0)
elif confidence >= 0.6: distribution['medium'] += 1 if confidence >= 0.8:
else: distribution['low'] += 1 distribution['high'] += 1
elif confidence >= 0.6:
distribution['medium'] += 1
else:
distribution['low'] += 1
return distribution return distribution
def get_statistics(self) -> Dict[str, Any]: def get_statistics(self) -> Dict[str, Any]:
@ -439,9 +443,10 @@ class GraphManager:
# Calculate distributions # Calculate distributions
for node_type in NodeType: for node_type in NodeType:
stats['node_type_distribution'][node_type.value] = self.get_nodes_by_type(node_type).__len__() stats['node_type_distribution'][node_type.value] = self.get_nodes_by_type(node_type).__len__()
for _, _, rel_type in self.graph.edges(data='relationship_type', default='unknown'): for _, _, data in self.graph.edges(data=True):
rel_type = data.get('relationship_type', 'unknown')
stats['relationship_type_distribution'][rel_type] = stats['relationship_type_distribution'].get(rel_type, 0) + 1 stats['relationship_type_distribution'][rel_type] = stats['relationship_type_distribution'].get(rel_type, 0) + 1
for _, _, provider in self.graph.edges(data='source_provider', default='unknown'): provider = data.get('source_provider', 'unknown')
stats['provider_distribution'][provider] = stats['provider_distribution'].get(provider, 0) + 1 stats['provider_distribution'][provider] = stats['provider_distribution'].get(provider, 0) + 1
return stats return stats

View File

@ -42,7 +42,7 @@ class ForensicLogger:
Maintains detailed audit trail of all reconnaissance activities. Maintains detailed audit trail of all reconnaissance activities.
""" """
def __init__(self, session_id: str = None): def __init__(self, session_id: str = ""):
""" """
Initialize forensic logger. Initialize forensic logger.

View File

@ -5,7 +5,7 @@ import traceback
import time import time
import os import os
import importlib import importlib
from typing import List, Set, Dict, Any, Tuple from typing import List, Set, Dict, Any, Tuple, Optional
from concurrent.futures import ThreadPoolExecutor, as_completed, CancelledError, Future from concurrent.futures import ThreadPoolExecutor, as_completed, CancelledError, Future
from collections import defaultdict, deque from collections import defaultdict, deque
from datetime import datetime, timezone from datetime import datetime, timezone
@ -49,7 +49,7 @@ class Scanner:
self.max_depth = 2 self.max_depth = 2
self.stop_event = threading.Event() self.stop_event = threading.Event()
self.scan_thread = None self.scan_thread = None
self.session_id = None # Will be set by session manager self.session_id: Optional[str] = None # Will be set by session manager
self.task_queue = deque([]) self.task_queue = deque([])
self.target_retries = defaultdict(int) self.target_retries = defaultdict(int)
self.scan_failed_due_to_retries = False self.scan_failed_due_to_retries = False
@ -170,9 +170,10 @@ class Scanner:
attribute = getattr(module, attribute_name) attribute = getattr(module, attribute_name)
if isinstance(attribute, type) and issubclass(attribute, BaseProvider) and attribute is not BaseProvider: if isinstance(attribute, type) and issubclass(attribute, BaseProvider) and attribute is not BaseProvider:
provider_class = attribute provider_class = attribute
provider_name = provider_class(session_config=self.config).get_name() provider = provider_class(name=attribute_name, session_config=self.config)
provider_name = provider.get_name()
if self.config.is_provider_enabled(provider_name): if self.config.is_provider_enabled(provider_name):
provider = provider_class(session_config=self.config)
if provider.is_available(): if provider.is_available():
provider.set_stop_event(self.stop_event) provider.set_stop_event(self.stop_event)
self.providers.append(provider) self.providers.append(provider)
@ -459,7 +460,7 @@ class Scanner:
provider_states = node_data.get('metadata', {}).get('provider_states', {}) provider_states = node_data.get('metadata', {}).get('provider_states', {})
return provider_name in provider_states return provider_name in provider_states
def _query_single_provider_forensic(self, provider, target: str, is_ip: bool, current_depth: int) -> List: def _query_single_provider_forensic(self, provider, target: str, is_ip: bool, current_depth: int) -> Optional[List]:
"""Query a single provider with stop signal checking.""" """Query a single provider with stop signal checking."""
provider_name = provider.get_name() provider_name = provider.get_name()
start_time = datetime.now(timezone.utc) start_time = datetime.now(timezone.utc)
@ -493,7 +494,7 @@ class Scanner:
return None return None
def _update_provider_state(self, target: str, provider_name: str, status: str, def _update_provider_state(self, target: str, provider_name: str, status: str,
results_count: int, error: str, start_time: datetime) -> None: results_count: int, error: Optional[str], start_time: datetime) -> None:
"""Update provider state in node metadata for forensic tracking.""" """Update provider state in node metadata for forensic tracking."""
if not self.graph.graph.has_node(target): if not self.graph.graph.has_node(target):
return return
@ -785,7 +786,7 @@ class Scanner:
if isinstance(attribute, type) and issubclass(attribute, BaseProvider) and attribute is not BaseProvider: if isinstance(attribute, type) and issubclass(attribute, BaseProvider) and attribute is not BaseProvider:
provider_class = attribute provider_class = attribute
# Instantiate to get metadata, even if not fully configured # Instantiate to get metadata, even if not fully configured
temp_provider = provider_class(session_config=self.config) temp_provider = provider_class(name=attribute_name, session_config=self.config)
provider_name = temp_provider.get_name() provider_name = temp_provider.get_name()
# Find the actual provider instance if it exists, to get live stats # Find the actual provider instance if it exists, to get live stats

View File

@ -228,7 +228,7 @@ class BaseProvider(ABC):
self.total_requests += 1 self.total_requests += 1
# Prepare request # Prepare request
request_headers = self.session.headers.copy() request_headers = dict(self.session.headers).copy()
if headers: if headers:
request_headers.update(headers) request_headers.update(headers)

View File

@ -21,7 +21,7 @@ class CrtShProvider(BaseProvider):
Now uses session-specific configuration and caching. Now uses session-specific configuration and caching.
""" """
def __init__(self, session_config=None): def __init__(self, name=None, session_config=None):
"""Initialize CrtSh provider with session-specific configuration.""" """Initialize CrtSh provider with session-specific configuration."""
super().__init__( super().__init__(
name="crtsh", name="crtsh",

View File

@ -1,7 +1,6 @@
# dnsrecon/providers/dns_provider.py # dnsrecon/providers/dns_provider.py
import dns.resolver from dns import resolver, reversename
import dns.reversename
from typing import List, Dict, Any, Tuple from typing import List, Dict, Any, Tuple
from .base_provider import BaseProvider from .base_provider import BaseProvider
from utils.helpers import _is_valid_ip, _is_valid_domain from utils.helpers import _is_valid_ip, _is_valid_domain
@ -13,7 +12,7 @@ class DNSProvider(BaseProvider):
Now uses session-specific configuration. Now uses session-specific configuration.
""" """
def __init__(self, session_config=None): def __init__(self, name=None, session_config=None):
"""Initialize DNS provider with session-specific configuration.""" """Initialize DNS provider with session-specific configuration."""
super().__init__( super().__init__(
name="dns", name="dns",
@ -23,7 +22,7 @@ class DNSProvider(BaseProvider):
) )
# Configure DNS resolver # Configure DNS resolver
self.resolver = dns.resolver.Resolver() self.resolver = resolver.Resolver()
self.resolver.timeout = 5 self.resolver.timeout = 5
self.resolver.lifetime = 10 self.resolver.lifetime = 10
#self.resolver.nameservers = ['127.0.0.1'] #self.resolver.nameservers = ['127.0.0.1']
@ -87,7 +86,7 @@ class DNSProvider(BaseProvider):
try: try:
# Perform reverse DNS lookup # Perform reverse DNS lookup
self.total_requests += 1 self.total_requests += 1
reverse_name = dns.reversename.from_address(ip) reverse_name = reversename.from_address(ip)
response = self.resolver.resolve(reverse_name, 'PTR') response = self.resolver.resolve(reverse_name, 'PTR')
self.successful_requests += 1 self.successful_requests += 1

View File

@ -15,7 +15,7 @@ class ShodanProvider(BaseProvider):
Now uses session-specific API keys. Now uses session-specific API keys.
""" """
def __init__(self, session_config=None): def __init__(self, name=None, session_config=None):
"""Initialize Shodan provider with session-specific configuration.""" """Initialize Shodan provider with session-specific configuration."""
super().__init__( super().__init__(
name="shodan", name="shodan",

View File

@ -376,7 +376,7 @@ class GraphManager {
// Single correlation value // Single correlation value
const value = Array.isArray(values) && values.length > 0 ? values[0] : (metadata.value || 'Unknown'); const value = Array.isArray(values) && values.length > 0 ? values[0] : (metadata.value || 'Unknown');
const displayValue = typeof value === 'string' && value.length > 20 ? value.substring(0, 17) + '...' : value; const displayValue = typeof value === 'string' && value.length > 20 ? value.substring(0, 17) + '...' : value;
processedNode.label = `Corr: ${displayValue}`; processedNode.label = `${displayValue}`;
processedNode.title = `Correlation: ${value}`; processedNode.title = `Correlation: ${value}`;
} }
} }