executive summary

This commit is contained in:
overcuriousity
2025-09-18 00:13:37 +02:00
parent 140ef54674
commit fdc26dcf15
4 changed files with 222 additions and 11 deletions

View File

@@ -112,7 +112,7 @@ class Scanner:
# Fall back to local event
return self.stop_event.is_set()
return False
return self.stop_event.is_set()
def _set_stop_signal(self) -> None:
"""
@@ -883,6 +883,96 @@ class Scanner:
'scan_summary': self.logger.get_forensic_summary()
}
def export_targets_txt(self) -> str:
"""Export all discovered domains and IPs as a text file."""
nodes = self.graph.get_graph_data().get('nodes', [])
targets = {node['id'] for node in nodes if _is_valid_domain(node['id']) or _is_valid_ip(node['id'])}
return "\n".join(sorted(list(targets)))
def generate_executive_summary(self) -> str:
"""Generate a natural-language executive summary of the scan results."""
summary = []
now = datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S %Z')
scan_metadata = self.get_scan_status()
graph_data = self.graph.get_graph_data()
nodes = graph_data.get('nodes', [])
edges = graph_data.get('edges', [])
summary.append(f"DNSRecon Executive Summary")
summary.append(f"Report Generated: {now}")
summary.append("="*40)
# Scan Overview
summary.append("\n## Scan Overview")
summary.append(f"- Initial Target: {self.current_target}")
summary.append(f"- Scan Status: {self.status.capitalize()}")
summary.append(f"- Analysis Depth: {self.max_depth}")
summary.append(f"- Total Indicators Found: {len(nodes)}")
summary.append(f"- Total Relationships Discovered: {len(edges)}")
# Key Findings
summary.append("\n## Key Findings")
domains = [n for n in nodes if n['type'] == 'domain']
ips = [n for n in nodes if n['type'] == 'ip']
isps = [n for n in nodes if n['type'] == 'isp']
cas = [n for n in nodes if n['type'] == 'ca']
summary.append(f"- Discovered {len(domains)} unique domain(s).")
summary.append(f"- Identified {len(ips)} unique IP address(es).")
if isps:
summary.append(f"- Infrastructure is hosted across {len(isps)} unique ISP(s).")
if cas:
summary.append(f"- Found certificates issued by {len(cas)} unique Certificate Authorit(y/ies).")
# Detailed Findings
summary.append("\n## Detailed Findings")
# Domain Analysis
if domains:
summary.append("\n### Domain Analysis")
for domain in domains[:5]: # report on first 5
summary.append(f"\n- Domain: {domain['id']}")
# Associated IPs
associated_ips = [edge['to'] for edge in edges if edge['from'] == domain['id'] and _is_valid_ip(edge['to'])]
if associated_ips:
summary.append(f" - Associated IPs: {', '.join(associated_ips)}")
# Certificate info
cert_attributes = [attr for attr in domain.get('attributes', []) if attr.get('name', '').startswith('cert_')]
if cert_attributes:
issuer = next((attr['value'] for attr in cert_attributes if attr['name'] == 'cert_issuer_name'), 'N/A')
valid_until = next((attr['value'] for attr in cert_attributes if attr['name'] == 'cert_not_after'), 'N/A')
summary.append(f" - Certificate Issuer: {issuer}")
summary.append(f" - Certificate Valid Until: {valid_until}")
# IP Address Analysis
if ips:
summary.append("\n### IP Address Analysis")
for ip in ips[:5]: # report on first 5
summary.append(f"\n- IP Address: {ip['id']}")
# Hostnames
hostnames = [edge['to'] for edge in edges if edge['from'] == ip['id'] and _is_valid_domain(edge['to'])]
if hostnames:
summary.append(f" - Associated Hostnames: {', '.join(hostnames)}")
# ISP
isp_edge = next((edge for edge in edges if edge['from'] == ip['id'] and self.graph.graph.nodes[edge['to']]['type'] == 'isp'), None)
if isp_edge:
summary.append(f" - ISP: {isp_edge['to']}")
# Data Sources
summary.append("\n## Data Sources")
provider_stats = self.logger.get_forensic_summary().get('provider_statistics', {})
for provider, stats in provider_stats.items():
summary.append(f"- {provider.capitalize()}: {stats.get('relationships_discovered', 0)} relationships from {stats.get('successful_requests', 0)} requests.")
summary.append("\n" + "="*40)
summary.append("End of Report")
return "\n".join(summary)
def get_provider_info(self) -> Dict[str, Dict[str, Any]]:
info = {}
provider_dir = os.path.join(os.path.dirname(__file__), '..', 'providers')