
Платформа OSINT-расследований на основе графов с анализом временной шкалы, управлением сущностями и преобразованиями на базе ИИ для выявления скрытых связей между электронными письмами, именами пользователей, изображениями и местоположениями.

PANO — это мощная OSINT-платформа для расследований, которая сочетает визуализацию графов, анализ временных шкал и инструменты с ИИ, помогающие выявлять скрытые связи и закономерности в ваших данных.
Начало работы • Возможности • Документация • Участие
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
Клонируйте репозиторий:
git clone https://github.com/ALW1EZ/PANO.git
cd PANO
Запустите приложение:
./start_pano.shstart_pano.batСценарий запуска автоматически:
Чтобы использовать трансформацию Email Lookup, необходимо сначала войти в GHunt. После запуска PANO через стартовые сценарии:
source venv/bin/activatecall venv\Scripts\activateИнтерактивная визуализация графов
Анализ временных шкал
Интеграция карт
Анализ электронной почты
Анализ имён пользователей
Анализ изображений
Сущности — это фундаментальные строительные блоки PANO. Они представляют собой отдельные фрагменты информации, которые можно связывать и анализировать:
Встроенные типы
Система свойств
Трансформации — это автоматизированные операции, которые обрабатывают сущности для обнаружения новой информации и взаимосвязей:
Типы операций
Возможности
Помощники — это специализированные инструменты с собственными интерфейсами для конкретных задач расследования:
Доступные помощники
Возможности помощников
Мы приветствуем contributions! Чтобы внести вклад в PANO:
Примечание: Мы используем единственную ветку
mainдля разработки. Все pull request'ы должны направляться непосредственно вmain.
Сущности — это основные структуры данных в PANO. Каждая сущность представляет собой фрагмент информации с определёнными свойствами и поведением. Чтобы создать пользовательскую сущность:
entities (например, 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] = "Номер телефона"
description: ClassVar[str] = "Сущность номера телефона с кодом страны и валидацией"
def init_properties(self):
"""Инициализация свойств номера телефона"""
self.setup_properties({
"number": str,
"country_code": str,
"carrier": str,
"type": str, # mobile, landline, etc.
"verified": bool
})
def update_label(self):
"""Обновление отображаемой метки"""
self.label = self.format_label(["country_code", "number"])
Этот проект лицензирован под Creative Commons Attribution-NonCommercial (CC BY-NC).
Вы можете:
При соблюдении следующих условий:
Особая благодарность всем авторам библиотек и участникам, сделавшим этот проект возможным.
Создано ALW1EZ с ❤️ от ИИ
Трансформации — это операции, которые обрабатывают сущности и генерируют новые инсайты или связи. Чтобы создать пользовательскую трансформацию:
transforms (например, 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] = "Поиск номера телефона"
description: ClassVar[str] = "Поиск деталей и местоположения номера телефона"
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("Поиск телефона")
try:
# Здесь ваша логика поиска номера телефона
# Пример: запрос к API для получения деталей номера
location = Location(properties={
"country": "Пример страны",
"region": "Пример региона",
"carrier": "Пример оператора",
"source": "Трансформация PhoneLookup"
})
return [location]
except Exception as e:
status.set_text(f"Ошибка при поиске телефона: {str(e)}")
return []
finally:
status.stop_loading(operation_id)
Помощники — это специализированные инструменты, предоставляющие дополнительные возможности расследования через собственный интерфейс. Чтобы создать пользовательского помощника:
helpers (например, 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):
"""Тестовый помощник"""
name = "Тестовый помощник"
description = "Тестовый помощник"
def setup_ui(self):
"""Инициализация пользовательского интерфейса помощника"""
# Создание области ввода текста
self.input_label = QLabel("Ввод:")
self.input_text = QTextEdit()
self.input_text.setPlaceholderText("Введите текст для обработки...")
self.input_text.setMinimumHeight(100)
# Создание селектора операции
operation_layout = QHBoxLayout()
self.operation_label = QLabel("Операция:")
self.operation_combo = QComboBox()
self.operation_combo.addItems(["Верхний регистр", "Нижний регистр", "С заглавной буквы"])
operation_layout.addWidget(self.operation_label)
operation_layout.addWidget(self.operation_combo)
# Создание кнопки обработки
self.process_btn = QPushButton("Обработать")
self.process_btn.clicked.connect(self.process_text)
# Создание области вывода текста
self.output_label = QLabel("Вывод:")
self.output_text = QTextEdit()
self.output_text.setReadOnly(True)
self.output_text.setMinimumHeight(100)
# Добавление виджетов в основной макет
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)
# Установка размера диалога
self.resize(400, 500)
@asyncSlot()
async def process_text(self):
"""Обработка введённого текста в зависимости от выбранной операции"""
text = self.input_text.toPlainText()
operation = self.operation_combo.currentText()
if operation == "Верхний регистр":
result = text.upper()
elif operation == "Нижний регистр":
result = text.lower()
else: # С заглавной буквы
result = text.title()
self.output_text.setPlainText(result)