
Plateforme d'enquête OSINT basée sur des graphes avec analyse chronologique, gestion d'entités et transformations basées sur l'IA pour découvrir des connexions cachées entre e-mails, noms d'utilisateur, images et lieux.

PANO est une puissante plateforme d'investigation OSINT qui combine la visualisation de graphes, l'analyse chronologique et des outils alimentés par l'IA pour vous aider à découvrir des connexions et des motifs cachés dans vos données.
Démarrage • Fonctionnalités • Documentation • Contribuer
https://github.com/user-attachments/assets/6b95e97a-ffdd-4056-b12b-f268d8e5d565
https://github.com/user-attachments/assets/af0c0f65-7b79-417c-a678-a789d42a6003
https://github.com/user-attachments/assets/568b4c28-be78-4559-a607-899fca2f9613
https://github.com/user-attachments/assets/6aa191eb-09de-41d5-b96f-4a2e32d6a0c2
https://github.com/user-attachments/assets/96377b80-e137-4eb4-9387-a0db4e49c2c1
https://github.com/user-attachments/assets/4228bda0-6c13-4ea9-bc07-d87abe367e10
Clonez le dépôt :
git clone https://github.com/ALW1EZ/PANO.git
cd PANO
Lancez l'application :
./start_pano.shstart_pano.batLe script de démarrage va automatiquement :
Pour utiliser la transformation Email Lookup, vous devez d'abord vous connecter avec GHunt. Après avoir lancé PANO via les scripts de démarrage ;
source venv/bin/activatecall venv\Scripts\activateVisualisation interactive de graphes
Analyse chronologique
Intégration cartographique
Analyse d'email
Analyse de nom d'utilisateur
Analyse d'image
Les entités sont les éléments de base de PANO. Elles représentent des informations distinctes qui peuvent être connectées et analysées :
Types intégrés
Système de propriétés
Les transformations sont des opérations automatisées qui traitent les entités pour découvrir de nouvelles informations et relations :
Types d'opérations
Fonctionnalités
Les aides sont des outils spécialisés avec des interfaces utilisateur dédiées pour des tâches d'investigation spécifiques :
Aides disponibles
Fonctionnalités des aides
Nous accueillons les contributions ! Pour contribuer à PANO :
Note : Nous utilisons une seule branche
mainpour le développement. Toutes les pull requests doivent être faites directement surmain.
Les entités sont les structures de données fondamentales dans PANO. Chaque entité représente une information avec des propriétés et comportements spécifiques. Pour créer une entité personnalisée :
entities (par exemple, entities/phone_number.py)from dataclasses import dataclass
from typing import ClassVar, Dict, Any
from .base import Entity
@dataclass
class PhoneNumber(Entity):
name: ClassVar[str] = "Phone Number"
description: ClassVar[str] = "A phone number entity with country code and validation"
def init_properties(self):
"""Initialize phone number properties"""
self.setup_properties({
"number": str,
"country_code": str,
"carrier": str,
"type": str, # mobile, landline, etc.
"verified": bool
})
def update_label(self):
"""Update the display label"""
self.label = self.format_label(["country_code", "number"])
Ce projet est sous licence Creative Commons Attribution - Pas d'Utilisation Commerciale (CC BY-NC).
Vous êtes libre de :
Selon les conditions suivantes :
Remerciements particuliers à tous les auteurs de bibliothèques et contributeurs qui ont rendu ce projet possible.
Créé par ALW1EZ avec IA ❤️
Les transformations sont des opérations qui traitent les entités et génèrent de nouvelles informations ou relations. Pour créer une transformation personnalisée :
transforms (par exemple, transforms/phone_lookup.py)from dataclasses import dataclass
from typing import ClassVar, List
from .base import Transform
from entities.base import Entity
from entities.phone_number import PhoneNumber
from entities.location import Location
from ui.managers.status_manager import StatusManager
@dataclass
class PhoneLookup(Transform):
name: ClassVar[str] = "Phone Number Lookup"
description: ClassVar[str] = "Lookup phone number details and location"
input_types: ClassVar[List[str]] = ["PhoneNumber"]
output_types: ClassVar[List[str]] = ["Location"]
async def run(self, entity: PhoneNumber, graph) -> List[Entity]:
if not isinstance(entity, PhoneNumber):
return []
status = StatusManager.get()
operation_id = status.start_loading("Phone Lookup")
try:
# Your phone number lookup logic here
# Example: query an API for phone number details
location = Location(properties={
"country": "Example Country",
"region": "Example Region",
"carrier": "Example Carrier",
"source": "PhoneLookup transform"
})
return [location]
except Exception as e:
status.set_text(f"Error during phone lookup: {str(e)}")
return []
finally:
status.stop_loading(operation_id)
Les aides sont des outils spécialisés qui offrent des capacités d'investigation supplémentaires via une interface utilisateur dédiée. Pour créer une aide personnalisée :
helpers (par exemple, helpers/data_analyzer.py)from PySide6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
QTextEdit, QLabel, QComboBox
)
from .base import BaseHelper
from qasync import asyncSlot
class DummyHelper(BaseHelper):
"""A dummy helper for testing"""
name = "Dummy Helper"
description = "A dummy helper for testing"
def setup_ui(self):
"""Initialize the helper's user interface"""
# Create input text area
self.input_label = QLabel("Input:")
self.input_text = QTextEdit()
self.input_text.setPlaceholderText("Enter text to process...")
self.input_text.setMinimumHeight(100)
# Create operation selector
operation_layout = QHBoxLayout()
self.operation_label = QLabel("Operation:")
self.operation_combo = QComboBox()
self.operation_combo.addItems(["Uppercase", "Lowercase", "Title Case"])
operation_layout.addWidget(self.operation_label)
operation_layout.addWidget(self.operation_combo)
# Create process button
self.process_btn = QPushButton("Process")
self.process_btn.clicked.connect(self.process_text)
# Create output text area
self.output_label = QLabel("Output:")
self.output_text = QTextEdit()
self.output_text.setReadOnly(True)
self.output_text.setMinimumHeight(100)
# Add widgets to main layout
self.main_layout.addWidget(self.input_label)
self.main_layout.addWidget(self.input_text)
self.main_layout.addLayout(operation_layout)
self.main_layout.addWidget(self.process_btn)
self.main_layout.addWidget(self.output_label)
self.main_layout.addWidget(self.output_text)
# Set dialog size
self.resize(400, 500)
@asyncSlot()
async def process_text(self):
"""Process the input text based on selected operation"""
text = self.input_text.toPlainText()
operation = self.operation_combo.currentText()
if operation == "Uppercase":
result = text.upper()
elif operation == "Lowercase":
result = text.lower()
else: # Title Case
result = text.title()
self.output_text.setPlainText(result)