
Plataforma de investigação OSINT baseada em grafos com análise de linha do tempo, gestão de entidades e transformações alimentadas por IA para descobrir conexões ocultas entre emails, nomes de usuário, imagens e localizações.

PANO é uma plataforma poderosa de investigação OSINT que combina visualização de grafos, análise de linha do tempo e ferramentas baseadas em IA para ajudá-lo a descobrir conexões e padrões ocultos nos seus dados.
Primeiros Passos • Funcionalidades • Documentação • Contribuir
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
Clone o repositório:
git clone https://github.com/ALW1EZ/PANO.git
cd PANO
Execute a aplicação:
./start_pano.shstart_pano.batO script de inicialização automaticamente:
Para usar o transform Email Lookup Você precisa fazer login com o GHunt primeiro. Após iniciar o pano pelos scripts de inicialização;
source venv/bin/activatecall venv\Scripts\activateVisualização Interativa de Grafos
Análise de Linha do Tempo
Integração de Mapa
Análise de Email
Análise de Nome de Usuário
Análise de Imagem
Entidades são os blocos fundamentais do PANO. Elas representam peças distintas de informação que podem ser conectadas e analisadas:
Tipos Embutidos
Sistema de Propriedades
Transforms são operações automatizadas que processam entidades para descobrir novas informações e relacionamentos:
Tipos de Operação
Funcionalidades
Helpers são ferramentas especializadas com interfaces de usuário dedicadas para tarefas específicas de investigação:
Helpers Disponíveis
Funcionalidades dos Helpers
Aceitamos contribuições! Para contribuir com o PANO:
Nota: Usamos um único branch
mainpara desenvolvimento. Todos os pull requests devem ser feitos diretamente paramain.
Entidades são as estruturas de dados principais no PANO. Cada entidade representa uma informação com propriedades e comportamentos específicos. Para criar uma entidade personalizada:
entities (ex.: 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"])
Este projeto está licenciado sob a Licença Creative Commons Attribution-NonCommercial (CC BY-NC).
Você está livre para:
Sob estes termos:
Agradecimentos especiais a todos os autores de bibliotecas e contribuidores que tornaram este projeto possível.
Criado por ALW1EZ com IA ❤️
Transforms são operações que processam entidades e geram novos insights ou relacionamentos. Para criar um transform personalizado:
transforms (ex.: 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)
Helpers são ferramentas especializadas que fornecem capacidades adicionais de investigação através de uma interface de usuário dedicada. Para criar um helper personalizado:
helpers (ex.: 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)