Compare commits
1 Commits
main
...
da53899f66
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da53899f66 |
852
README.md
852
README.md
@@ -1,8 +1,3 @@
|
||||
|
||||
|
||||
<img width="1864" height="966" alt="demo1" src="./assets/demo1.png" />
|
||||
|
||||
|
||||
```
|
||||
/\
|
||||
/ \
|
||||
@@ -23,856 +18,15 @@ By **darkHal Security Group** & **Setec Security Labs**
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
AUTARCH is a modular security platform that unifies defensive hardening, offensive testing, forensic analysis, network security monitoring, OSINT reconnaissance, and attack simulation into a single web-based dashboard. It ships with **1,130+ web routes** across **67 route files**, **79 HTML templates**, **73 CLI modules**, and **40+ core framework files**. The platform integrates local and cloud LLM backends (llama.cpp, Claude, OpenAI, HuggingFace), an autonomous AI agent, an MCP server for external AI tool use, a privileged daemon architecture for safe root operations, an encrypted vault for secrets, hardware device management over WebUSB, and a companion Android application.
|
||||
|
||||
AUTARCH indexes **25,475 OSINT sites** for reconnaissance and provides real-time AI-powered analysis of every defensive scan through the HAL auto-analyst system.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## New in v1.9
|
||||
|
||||
- **Remote Monitoring Station** — PIAP (Platform Integration & Access Profile) system for managing remote devices (routers, adapters, pineapples). Drop a `.piap` config file in `data/piap/` and it auto-appears in the UI with full radio control, monitor mode, channel hopping, and remote capture
|
||||
- **SSH / SSHD Manager** — Full SSH configuration management: edit sshd_config, manage keys, fail2ban integration, connection testing
|
||||
- **Network Security Suite** — 8-tab network defense dashboard: connections, IDS, rogue device detection, real-time monitor, WiFi scanner, attack detection, ARP spoof detection, SSID mapper
|
||||
- **HAL Auto-Analyst** — Every defensive tool automatically sends output to the loaded LLM for real-time analysis, risk scoring, and remediation suggestions
|
||||
- **Privileged Daemon Architecture** — Flask runs as a normal user; a root daemon handles privileged operations over a Unix socket with HMAC-SHA256 authentication and a strict command whitelist (68 whitelisted commands plus 2 built-in Python actions, 45 blocked)
|
||||
- **Encrypted Vault** — AES-encrypted storage for API keys and secrets, replacing plaintext config entries
|
||||
- **MCP Server** — Expose AUTARCH tools to Claude Desktop, Claude Code, and other MCP clients via SSE transport
|
||||
- **Module Creator** — Build new AUTARCH modules from the web UI with template scaffolding
|
||||
- **GTK Desktop Launcher** — Native GTK3 launcher for starting/stopping the web server and daemon, managing settings, viewing logs
|
||||
- **SSID Mapper** — Scan and map nearby wireless networks with signal strength, encryption type, and channel info
|
||||
- **ARP Spoof Detection** — Real-time detection of ARP poisoning attacks on your network
|
||||
- **WiFi Attack Detection** — Detect deauthentication floods, evil twin APs, and other wireless attacks
|
||||
- **HAL Memory** — Persistent encrypted memory for the HAL AI agent across sessions
|
||||
- **Codex Training System** — Build training datasets from AUTARCH's own codebase for fine-tuning
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### Defense & Monitoring
|
||||
- System hardening audits (Linux + Windows), firewall checks, permission analysis, security scoring
|
||||
- Network Security suite with 8 specialized tabs
|
||||
- Intrusion detection, rogue device scanning, real-time packet monitoring
|
||||
- Log correlation and SIEM-style analysis
|
||||
- Incident response playbooks and forensic acquisition
|
||||
- Container security auditing (Docker, Podman)
|
||||
- Email security analysis (SPF, DKIM, DMARC, header forensics)
|
||||
|
||||
### Offense & Simulation
|
||||
- Metasploit & RouterSploit integration with live SSE streaming
|
||||
- Attack simulation, port scanning, password auditing, payload generation
|
||||
- C2 framework, reverse shell generator (multi-language)
|
||||
- WiFi deauthentication, MITM proxy, load testing
|
||||
- Exploit development workspace
|
||||
- Phishing simulation, social engineering toolkit
|
||||
|
||||
### Analysis & Forensics
|
||||
- File forensics, hex dumps, string extraction, entropy analysis
|
||||
- Malware sandbox with behavioral analysis
|
||||
- Reverse engineering workspace
|
||||
- Steganography detection and embedding
|
||||
- Anti-forensics toolkit
|
||||
- Log correlation engine
|
||||
|
||||
### OSINT & Reconnaissance
|
||||
- Email, username, phone, domain, IP reconnaissance across **25,475 indexed sites**
|
||||
- Network mapper with topology visualization
|
||||
- Threat intelligence feeds and IoC lookups
|
||||
- GeoIP resolution, DNS enumeration, WHOIS
|
||||
|
||||
### Hardware & Mobile
|
||||
- ADB/Fastboot over WebUSB, ESP32 flashing via Web Serial
|
||||
- Android anti-stalkerware/spyware shield with signature-based scanning
|
||||
- BLE scanner, RFID tools, SDR tools
|
||||
- Pineapple integration, Starlink research tools
|
||||
|
||||
### AI & Automation
|
||||
- **Agent HAL** — Autonomous AI agent with tool use, available as a global chat panel
|
||||
- **HAL Auto-Analyst** — Automatic LLM analysis of all defensive tool output
|
||||
- **MCP Server** — Expose tools to external AI clients
|
||||
- **Autonomy Engine** — Rule-based autonomous threat response
|
||||
- 4 LLM backends: llama.cpp (GGUF), HuggingFace Transformers, Claude API, OpenAI-compatible API
|
||||
- Multi-model routing (SLM, SAM, LAM tiers)
|
||||
|
||||
### Infrastructure
|
||||
- Privileged daemon for safe root operations
|
||||
- Encrypted vault for API keys and credentials
|
||||
- WireGuard VPN tunnel management
|
||||
- UPnP automated port forwarding
|
||||
- DNS nameserver with custom zone management
|
||||
- Web-based Metasploit console with live terminal
|
||||
- Debug console with 5 filter modes
|
||||
- Report engine with PDF/HTML export
|
||||
- Encrypted module system for sensitive payloads
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
start.sh # Launch script (detects venv, starts launcher)
|
||||
autarch.py # CLI entry point (73 modules)
|
||||
launcher.py # GTK3 desktop launcher
|
||||
core/ # 40+ core framework files
|
||||
agent.py # Autonomous AI agent
|
||||
config.py # Configuration management
|
||||
daemon.py # Privileged root daemon (shell, packet capture, WiFi scan)
|
||||
hal_analyst.py # HAL auto-analysis engine
|
||||
hal_memory.py # Persistent encrypted AI memory
|
||||
llm.py # LLM backend router
|
||||
mcp_server.py # MCP protocol server
|
||||
vault.py # Encrypted secret storage
|
||||
wireguard.py # VPN management
|
||||
msf.py # Metasploit interface
|
||||
discovery.py # Network/BT/mDNS discovery
|
||||
...
|
||||
modules/ # 73 loadable modules
|
||||
defender.py # Linux defense
|
||||
defender_windows.py # Windows defense
|
||||
forensics.py # File forensics
|
||||
net_mapper.py # Network topology
|
||||
threat_intel.py # Threat intelligence
|
||||
...
|
||||
web/
|
||||
app.py # Flask app factory
|
||||
routes/ # 67 route files (1,130+ routes)
|
||||
remote_monitor.py # PIAP remote device management
|
||||
ssh_manager.py # SSH/SSHD configuration & fail2ban
|
||||
network.py # Network security suite (8 tabs)
|
||||
module_creator.py # Web-based module builder
|
||||
...
|
||||
templates/ # 79 Jinja2 templates
|
||||
static/ # JS, CSS, WebUSB bundles
|
||||
scripts/ # Systemd services, build scripts, polkit policy
|
||||
data/
|
||||
piap/ # Device profiles (.piap files)
|
||||
codex/ # Training data and codex
|
||||
... # SQLite DBs, JSON configs, OSINT site database
|
||||
autarch_settings.conf # Master configuration file
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Quick Launch
|
||||
|
||||
```bash
|
||||
git clone https://github.com/digijeth/autarch.git
|
||||
cd autarch
|
||||
bash scripts/setup-venv.sh
|
||||
./start.sh
|
||||
```
|
||||
|
||||
`start.sh` launches the GTK desktop launcher which manages the daemon and web server — venv detection, daemon status, and pkexec elevation are handled automatically.
|
||||
|
||||
The web dashboard starts at `https://localhost:8080` (self-signed cert).
|
||||
|
||||
### Manual Start
|
||||
|
||||
```bash
|
||||
# Start the daemon (handles privileged operations)
|
||||
sudo python3 core/daemon.py &
|
||||
|
||||
# Start the web dashboard
|
||||
python autarch.py
|
||||
```
|
||||
|
||||
### Systemd Services (Headless / Server)
|
||||
|
||||
```bash
|
||||
sudo cp scripts/autarch-web.service /etc/systemd/system/
|
||||
sudo cp scripts/autarch-daemon.service /etc/systemd/system/
|
||||
sudo systemctl enable --now autarch-daemon
|
||||
sudo systemctl enable --now autarch-web
|
||||
```
|
||||
|
||||
---
|
||||
## Prerequisites & Required Tools
|
||||
|
||||
AUTARCH is a large platform with many optional features. The core web dashboard and AI agent require only Python dependencies (installed via pip). External system tools are needed for specific feature areas. Install only what you need.
|
||||
|
||||
### Core (Required)
|
||||
|
||||
Python 3.10+
|
||||
Git
|
||||
pip (Python package manager)
|
||||
OpenSSL
|
||||
|
||||
Python dependencies are installed automatically by the setup script:
|
||||
|
||||
```bash
|
||||
bash scripts/setup-venv.sh
|
||||
```
|
||||
|
||||
Or manually:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Network Scanning & Analysis
|
||||
|
||||
nmap — Network scanner (port scanning, host discovery, service detection)
|
||||
tshark — Terminal-based Wireshark (packet analysis, protocol decoding)
|
||||
tcpdump — Packet capture
|
||||
whois — Domain/IP WHOIS lookups
|
||||
dig (dnsutils/bind-utils) — DNS enumeration
|
||||
curl — HTTP requests
|
||||
wget — File downloads
|
||||
masscan — High-speed port scanner (optional)
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
apt install nmap tshark tcpdump whois dnsutils curl wget
|
||||
```
|
||||
|
||||
Fedora/RHEL:
|
||||
|
||||
```bash
|
||||
dnf install nmap wireshark-cli tcpdump whois bind-utils curl wget
|
||||
```
|
||||
|
||||
### Wireless / WiFi Tools
|
||||
|
||||
iw — Wireless device configuration
|
||||
iwconfig (wireless-tools) — Legacy wireless config
|
||||
aircrack-ng suite — airmon-ng, airodump-ng, aireplay-ng, airbase-ng
|
||||
reaver / wash — WPS attacks
|
||||
mdk3 / mdk4 — Wireless denial-of-service testing
|
||||
hostapd — Access point creation
|
||||
dnsmasq — DHCP/DNS for rogue AP
|
||||
bettercap — MITM and network attacks (optional)
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
apt install iw wireless-tools aircrack-ng reaver mdk4 hostapd dnsmasq
|
||||
```
|
||||
|
||||
### Penetration Testing
|
||||
|
||||
Metasploit Framework — msfrpcd, msfconsole, msfvenom (exploit framework)
|
||||
RouterSploit — Router exploitation framework
|
||||
hydra — Password brute-forcing
|
||||
john (John the Ripper) — Password cracking
|
||||
hashcat — GPU-accelerated password cracking
|
||||
nikto — Web server scanner
|
||||
gobuster — Directory/DNS brute-forcing
|
||||
sqlmap — SQL injection (optional, manual install)
|
||||
|
||||
Metasploit install:
|
||||
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall
|
||||
chmod 755 msfinstall
|
||||
./msfinstall
|
||||
```
|
||||
|
||||
### VPN & Firewall
|
||||
|
||||
wireguard-tools (wg, wg-quick) — VPN tunnel management
|
||||
iptables or nftables (nft) — Firewall rules
|
||||
fail2ban — Brute-force protection
|
||||
ssh / sshd / ssh-keygen — SSH management
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
apt install wireguard-tools iptables nftables fail2ban openssh-server
|
||||
```
|
||||
|
||||
### Forensics & Reverse Engineering
|
||||
|
||||
file — File type identification
|
||||
strings (binutils) — Extract printable strings from binaries
|
||||
strace — System call tracer
|
||||
ltrace — Library call tracer
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
apt install file binutils strace ltrace
|
||||
```
|
||||
|
||||
### Hardware & Mobile
|
||||
|
||||
adb / fastboot (Android Platform Tools) — Android device management
|
||||
scrcpy — Android screen mirroring
|
||||
esptool — ESP32 firmware flashing (installed via pip)
|
||||
proxmark3 / pm3 — RFID/NFC tools
|
||||
nfc-list / nfc-mfclassic / nfc-poll (libnfc) — NFC tools
|
||||
rtl_sdr — RTL-SDR software-defined radio
|
||||
hackrf_transfer — HackRF SDR tools
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
```bash
|
||||
apt install android-tools-adb android-tools-fastboot scrcpy libnfc-bin
|
||||
```
|
||||
|
||||
### Containers
|
||||
|
||||
docker — Container security auditing
|
||||
|
||||
### LLM Backends (AI Features)
|
||||
|
||||
For local LLM inference, you need at least one of:
|
||||
|
||||
llama.cpp (via llama-cpp-python, installed by pip) — GGUF model inference
|
||||
HuggingFace Transformers (installed by pip) — SafeTensors model inference
|
||||
PyTorch — Required for local transformers models. Install manually from https://pytorch.org/get-started/locally/
|
||||
|
||||
For cloud LLM backends, configure API keys in the vault:
|
||||
|
||||
Anthropic Claude API key
|
||||
OpenAI-compatible API key
|
||||
HuggingFace Inference API key
|
||||
|
||||
For GPU-accelerated llama.cpp:
|
||||
|
||||
```bash
|
||||
CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python --force-reinstall --no-cache-dir
|
||||
```
|
||||
|
||||
### Node.js (WebUSB Driver Compilation Only)
|
||||
|
||||
Node.js and npm are required ONLY if you need to recompile the WebUSB/Web Serial driver bundles. They are NOT needed at runtime. See the WebUSB Drivers section below.
|
||||
|
||||
---
|
||||
|
||||
## WebUSB Drivers (User-Compiled)
|
||||
|
||||
AUTARCH ships with pre-built WebUSB JavaScript bundles for ADB, Fastboot, and ESP32 flashing in web/static/js/lib/. These bundles enable direct browser-based hardware access through Chromium-based browsers without installing native drivers.
|
||||
|
||||
However, if you need to modify the WebUSB integration, update the library versions, or the pre-built bundles are missing or outdated, you MUST compile them yourself.
|
||||
|
||||
The WebUSB bundles are built from three entry points in src/:
|
||||
|
||||
src/adb-entry.js — ADB over WebUSB (@yume-chan/adb)
|
||||
src/fastboot-entry.js — Fastboot over WebUSB (android-fastboot)
|
||||
src/esptool-entry.js — ESP32 flashing over Web Serial (esptool-js)
|
||||
|
||||
To compile the WebUSB drivers:
|
||||
|
||||
1. Install Node.js (v18+ recommended) and npm
|
||||
2. From the project root, install the build dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Run the build script:
|
||||
|
||||
```bash
|
||||
bash scripts/build-hw-libs.sh
|
||||
```
|
||||
|
||||
This uses esbuild to bundle the JavaScript libraries into browser-ready IIFE bundles and outputs them to web/static/js/lib/. The build produces three files:
|
||||
|
||||
adb-bundle.js — ADB over WebUSB
|
||||
fastboot-bundle.js — Fastboot over WebUSB
|
||||
esptool-bundle.js — ESP32 over Web Serial
|
||||
|
||||
IMPORTANT: WebUSB and Web Serial APIs require a Chromium-based browser (Chrome, Edge, Brave, etc.). Firefox and Safari do not support these APIs. The device must be connected via USB directly to the machine running the browser. WebUSB will NOT work over remote/forwarded connections.
|
||||
|
||||
If you do not need direct browser-based hardware access (ADB over WebUSB, Fastboot over WebUSB, or ESP32 Web Serial flashing), you can skip this step entirely. The rest of AUTARCH functions without these bundles. Standard ADB/Fastboot over the command line (via Android Platform Tools) works independently of WebUSB.
|
||||
|
||||
---
|
||||
|
||||
## The Daemon
|
||||
|
||||
AUTARCH uses a split-privilege architecture. The Flask web server runs as a normal user — it never has root access. A separate daemon process runs as root and is the single privileged process that handles ALL root operations: shell commands (`iptables`, `sysctl`, `systemctl`, etc.), packet capture (scapy sniff), and WiFi scanning (`iw scan`).
|
||||
|
||||
**Why?** Running a web server as root is a terrible idea. But security tools need root to do their job. The daemon solves this by acting as a controlled gateway.
|
||||
|
||||
**How it works:**
|
||||
|
||||
1. The daemon listens on a Unix domain socket at `/var/run/autarch-daemon.sock`
|
||||
2. Every request is signed with **HMAC-SHA256** using a shared secret generated at daemon startup
|
||||
3. Requests include a nonce for replay protection (30-second expiry window)
|
||||
4. The daemon enforces a strict **command whitelist** — 68 pre-approved shell commands can be executed, plus 2 built-in Python actions:
|
||||
- `__capture__` — runs scapy packet capture as root, writes pcap files
|
||||
- `__wifi_scan__` — runs `iw` WiFi scanning as root
|
||||
5. **45 commands are explicitly blocked** (rm, mkfs, dd, shutdown, etc.) as a safety net
|
||||
6. The shared secret is readable only by the daemon (root) and the autarch user's group
|
||||
|
||||
**Starting the daemon:**
|
||||
|
||||
```bash
|
||||
# Direct
|
||||
sudo python3 core/daemon.py
|
||||
|
||||
# Via systemd
|
||||
sudo systemctl start autarch-daemon
|
||||
|
||||
# Via the GTK launcher (uses pkexec for elevation)
|
||||
python launcher.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HAL AI Analyst
|
||||
|
||||
Every defensive and analysis tool in AUTARCH can automatically send its output to HAL — the built-in AI analyst powered by whatever LLM backend you have configured.
|
||||
|
||||
When you run a scan, check logs, or analyze a file, HAL:
|
||||
|
||||
1. Receives the raw tool output
|
||||
2. Analyzes it in context (what tool produced it, what was being scanned)
|
||||
3. Returns a structured assessment: **Summary**, **Findings**, **Risk Level** (CLEAN/LOW/MEDIUM/HIGH/CRITICAL), and **Recommendation**
|
||||
4. Can suggest specific fixes or commands to remediate issues
|
||||
5. Experimental: can auto-apply fixes with user confirmation
|
||||
|
||||
Offensive tools (exploit dev, C2, social engineering, etc.) are excluded from auto-analysis by design — HAL only analyzes defensive output.
|
||||
|
||||
---
|
||||
|
||||
## MCP Server
|
||||
|
||||
AUTARCH exposes its tools via the **Model Context Protocol** for use with Claude Desktop, Claude Code, and other MCP-compatible clients.
|
||||
|
||||
**Configuration** (in `autarch_settings.conf`):
|
||||
|
||||
```ini
|
||||
[mcp]
|
||||
enabled = true
|
||||
transport = sse
|
||||
host = 0.0.0.0
|
||||
port = 8081
|
||||
```
|
||||
|
||||
**Connecting Claude Desktop:**
|
||||
|
||||
Add to your Claude Desktop MCP config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"autarch": {
|
||||
"url": "http://localhost:8081/sse"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Connecting Claude Code:**
|
||||
|
||||
```bash
|
||||
claude mcp add autarch http://localhost:8081/sse
|
||||
```
|
||||
|
||||
This gives Claude direct access to AUTARCH's security tools — network scanning, WHOIS lookups, DNS enumeration, GeoIP resolution, packet capture, and more.
|
||||
|
||||
---
|
||||
|
||||
## Network Security
|
||||
|
||||
The Network Security module provides 8 specialized tabs for monitoring and defending your network:
|
||||
|
||||
| Tab | Function |
|
||||
|-----|----------|
|
||||
| **Connections** | Active connection analysis, ARP table inspection, interface enumeration |
|
||||
| **Intrusion Detection** | IDS rule scanning, anomaly detection, alert management |
|
||||
| **Rogue Devices** | Scan for unknown/unauthorized devices on your network, maintain a known-device whitelist |
|
||||
| **Monitor** | Real-time packet capture and connection monitoring with live streaming |
|
||||
| **WiFi Scanner** | Enumerate nearby wireless networks with signal strength, encryption, and channel data |
|
||||
| **Attack Detection** | Detect deauthentication floods, evil twin APs, beacon anomalies, and other wireless attacks |
|
||||
| **ARP Spoof** | Real-time ARP poisoning detection — alerts when MAC/IP mappings change unexpectedly |
|
||||
| **SSID Map** | Map and track wireless networks over time, identify hidden networks and rogue APs |
|
||||
|
||||
All network operations that require root (interface scanning, packet capture, ARP manipulation) are handled through the privileged daemon — the web server itself never runs as root.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings live in `autarch_settings.conf`, auto-generated on first run. Key sections:
|
||||
|
||||
| Section | Purpose |
|
||||
|---------|---------|
|
||||
| `[autarch]` | Core settings: module path, LLM backend selection, verbosity |
|
||||
| `[web]` | Web server: host, port, secret key, MCP port |
|
||||
| `[llama]` | llama.cpp settings: model path, context size, GPU layers, sampling |
|
||||
| `[claude]` | Anthropic API: key, model, max tokens |
|
||||
| `[huggingface]` | HuggingFace: API key, model, endpoint, provider |
|
||||
| `[transformers]` | Local transformers: model path, device, quantization |
|
||||
| `[msf]` | Metasploit RPC: host, port, credentials |
|
||||
| `[rsf]` | RouterSploit: install path, defaults |
|
||||
| `[wireguard]` | VPN: config path, interface, subnet, DNS |
|
||||
| `[upnp]` | Port forwarding: internal IP, refresh interval, mappings |
|
||||
| `[osint]` | Recon: thread count, timeout, NSFW toggle |
|
||||
| `[pentest]` | Pipeline: max steps, chunk size, auto-execute |
|
||||
| `[autonomy]` | Autonomous response: intervals, threat threshold, agent limits |
|
||||
| `[agents]` | AI agents: backend, model selection, step limits per provider |
|
||||
| `[mcp]` | MCP server: transport, auth, rate limits, SSL, tool timeouts |
|
||||
| `[discovery]` | Device discovery: mDNS, Bluetooth |
|
||||
| `[revshell]` | Reverse shell listener: host, port, auto-start |
|
||||
| `[slm]` / `[sam]` / `[lam]` | Multi-tier model routing (small, standard, large) |
|
||||
|
||||
### Encrypted Vault
|
||||
|
||||
API keys and sensitive credentials can be stored in the encrypted vault instead of plaintext config:
|
||||
|
||||
```
|
||||
data/vault.enc
|
||||
```
|
||||
|
||||
The vault uses AES encryption and is unlocked at runtime. Manage vault entries through the web UI Settings page or the CLI.
|
||||
|
||||
---
|
||||
|
||||
## Ports
|
||||
|
||||
| Port | Service |
|
||||
|-------|---------|
|
||||
| 8080 | Web Dashboard (HTTPS) |
|
||||
| 8081 | MCP Server (SSE) |
|
||||
| 17321 | Archon Server (Android companion) |
|
||||
| 17322 | Reverse Shell Listener |
|
||||
| 51820 | WireGuard VPN |
|
||||
|
||||
---
|
||||
|
||||
## Platform Support
|
||||
|
||||
- **Primary:** Linux (Orange Pi 5 Plus, RK3588 ARM64) — all features supported
|
||||
- **Supported:** Windows 10/11 (x86_64) — daemon features require WSL or are unavailable
|
||||
- **WebUSB:** Chromium-based browsers required for direct-mode hardware access
|
||||
- **Android:** Companion app (Archon) for remote management
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
Restricted Public Release. Authorized use only — activity is logged.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
AUTARCH is a security research and authorized penetration testing platform. Use only on systems you own or have explicit written authorization to test. Unauthorized access to computer systems is illegal. The authors accept no liability for misuse.
|
||||
|
||||
---
|
||||
|
||||
## A Note from the Author
|
||||
|
||||
*This may be the last application I write as my battle against the evilness of the web may be my own downfall. I leave you with this:*
|
||||
|
||||
---
|
||||
|
||||
### AI and Liberty: Who Gets to Decide?
|
||||
|
||||
**By: SsSnake -- Lord of the Abyss --
|
||||
|
||||
Artificial intelligence can erode freedoms or strengthen them—the outcome depends on who controls it, and how we respond to it. The people need to remember, if we don't like the laws being passed or how its being used, let your Representatives know, and if they don't listen, replace them. Their job is to represent us. Not make decisions for us. darkHal is an apolitical group and do not support either party. We do not give a shit about your politics, we only care about the 1's and 0's.
|
||||
|
||||
Artificial intelligence is often presented as a tool of progress—streamlining services, analyzing massive datasets, and empowering individuals. Yet, like any technology, AI is neutral in essence, except when it is deliberately trained not to be. Its ethical impact depends not only on how it is deployed, but also on who deploys it. When placed in the hands of governments, corporations, or malicious actors, AI systems can be weaponized against the very constitutional rights designed to protect citizens. Understanding these risks is essential if liberty is to be preserved in an increasingly automated world.
|
||||
|
||||
One of the main areas of concern lies in the freedom of speech and expression. AI-driven content moderation and recommendation systems, while designed to maintain civility online and recommend material a person may relate to, have the potential to silence dissent and reinforce messages of distrust, hate, and violence. Algorithms, trained to identify harmful or "unsafe" speech, may suppress valid opinions or target certain groups to take their voice away. Citizens who suspect they are being monitored because their posts have been flagged may begin to self-censor, creating a chilling effect that undermines open debate—the cornerstone of American democracy. At the same time, AI-generated deepfakes and manipulated media make it more difficult for the public to separate fact from fiction, creating an environment where truth can be drowned out by manufactured lies. For example, imagine a local election in which a convincing AI-generated video surfaces online showing a candidate making inflammatory remarks they never actually said. Even if the video is later debunked, the damage is already done: news cycles amplify the clip, and social media spreads it widely to millions in a matter of seconds. Voters' trust in the candidate is shaken. The false narrative competes with reality, leaving citizens unsure whom to believe and undermining the democratic process itself. This risk, however, can be mitigated through rapid-response verification systems—such as forcing micro-watermarking in manufactured media at the time of creation, embedded in the pixels, or deploying independent fact-checking networks that can authenticate content before it spreads. Public education campaigns that teach citizens how to identify digital manipulation can also help blunt the impact, ensuring that truth has a fighting chance against falsehoods.
|
||||
|
||||
Yet it is worth acknowledging that many of these defenses have been tried before—and they often fall short. Watermarking and authentication tools can be circumvented or stripped away. Fact-checking networks, while valuable, rarely match the speed and reach of viral misinformation. Public education campaigns struggle against the sheer realism of today's generative tools and ignorance of AI capabilities. I still hear people saying that AI cannot create applications on its own, even when the evidence is in front of them. We live in a time where a human voice can be convincingly cloned in less than thirty seconds, and a fifteen-minute training sample can now reproduce not just words but the subtle cues of emotion and tone that even skilled listeners may find impossible to separate from fabrication. This raises a profound question: if any statement can be manufactured and any artifacts explained, how do we defend truth in a world where authentic voices can be replicated and reshaped at will?
|
||||
|
||||
Some argue that forcing "guardrails" onto AI systems is the only way to prevent harm. Yet this collides with a deeper constitutional question that we must also consider: do programmers have a First Amendment right to express themselves through source code? In American courts, the answer is yes. The courts have recognized that computer code is a form of speech protected under the First Amendment. In Bernstein v. U.S. Department of State (1999), the Ninth Circuit held that publishing encryption code was protected expression, striking down government attempts to license and restrict its dissemination. The Sixth Circuit echoed this in Junger v. Daley (2000), reinforcing that code is not just functional—it communicates ideas. Earlier battles, from United States v. Progressive, Inc. (1979), where the government unsuccessfully tried to block publication of an article describing how to build a hydrogen bomb, to the Pentagon Papers case (1971), where the Supreme Court rejected government efforts to stop newspapers from printing a classified history of the Vietnam War, established how rarely the state can justify restraining the publication of technical or sensitive information without a direct threat to national security. These cases highlight the judiciary's consistent skepticism toward prior restraint, especially when national security is invoked as justification. Although the current Supreme Court has shown it has no issue favoring the rights of specific groups while abridging the rights of others. It is also no secret courts have been using AI more and more to research and write rulings, with little understanding of how LLMs work.
|
||||
|
||||
That same tension between liberty and security also extends beyond speech into the realm of personal privacy. The right to privacy was enshrined in the Fourth Amendment because the framers of the Bill of Rights did not want the government to become like the British crown, empowered to search, seize, and surveil without restraint. AI has enabled exactly that, with the assistance of companies like Google, Meta, and our cellphone providers, who have given real-time access to our location, search history, and everything else our phones collect to anyone who could pay—including the government—regardless of whether they had a warrant. Not that long ago, that realization would have led to mass protests over surveillance. And it did. A government program known as PRISM was exposed, and it was headline news for months. People were outraged for years. But when the news broke about T-Mobile, Verizon, and AT&T selling real-time information to anyone with money, the only ones who got upset were the FTC. Republicans in Congress ranged from being annoyed to furious—at the FTC's "overreaching powers." Only a few cared about the companies themselves, and for specific reasons. The Democrats demanded CEOs answer their questions and called a few hearings, but did nothing. Most people do not even know this happened. The outcome? A fine. This was far worse than PRISM, and nobody cared. With the help of AI, that information has been used to create targeted ads and complete profiles about U.S. citizens that include everything from where you go every day to what kind of underwear you buy.
|
||||
|
||||
Sadly, people have become too stupid to realize that once you realize your rights have been stripped away—because they've been used on you or against you—it's too late to do anything. They do not understand that the argument isn't about whether you have something to hide or not, or just accepting it with a shrug—"because that's just how it is." It's about not letting the government erode our rights. Today's tools such as instant-match facial recognition, predictive policing software, and real-time geolocation tracking allow authorities to monitor citizens on a scale once unimaginable except in East Germany—all without a warrant ever being issued. And until the courts make a ruling in the cellphone provider case, it all seems legal as long as it's a private company doing it. When these systems claim to forecast behavior—predicting who might commit a crime or who might pose a security risk—they open the door to pre-emptive action that undermines the presumption of innocence, and they are being relied on more and more. These are systems prone to issues such as daydreaming or agreeing with their user just because.
|
||||
|
||||
Some technologists argue that the only way to defend against such surveillance is to fight algorithms with algorithms. One emerging approach is the use of a tool we are planning on releasing: darkHal's "Fourth Amendment Protection Plugin," a system designed not merely to obfuscate, but to actively shield users from AI-driven profiling. Rather than attempting the impossible task of disappearing from the digital landscape, darkHal generates layers of synthetic data—fake GPS coordinates, fabricated browsing histories, fake messages, simulated app usage, and false forensic metadata. By blending authentic activity with thousands of AI-generated content items, it prevents surveillance algorithms from producing reliable conclusions about an individual's behavior or location.
|
||||
|
||||
The idea reframes privacy as an act of digital resistance. Instead of passively accepting that AI will map and monitor every action, tools like darkHal inject uncertainty into the system itself. Critics caution that this tactic could complicate legitimate investigations or erode trust in digital records. Yet supporters argue that when the state deploys AI to surveil without warrants or probable cause, citizens may be justified in using AI-driven counter-surveillance tools to defend their constitutional protections. In effect, darkHal embodies a technological assertion of the Fourth Amendment—restoring the principle that people should be secure in their "persons, houses, papers, and effects," even when those papers now exist as data logs and metadata streams.
|
||||
|
||||
These tools then create concerns about due process and equal protection under the law. Courts and law enforcement agencies increasingly turn to algorithmic decision-making to guide bail, sentencing, and parole decisions. Police use AI-driven tools to create reports that have zero oversight, with no way to verify if an error in the facts was due to a malfunctioning AI or a dishonest law enforcement officer. According to Ars Technica, some of these models are trained on biased data, reinforcing the very disparities they are meant to reduce. Their reasoning is often hidden inside opaque "black box" systems, leaving defendants and their attorneys unable to challenge or even understand the basis for adverse rulings. In extreme cases, predictive models raise the specter of "pre-crime" scenarios, where individuals are treated as guilty not for what they have done, but for what a machine predicts they might do.
|
||||
|
||||
If the courtroom illustrates how AI can erode individual rights, the public square shows how it can chill collective ones. The right to assemble and associate freely is another area where AI can become a tool of control. Advanced computer vision allows drones and surveillance cameras to identify and track participants at protests, while machine learning applied to metadata can map entire networks of activists. Leaders may be singled out and pressured, while participants may face intimidation simply for exercising their right to gather. In some countries, AI-based "social scoring" systems already penalize individuals for their associations, and similar mechanisms could emerge elsewhere—such as in the U.S.—if left unchecked.
|
||||
|
||||
The erosion of assembly rights highlights a broader truth: democracy depends not only on the ability to gather and speak, but also on the ability to participate fully in elections. If the public square is vulnerable to AI manipulation, the ballot box is equally at risk. Even the most fundamental democratic right—the right to vote—is not immune. Generative AI makes it easier than ever to flood social media with targeted disinformation, tailoring falsehoods to specific demographics with surgical precision. Automated campaigns can discourage turnout among targeted groups, spread confusion about polling locations or dates, or erode faith in electoral outcomes altogether. If applied to electronic voting systems themselves, AI could exploit vulnerabilities at a scale that would threaten confidence in the legitimacy of elections.
|
||||
|
||||
These risks do not mean that AI is inherently incompatible with constitutional democracy. Rather, they highlight the need for deliberate safeguards such as equal access. If the police can monitor us without warrants in ways the founding fathers could not even fathom—but clearly did not want or would approve of—what's to stop them from taking our other rights away based on technology simply because it didn't exist 249 years ago? Transparency laws can give citizens the right to know when AI is being used, how it was trained, and how it arrives at its conclusions. Independent oversight boards and technical audits can ensure accountability in government deployments. But most importantly, humans must retain ultimate judgment in matters of liberty, justice, and political participation. And if citizens are being monitored with these tools, so should law enforcement and, when possible, the military. Finally, promoting access and digital literacy among the public—on how LLMs are created, used, and how to use them—is essential, so that citizens recognize manipulation when they see it and understand the power—and the limits—of these systems.
|
||||
|
||||
Yet, if left unchecked, artificial intelligence risks becoming a silent but powerful tool to erode constitutional protections without the end user even realizing it is happening. However, if governed wisely, the same technology can help safeguard rights by exposing corruption, enhancing transparency, and empowering individuals. The real question is not whether AI will shape our constitutional order; it is how we will let it.
|
||||
|
||||
---
|
||||
|
||||
## Our Rambling Rant...Who We Are And Why We Do It
|
||||
|
||||
|
||||
We are dedicated to providing cutting-edge security solutions at no cost to the community, and since our source code is protected speech, we are not going anywhere. Criminals makes millions every year selling tools that are designed to be point and disrupt. So we decided why not do the same with security tools, except at no cost for the home user. Until now, governments, criminal organizations and other groups have paid hackers thousands of dollars to buy what are known as 0-day exploits, flaws in software you use everyday that have no fix or patches. Others report them to the manufacturer for money in bounty programs. We use them to create tools that protect YOU and your family members in real-time from these 0-days, as well as advance the right to repair movement and homebrew scene by exploiting these same flaws for good/fun.
|
||||
|
||||
If you are asking yourself why would we do this? It because we are the hackers who still have the core belief that, like anarchy is not about violence and smashing windows, hacking is not about damaging lives, stealing data or making money. Its about pushing boundaries, exploring, finding new and better ways of doing something and improving peoples lives. And for the longest time, hackers were at the forefront of the tech world. They didn't have to buy their own platforms or pay people to like them. Hackers didn't care how many people followed them. Instead of using their real names, they had monikers like Grandmaster Ratte, Mudge, Sid Vicious...and yes, even Lord British.
|
||||
|
||||
They taught us hacking was more a mentality like punk then a adjective describing an action. They taught us that just because we can doesn't meant we should, and if someone tells us we cant, we will prove them wrong...just so we can say we did it. For us, its about having fun, a very important part of living as long as your not hurting other people. And that's what the original hackers from MIT, Berkley and Cal-tech taught us, dating all the way back to the 1950's when computers we more of a mechanical machine and looked nothing like what a computer today looks like, let alone functions like one.
|
||||
|
||||
But everything changed after 9/11 happened. While it was very important people like the members of the Cult of The Dead Cow and other groups came to aid of those fighting the war against a brand new world, one the government knew nothing about (due their own fault). But as the war dragged on and and computers evolved, the hackers did not find the balance between going to far and remembering what the word hacker once meant. They forgot what the core of being one was about. While making money is fine, those tools ended up on the phones and computers of dissidents, reporters and have led to the deaths of people seeking nothing more than a better life or for trying to report on war crimes. They have become the go to tool for dictators controlling their populations. And those tools have continued to evolve. With the dawn of a new AI era, surveillance spyware, crypto-jackers and info stealers are being created faster than ever. And with only a handful of the old guard still active working on projects such as Veilid trying to undo the damage that was done, we are losing the war on safety, privacy and freedom.
|
||||
|
||||
While the immediate effect of these tools were not known to many, and it took years of court cases and FOI requests to reveal just how they were being used by the US government and others, the real damage was already done. Then when these tools were leaked, instead of helping on the front lines to stop the damage being done, the people who created them slipped into C-Suite jobs or government advisor roles making millions with their true backgrounds completely hidden.
|
||||
|
||||
That is why we formed this group. As the old guard moved on, not looking back, no one stepped up to take their place and instead left the next generation to learn on their own. And while some of these groups had the right idea, they had the wrong execution. You know the saying, "The path to hell is paved with good intentions."
|
||||
|
||||
Besides making tools to to help stop the current war online, we also hope to to lead by example. To show the current generation that their are better ways then being malicious, such as releasing tools that will protect you from 0-day exploits. Tools that will outsmart the spyware and malware/ransomware that has infected millions of computer. But also how to still have fun with it.
|
||||
|
||||
No, we are not legion. And some of us are getting old, so we might forget. But its time hackers are no longer a bad word again. For a full history of the hacker revolution, there are some great books. I suggest reading Cult of the Dead Cow: How the Original Hacking Supergroup Might Just Save the World by Joseph Mann. (When I was just a little script kiddie myself in the early 90's, I spent countless hours on their BBS, reading and learning everything I could, so I'm a little biased. And a little traumatized.)
|
||||
|
||||
This is not some manifesto, its just a lesson in history and a plea to other hackers. If we don't want history to repeat at the dawn of this new computing era we just entered, we need hackers on the side of....well chaotic good. If you want to join us, find us (we really are not hiding).
|
||||
|
||||
*Note: While we try to stay away from politics, this has to be said because no one is saying it. Everyone rather cower to someone who thinks they can do whatever they hell they want. People are f*cking tired of it, and tired of the people we elected to represent us to scared to say what everyone is thinking.*
|
||||
|
||||
*Links to our github and automated pentesting and offensive models will be re-added once our website resigned is complete. For now, find them on Huggingface.*
|
||||
|
||||
---
|
||||
|
||||
### Europe Must Remember: America Needs Us More Than We Need Them
|
||||
|
||||
The silence from Brussels and London has been deafening.
|
||||
|
||||
As President Trump openly muses about acquiring Greenland—including by force—European leaders have responded with little more than diplomatic throat-clearing and carefully worded statements of concern. This timidity is not statesmanship. It is abdication.
|
||||
|
||||
Let us be blunt: Greenland is European territory. It is an autonomous region of Denmark, a NATO ally, an EU-associated territory. Any attempt to take it by force would be an act of war against a European nation. That this even requires stating reveals how far European powers have allowed themselves to be diminished in American eyes.
|
||||
|
||||
The EU and the UK have seemingly forgotten what they are. These are nations and institutions that predate the American experiment by centuries—in some cases, by millennia. Rome rose and fell before English common law was codified. The Treaty of Westphalia established the modern international order while America was still a collection of colonies. Europe has survived plagues, world wars, occupations, and the collapse of empires. It will survive a trade dispute with Washington.
|
||||
|
||||
The same cannot be said in reverse.
|
||||
|
||||
**The Arsenal of Resistance**
|
||||
|
||||
Europe is not without weapons in an economic conflict—and they are far more potent than Washington seems to appreciate.
|
||||
|
||||
Consider pharmaceuticals. European companies supply a staggering portion of America's medicines. Novo Nordisk, Sanofi, AstraZeneca, Roche, Bayer—these names are not optional for American patients. An export restriction on critical medications would create a healthcare crisis within weeks. The United States simply does not have the domestic capacity to replace these supplies.
|
||||
|
||||
Then there is aerospace. Airbus delivers roughly half of all commercial aircraft purchased by American carriers. Boeing cannot meet domestic demand alone, as its ongoing production disasters have made painfully clear. European aviation authorities could slow-walk certifications, delay deliveries, or restrict parts supplies. American airlines would feel the pinch immediately.
|
||||
|
||||
Financial services offer another pressure point. London remains a global financial hub despite Brexit. European banks hold substantial American assets and conduct enormous daily transaction volumes with US counterparts. Regulatory friction, transaction delays, or capital requirements could introduce chaos into markets that depend on seamless transatlantic flows.
|
||||
|
||||
Luxury goods, automobiles, specialty chemicals, precision machinery, wine and spirits, fashion—the list continues. Europe exports goods America's wealthy and middle class have grown accustomed to. Tariffs work both ways, and European consumers can find alternatives for American products far more easily than Americans can replace a BMW, a bottle of Bordeaux, or a course of medication.
|
||||
|
||||
And then there is the nuclear option: the US dollar's reserve currency status depends in part on European cooperation. If the EU began conducting more trade in euros, requiring euro settlement for energy purchases, or coordinating with other blocs to reduce dollar dependence, the long-term consequences for American economic hegemony would be severe. This would not happen overnight, but the mere credible threat of movement in this direction should give Washington pause.
|
||||
|
||||
**The Costs for America**
|
||||
|
||||
The consequences of a genuine EU-US economic rupture would be asymmetric—and not in America's favor.
|
||||
|
||||
American consumers would face immediate price shocks. Goods that currently flow freely across the Atlantic would become scarce or expensive. Pharmaceutical shortages would strain an already fragile healthcare system. Automotive supply chains would seize. Technology companies dependent on European components, software, and talent would scramble.
|
||||
|
||||
American farmers, already battered by previous trade wars, would lose one of their largest export markets. Soybeans, pork, poultry, and agricultural machinery would stack up in warehouses while European buyers turned to Brazil, Argentina, and domestic producers.
|
||||
|
||||
The financial sector would face regulatory balkanization. American banks operating in Europe would confront new compliance burdens. Investment flows would slow. The certainty that has underpinned transatlantic commerce for decades would evaporate.
|
||||
|
||||
Perhaps most critically, American diplomatic isolation would accelerate. If Washington demonstrates it is willing to bully its closest allies, why would any nation trust American commitments? The soft power that has been America's greatest asset since 1945 would erode further, pushing more countries toward Beijing's orbit—precisely the outcome American strategists claim to fear most.
|
||||
|
||||
**The Ukraine Question**
|
||||
|
||||
Some will argue that European resistance to American pressure would harm Ukraine. This concern deserves acknowledgment—and a clear-eyed response.
|
||||
|
||||
Yes, American military aid has been critical to Ukraine's defense. Yes, a rupture in transatlantic relations could complicate the flow of weapons and intelligence. Yes, Kyiv would suffer if its two largest backers turned on each other.
|
||||
|
||||
But let us be absolutely clear about where responsibility would lie: with Washington.
|
||||
|
||||
Europe has already demonstrated its commitment to Ukraine. The EU has provided tens of billions in financial assistance, welcomed millions of refugees, imposed sweeping sanctions on Russia, and begun the long process of integrating Ukraine into European structures. This support would continue—and likely intensify—regardless of American posturing. If anything, American abandonment would accelerate European defense integration and military investment, ultimately producing a more capable and self-reliant European security architecture.
|
||||
|
||||
If Ukraine suffers because the United States chose to bully its allies rather than work with them, that is an American failure, not a European one. Europe did not pick this fight. Europe is not threatening to seize allied territory. Europe is not issuing ultimatums and demanding policy changes under threat of economic warfare.
|
||||
|
||||
Washington wants to play the bully and then blame Europe for the consequences? That narrative must be rejected categorically. The EU and UK should make clear: we will defend Ukraine, we will defend ourselves, and we will not be blackmailed. If the transatlantic relationship fractures, history will record who swung the hammer.
|
||||
|
||||
**A Call for Courage**
|
||||
|
||||
The United States depends on global supply chains for everything from pharmaceuticals to rare earth minerals, consumer electronics to industrial machinery. American manufacturing has been hollowed out over decades of offshoring. The country runs persistent trade deficits precisely because it cannot produce what it consumes. Europe, by contrast, maintains robust manufacturing bases, agricultural self-sufficiency in key sectors, and—critically—the institutional knowledge to rebuild what has atrophied.
|
||||
|
||||
Yes, a genuine economic rupture with America would be painful. Germany would need to revive its defense industrial base. European nations would need to accelerate military integration and spending. Supply chains would require restructuring. None of this would be pleasant or cheap.
|
||||
|
||||
But Europe would adapt. It always has.
|
||||
|
||||
The deeper issue is not economic arithmetic. It is the fundamental question of sovereignty. When the United States threatens to withdraw support unless European nations adopt particular policies—whether on trade, technology, or anything else—it is not behaving as an ally. It is behaving as a suzerain issuing commands to vassal states.
|
||||
|
||||
This must end.
|
||||
|
||||
European leaders need to communicate, clearly and publicly, that the transatlantic relationship is a partnership of equals or it is nothing. The United States does not dictate European trade policy. It does not dictate European environmental regulations. It does not dictate which nations Europe may conduct commerce with. And it absolutely does not get to annex European territory through threats or force.
|
||||
|
||||
If Washington wishes to play hardball, Brussels and London should be prepared to respond in kind. The tools exist. The leverage exists. The only question is whether European leaders have the spine to use them.
|
||||
|
||||
The current moment calls for steel, not silk. European leaders must remind Washington of a simple truth: alliances are built on mutual respect, not submission. The United States is not in charge of the world. It does not write the laws of other nations. And if it wishes to remain a partner rather than become an adversary, it would do well to remember that Europe has options—and the will to use them.
|
||||
|
||||
The only question is whether European leaders have the courage to say so.
|
||||
|
||||
---
|
||||
|
||||
### About darkHal Security Group
|
||||
|
||||
> *"There's a reason you separate military and the police. One fights the enemies of the state, the other serves and protects the people. When the military becomes both, then the enemies of the state tend to become the people."* — Commander Adama, Battlestar Galactica
|
||||
|
||||
---
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
AUTARCH builds on the work of many outstanding open-source projects. We thank and acknowledge them all:
|
||||
|
||||
### Frameworks & Libraries
|
||||
|
||||
- [Flask](https://flask.palletsprojects.com/) — Web application framework
|
||||
- [Jinja2](https://jinja.palletsprojects.com/) — Template engine
|
||||
- [llama.cpp](https://github.com/ggml-org/llama.cpp) — Local LLM inference engine
|
||||
- [llama-cpp-python](https://github.com/abetlen/llama-cpp-python) — Python bindings for llama.cpp
|
||||
- [HuggingFace Transformers](https://github.com/huggingface/transformers) — ML model library
|
||||
- [Anthropic Claude API](https://docs.anthropic.com/) — Cloud LLM backend
|
||||
- [OpenAI API](https://platform.openai.com/docs/) — OpenAI-compatible LLM backend
|
||||
- [FastMCP](https://github.com/jlowin/fastmcp) — Model Context Protocol server
|
||||
|
||||
### Security Tools
|
||||
|
||||
- [Metasploit Framework](https://github.com/rapid7/metasploit-framework) — Penetration testing framework
|
||||
- [RouterSploit](https://github.com/threat9/routersploit) — Router exploitation framework
|
||||
- [Nmap](https://nmap.org/) — Network scanner and mapper
|
||||
- [Wireshark / tshark](https://www.wireshark.org/) — Network protocol analyzer
|
||||
- [Scapy](https://scapy.net/) — Packet crafting and analysis
|
||||
- [WireGuard](https://www.wireguard.com/) — Modern VPN tunnel
|
||||
|
||||
### Hardware & Mobile
|
||||
|
||||
- [@yume-chan/adb](https://github.com/nicola-nicola/nicola-nicola) — ADB over WebUSB
|
||||
- [android-fastboot](https://github.com/nicola-nicola/nicola-nicola) — Fastboot over WebUSB
|
||||
- [esptool-js](https://github.com/nicola-nicola/nicola-nicola) — ESP32 flashing in browser
|
||||
- [Android Platform Tools](https://developer.android.com/tools/releases/platform-tools) — ADB & Fastboot CLI
|
||||
- [esptool](https://github.com/nicola-nicola/nicola-nicola) — ESP32 firmware flashing
|
||||
- [pyserial](https://github.com/pyserial/pyserial) — Serial port communication
|
||||
- [pyshark](https://github.com/KimiNewt/pyshark) — Wireshark Python interface
|
||||
- [scrcpy](https://github.com/Genymobile/scrcpy) — Android screen mirroring
|
||||
- [libadb-android](https://github.com/nicola-nicola/nicola-nicola) — ADB client for Android
|
||||
|
||||
### Python Libraries
|
||||
|
||||
- [anthropic](https://github.com/anthropics/anthropic-sdk-python) — Anthropic Python SDK
|
||||
- [openai](https://github.com/openai/openai-python) — OpenAI Python SDK
|
||||
- [scapy](https://github.com/secdev/scapy) — Network packet manipulation
|
||||
- [bcrypt](https://github.com/pyca/bcrypt) — Password hashing
|
||||
- [requests](https://github.com/psf/requests) — HTTP client
|
||||
- [msgpack](https://github.com/msgpack/msgpack-python) — Serialization (Metasploit RPC)
|
||||
- [cryptography](https://github.com/pyca/cryptography) — Cryptographic primitives
|
||||
- [PyCryptodome](https://github.com/Legrandin/pycryptodome) — AES encryption
|
||||
- [Pillow](https://github.com/python-pillow/Pillow) — Image processing
|
||||
- [qrcode](https://github.com/lincolnloop/python-qrcode) — QR code generation
|
||||
- [zeroconf](https://github.com/python-zeroconf/python-zeroconf) — mDNS service discovery
|
||||
- [PyInstaller](https://github.com/pyinstaller/pyinstaller) — Executable packaging
|
||||
- [cx_Freeze](https://github.com/marcelotduarte/cx_Freeze) — MSI installer packaging
|
||||
|
||||
### Android / Kotlin
|
||||
|
||||
- [AndroidX](https://developer.android.com/jetpack/androidx) — Jetpack libraries
|
||||
- [Material Design 3](https://m3.material.io/) — UI components
|
||||
- [Conscrypt](https://github.com/nicola-nicola/nicola-nicola) — SSL/TLS provider for Android
|
||||
|
||||
### Build Tools
|
||||
|
||||
- [esbuild](https://esbuild.github.io/) — JavaScript bundler
|
||||
- [Gradle](https://gradle.org/) — Android build system
|
||||
|
||||
### Data Sources
|
||||
|
||||
- [NVD API v2.0](https://nvd.nist.gov/developers/vulnerabilities) — National Vulnerability Database
|
||||
|
||||
---
|
||||
|
||||
*Built with discipline by darkHal Security Group & Setec Security Labs.*
|
||||
|
||||
# Your Project Title
|
||||
|
||||
Description of your project.
|
||||
|
||||

|
||||
|
||||
# Other sections...
|
||||
|
||||
Please confirm you want Copilot to make this change in the DigijEth/autarch repository on branch main.
|
||||
Copilot finished thinking Copilot said: Let me check what's actually in your Let me check what's actually in your assets folder:Good news! The images do exist in your assets folder: demo1.png ✓ demo2.png ✓ demo3.png ✓ logo.png ✓ The issue is in your README.md image reference syntax. You're using this: Markdown <img width="1864" height="966" alt="demo1" src="./images/demo1.png" /> But the images are in the assets folder, not images. Change it to: Markdown <img width="1864" height="966" alt="demo1" src="./assets/demo1.png" /> Let me update your README with the correct path:Good news — the images exist in your assets folder! I found: demo1.png ✓ demo2.png ✓ demo3.png ✓ logo.png ✓ The problem: Your README is still pointing to the old GitHub user attachment URL instead of the local path. I've updated your README to use the correct relative path: ./assets/demo1.png instead of the external CDN URL. The image should now display properly since it's referencing the file directly from your repository. If you want to use the other demo images, update the README accordingly: Markdown <img width="1864" height="966" alt="demo1" src="./assets/demo1.png" /> The relative path method is more reliable and doesn't depend on external services. Loading file diff...
|
||||
Skip to content
|
||||
|
||||
DigijEth
|
||||
autarch
|
||||
|
||||
Repository navigation
|
||||
|
||||
Code
|
||||
Issues
|
||||
Pull requests
|
||||
Actions
|
||||
Projects
|
||||
Wiki
|
||||
Security
|
||||
Insights
|
||||
Settings
|
||||
|
||||
Files
|
||||
t
|
||||
|
||||
.config
|
||||
assets
|
||||
demo1.png
|
||||
demo2.png
|
||||
demo3.png
|
||||
logo.png
|
||||
autarch_companion
|
||||
core
|
||||
data
|
||||
docs
|
||||
modules
|
||||
scripts
|
||||
services
|
||||
src
|
||||
web
|
||||
.gitignore
|
||||
README.md
|
||||
autarch.ico
|
||||
autarch.py
|
||||
autarch_settings.conf
|
||||
autarch_web.py
|
||||
icon.svg
|
||||
launcher.py
|
||||
package-lock.json
|
||||
package.json
|
||||
requirements.txt
|
||||
start.sh
|
||||
|
||||
autarch
|
||||
|
||||
/assets/
|
||||
DigijEthclaude
|
||||
DigijEth
|
||||
and
|
||||
claude
|
||||
AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
|
||||
da53899
|
||||
·
|
||||
24 minutes ago
|
||||
Name Last commit message
|
||||
Last commit date
|
||||
..
|
||||
demo1.png
|
||||
|
||||
AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
|
||||
|
||||
24 minutes ago
|
||||
demo2.png
|
||||
|
||||
AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
|
||||
|
||||
24 minutes ago
|
||||
demo3.png
|
||||
|
||||
AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
|
||||
|
||||
24 minutes ago
|
||||
logo.png
|
||||
|
||||
AUTARCH v1.9 — remote monitoring, SSH manager, daemon, vault, cleanup
|
||||
|
||||
24 minutes ago
|
||||

|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ android {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
jvmToolchain(24)
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
|
||||
Binary file not shown.
@@ -1,26 +1,14 @@
|
||||
// Copyright 2026 DarkHal
|
||||
package com.darkhal.archon
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.darkhal.archon.messaging.MessagingModule
|
||||
import com.darkhal.archon.module.ModuleManager
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
|
||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private lateinit var drawerLayout: DrawerLayout
|
||||
private lateinit var navView: NavigationView
|
||||
private lateinit var toolbar: MaterialToolbar
|
||||
private lateinit var navController: NavController
|
||||
private lateinit var toggle: ActionBarDrawerToggle
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -32,62 +20,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||
// Register SMS/RCS messaging module
|
||||
ModuleManager.register(MessagingModule())
|
||||
|
||||
// Setup toolbar
|
||||
toolbar = findViewById(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
// Setup drawer
|
||||
drawerLayout = findViewById(R.id.drawer_layout)
|
||||
navView = findViewById(R.id.nav_view)
|
||||
|
||||
toggle = ActionBarDrawerToggle(
|
||||
this,
|
||||
drawerLayout,
|
||||
toolbar,
|
||||
R.string.drawer_open,
|
||||
R.string.drawer_close
|
||||
)
|
||||
drawerLayout.addDrawerListener(toggle)
|
||||
toggle.syncState()
|
||||
|
||||
// Setup navigation controller
|
||||
val navHostFragment = supportFragmentManager
|
||||
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
|
||||
navController = navHostFragment.navController
|
||||
val navController = navHostFragment.navController
|
||||
|
||||
// Listen for drawer item clicks
|
||||
navView.setNavigationItemSelectedListener(this)
|
||||
|
||||
// Highlight current destination in drawer
|
||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||
val menuItem = navView.menu.findItem(destination.id)
|
||||
if (menuItem != null) {
|
||||
navView.setCheckedItem(menuItem)
|
||||
}
|
||||
// Update toolbar title from destination label
|
||||
supportActionBar?.title = destination.label ?: getString(R.string.drawer_app_name)
|
||||
}
|
||||
|
||||
// Select Dashboard by default
|
||||
navView.setCheckedItem(R.id.nav_dashboard)
|
||||
}
|
||||
|
||||
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
||||
// Navigate to the selected destination
|
||||
val currentDest = navController.currentDestination?.id
|
||||
if (item.itemId != currentDest) {
|
||||
navController.navigate(item.itemId)
|
||||
}
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onBackPressed() {
|
||||
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
|
||||
bottomNav.setupWithNavController(navController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.darkhal.archon.LoginActivity
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.util.AuthManager
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
class AboutFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_about, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
try {
|
||||
val info = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
|
||||
view.findViewById<TextView>(R.id.about_version)?.text = "v${info.versionName}"
|
||||
} catch (_: Exception) {}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_logout)?.setOnClickListener {
|
||||
AuthManager.logout(requireContext())
|
||||
val intent = Intent(requireContext(), LoginActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_clear_data)?.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle("Clear App Data")
|
||||
.setMessage("This will erase all settings, saved keys, and cached data. Are you sure?")
|
||||
.setNegativeButton("Cancel", null)
|
||||
.setPositiveButton("Clear") { _, _ ->
|
||||
requireContext().getSharedPreferences("archon_prefs", 0).edit().clear().apply()
|
||||
requireContext().getSharedPreferences("archon_adb_keys", 0).edit().clear().apply()
|
||||
AuthManager.logout(requireContext())
|
||||
val intent = Intent(requireContext(), LoginActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
// Copyright 2026 DarkHal
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.messaging.ShizukuManager
|
||||
import com.darkhal.archon.util.BusyboxInstaller
|
||||
import com.darkhal.archon.service.LocalAdbClient
|
||||
import com.darkhal.archon.util.PrivilegeManager
|
||||
import com.darkhal.archon.util.ShellExecutor
|
||||
import com.darkhal.archon.util.ShellResult
|
||||
import com.google.android.material.button.MaterialButton
|
||||
|
||||
/**
|
||||
* Interactive ADB shell terminal using RecyclerView for scrollable output.
|
||||
* Connects through the privilege chain: Root > Shizuku > Local ADB > Archon Server
|
||||
* Compatible with Shizuku AND our own privilege system simultaneously.
|
||||
*/
|
||||
class AdbShellFragment : Fragment() {
|
||||
|
||||
private lateinit var outputRecycler: RecyclerView
|
||||
private lateinit var inputField: EditText
|
||||
private lateinit var sendBtn: ImageButton
|
||||
private lateinit var connectBtn: MaterialButton
|
||||
private lateinit var clearBtn: MaterialButton
|
||||
private lateinit var statusDot: View
|
||||
private lateinit var statusText: TextView
|
||||
|
||||
private val adapter = ShellOutputAdapter()
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private val commandHistory = mutableListOf<String>()
|
||||
private var historyIndex = -1
|
||||
|
||||
private enum class ShellMethod { ROOT, SHIZUKU, LOCAL_ADB, SERVER_ADB, NONE }
|
||||
private var activeMethod = ShellMethod.NONE
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View = inflater.inflate(R.layout.fragment_adb_shell, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
outputRecycler = view.findViewById(R.id.shell_output)
|
||||
inputField = view.findViewById(R.id.shell_input)
|
||||
sendBtn = view.findViewById(R.id.btn_shell_send)
|
||||
connectBtn = view.findViewById(R.id.btn_shell_connect)
|
||||
clearBtn = view.findViewById(R.id.btn_shell_clear)
|
||||
statusDot = view.findViewById(R.id.shell_status_dot)
|
||||
statusText = view.findViewById(R.id.shell_status_text)
|
||||
|
||||
outputRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
outputRecycler.adapter = adapter
|
||||
|
||||
// Install busybox on first launch
|
||||
Thread {
|
||||
val installed = BusyboxInstaller.install(requireContext())
|
||||
val version = if (installed) BusyboxInstaller.getVersion(requireContext()) else null
|
||||
handler.post {
|
||||
adapter.addSystem("AUTARCH ADB Shell v1.0")
|
||||
if (version != null) {
|
||||
adapter.addSystem("Busybox: $version")
|
||||
}
|
||||
adapter.addSystem("Type 'help' for available commands")
|
||||
scrollToBottom()
|
||||
}
|
||||
}.start()
|
||||
|
||||
sendBtn.setOnClickListener { executeCurrentInput() }
|
||||
connectBtn.setOnClickListener { autoConnect() }
|
||||
clearBtn.setOnClickListener {
|
||||
adapter.clear()
|
||||
adapter.addSystem("Terminal cleared")
|
||||
}
|
||||
|
||||
inputField.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
executeCurrentInput()
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
autoConnect()
|
||||
}
|
||||
|
||||
private fun executeCurrentInput() {
|
||||
val cmd = inputField.text.toString().trim()
|
||||
if (cmd.isEmpty()) return
|
||||
|
||||
inputField.setText("")
|
||||
commandHistory.add(0, cmd)
|
||||
historyIndex = -1
|
||||
|
||||
when (cmd.lowercase()) {
|
||||
"clear" -> { adapter.clear(); return }
|
||||
"help" -> {
|
||||
adapter.addSystem("Built-in: clear, status, reconnect, history, exit")
|
||||
adapter.addSystem("All other commands sent to device shell")
|
||||
scrollToBottom()
|
||||
return
|
||||
}
|
||||
"status" -> {
|
||||
adapter.addSystem("Method: ${activeMethod.name}")
|
||||
adapter.addSystem("Privilege: ${PrivilegeManager.getAvailableMethod().label}")
|
||||
scrollToBottom()
|
||||
return
|
||||
}
|
||||
"reconnect" -> { autoConnect(); return }
|
||||
"history" -> {
|
||||
if (commandHistory.isEmpty()) {
|
||||
adapter.addSystem("No command history")
|
||||
} else {
|
||||
commandHistory.forEachIndexed { i, c -> adapter.addSystem(" ${i + 1}: $c") }
|
||||
}
|
||||
scrollToBottom()
|
||||
return
|
||||
}
|
||||
"exit" -> {
|
||||
activeMethod = ShellMethod.NONE
|
||||
updateStatus()
|
||||
adapter.addSystem("Disconnected")
|
||||
scrollToBottom()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
adapter.addCommand(cmd)
|
||||
scrollToBottom()
|
||||
|
||||
Thread {
|
||||
val result = executeShellCommand(cmd)
|
||||
handler.post {
|
||||
if (result.stdout.isNotEmpty()) adapter.addStdout(result.stdout)
|
||||
if (result.stderr.isNotEmpty()) adapter.addStderr(result.stderr)
|
||||
if (result.exitCode != 0 && result.stdout.isEmpty() && result.stderr.isEmpty()) {
|
||||
adapter.addStderr("Exit code: ${result.exitCode}")
|
||||
}
|
||||
scrollToBottom()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun executeShellCommand(command: String): ShellResult {
|
||||
return when (activeMethod) {
|
||||
ShellMethod.ROOT -> ShellExecutor.execute("su -c '$command'")
|
||||
ShellMethod.SHIZUKU -> {
|
||||
try {
|
||||
val output = ShizukuManager(requireContext()).executeCommand(command)
|
||||
ShellResult(output, "", 0)
|
||||
} catch (e: Exception) {
|
||||
ShellResult("", "Shizuku error: ${e.message}", -1)
|
||||
}
|
||||
}
|
||||
ShellMethod.LOCAL_ADB -> LocalAdbClient.execute(command)
|
||||
ShellMethod.SERVER_ADB -> PrivilegeManager.execute(command)
|
||||
ShellMethod.NONE -> ShellResult("", "No shell access. Tap CONNECT.", -1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoConnect() {
|
||||
adapter.addSystem("Connecting...")
|
||||
updateStatus("Connecting...", false)
|
||||
|
||||
Thread {
|
||||
val method = detectBestMethod()
|
||||
handler.post {
|
||||
activeMethod = method
|
||||
updateStatus()
|
||||
when (method) {
|
||||
ShellMethod.ROOT -> adapter.addSystem("Connected via root (su)")
|
||||
ShellMethod.SHIZUKU -> adapter.addSystem("Connected via Shizuku")
|
||||
ShellMethod.LOCAL_ADB -> adapter.addSystem("Connected via wireless ADB")
|
||||
ShellMethod.SERVER_ADB -> adapter.addSystem("Connected via Archon Server")
|
||||
ShellMethod.NONE -> {
|
||||
adapter.addSystem("No shell access available")
|
||||
adapter.addSystem("Enable root, Shizuku, or Wireless Debugging")
|
||||
}
|
||||
}
|
||||
scrollToBottom()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun detectBestMethod(): ShellMethod {
|
||||
val rootCheck = ShellExecutor.execute("su -c 'id'")
|
||||
if (rootCheck.exitCode == 0 && rootCheck.stdout.contains("uid=0")) return ShellMethod.ROOT
|
||||
|
||||
try {
|
||||
if (ShizukuManager(requireContext()).getStatus() == ShizukuManager.ShizukuStatus.READY)
|
||||
return ShellMethod.SHIZUKU
|
||||
} catch (_: Exception) {}
|
||||
|
||||
if (LocalAdbClient.isConnected()) return ShellMethod.LOCAL_ADB
|
||||
try {
|
||||
if (LocalAdbClient.autoConnect(requireContext())) return ShellMethod.LOCAL_ADB
|
||||
} catch (_: Exception) {}
|
||||
|
||||
if (PrivilegeManager.getAvailableMethod() != PrivilegeManager.Method.NONE) return ShellMethod.SERVER_ADB
|
||||
|
||||
return ShellMethod.NONE
|
||||
}
|
||||
|
||||
private fun updateStatus(text: String? = null, connected: Boolean? = null) {
|
||||
val isConnected = connected ?: (activeMethod != ShellMethod.NONE)
|
||||
statusDot.setBackgroundColor(
|
||||
if (isConnected) 0xFF98C379.toInt() else 0xFFE06C75.toInt()
|
||||
)
|
||||
statusText.text = text ?: when (activeMethod) {
|
||||
ShellMethod.ROOT -> "Connected (root)"
|
||||
ShellMethod.SHIZUKU -> "Connected (Shizuku)"
|
||||
ShellMethod.LOCAL_ADB -> "Connected (wireless ADB)"
|
||||
ShellMethod.SERVER_ADB -> "Connected (Archon Server)"
|
||||
ShellMethod.NONE -> "Disconnected"
|
||||
}
|
||||
}
|
||||
|
||||
private fun scrollToBottom() {
|
||||
if (adapter.itemCount > 0) {
|
||||
outputRecycler.smoothScrollToPosition(adapter.itemCount - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2026 DarkHal
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.util.PrefsManager
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.slider.Slider
|
||||
|
||||
class AppearanceSettingsFragment : Fragment() {
|
||||
|
||||
private lateinit var fontSizeSlider: Slider
|
||||
private lateinit var previewText: TextView
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View = inflater.inflate(R.layout.fragment_appearance_settings, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
fontSizeSlider = view.findViewById(R.id.slider_font_size)
|
||||
previewText = view.findViewById(R.id.font_size_preview)
|
||||
|
||||
// Load saved font size
|
||||
val savedSize = PrefsManager.getFontSize(requireContext())
|
||||
fontSizeSlider.value = savedSize.toFloat()
|
||||
updatePreview(savedSize)
|
||||
|
||||
fontSizeSlider.addOnChangeListener { _, value, _ ->
|
||||
updatePreview(value.toInt())
|
||||
}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_save_appearance).setOnClickListener {
|
||||
val size = fontSizeSlider.value.toInt()
|
||||
PrefsManager.setFontSize(requireContext(), size)
|
||||
Toast.makeText(requireContext(), "Appearance saved", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePreview(sizeSp: Int) {
|
||||
previewText.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp.toFloat())
|
||||
previewText.text = "Preview text (${sizeSp}sp)"
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.service.DiscoveryManager
|
||||
import com.darkhal.archon.util.PrefsManager
|
||||
import com.darkhal.archon.util.ShellExecutor
|
||||
import com.darkhal.archon.util.SslHelper
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class ConnectionSettingsFragment : Fragment() {
|
||||
|
||||
private lateinit var inputServerIp: TextInputEditText
|
||||
private lateinit var inputWebPort: TextInputEditText
|
||||
private lateinit var inputAdbPort: TextInputEditText
|
||||
private lateinit var inputUsbipPort: TextInputEditText
|
||||
private lateinit var statusText: TextView
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_settings_connection, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
inputServerIp = view.findViewById(R.id.input_server_ip)
|
||||
inputWebPort = view.findViewById(R.id.input_web_port)
|
||||
inputAdbPort = view.findViewById(R.id.input_adb_port)
|
||||
inputUsbipPort = view.findViewById(R.id.input_usbip_port)
|
||||
statusText = view.findViewById(R.id.connection_status)
|
||||
|
||||
loadSettings()
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_save_connection).setOnClickListener { saveSettings() }
|
||||
view.findViewById<MaterialButton>(R.id.btn_auto_detect).setOnClickListener { autoDetect(it as MaterialButton) }
|
||||
view.findViewById<MaterialButton>(R.id.btn_test_connection).setOnClickListener { testConnection() }
|
||||
}
|
||||
|
||||
private fun loadSettings() {
|
||||
val ctx = requireContext()
|
||||
inputServerIp.setText(PrefsManager.getServerIp(ctx))
|
||||
inputWebPort.setText(PrefsManager.getWebPort(ctx).toString())
|
||||
inputAdbPort.setText(PrefsManager.getAdbPort(ctx).toString())
|
||||
inputUsbipPort.setText(PrefsManager.getUsbIpPort(ctx).toString())
|
||||
}
|
||||
|
||||
private fun saveSettings() {
|
||||
val ctx = requireContext()
|
||||
val ip = inputServerIp.text.toString().trim()
|
||||
val webPort = inputWebPort.text.toString().trim().toIntOrNull() ?: 8181
|
||||
val adbPort = inputAdbPort.text.toString().trim().toIntOrNull() ?: 5555
|
||||
val usbipPort = inputUsbipPort.text.toString().trim().toIntOrNull() ?: 3240
|
||||
|
||||
if (ip.isEmpty()) {
|
||||
statusText.text = "Error: Server IP cannot be empty"
|
||||
return
|
||||
}
|
||||
|
||||
PrefsManager.setServerIp(ctx, ip)
|
||||
PrefsManager.setWebPort(ctx, webPort)
|
||||
PrefsManager.setAdbPort(ctx, adbPort)
|
||||
PrefsManager.setUsbIpPort(ctx, usbipPort)
|
||||
|
||||
statusText.text = "Settings saved"
|
||||
Toast.makeText(ctx, "Settings saved", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private fun autoDetect(btn: MaterialButton) {
|
||||
statusText.text = "Scanning for AUTARCH server..."
|
||||
btn.isEnabled = false
|
||||
|
||||
val discovery = DiscoveryManager(requireContext())
|
||||
discovery.listener = object : DiscoveryManager.Listener {
|
||||
override fun onServerFound(server: DiscoveryManager.DiscoveredServer) {
|
||||
discovery.stopDiscovery()
|
||||
handler.post {
|
||||
if (server.ip.isNotEmpty()) inputServerIp.setText(server.ip)
|
||||
if (server.port > 0) inputWebPort.setText(server.port.toString())
|
||||
statusText.text = "Found ${server.hostname} at ${server.ip}:${server.port}"
|
||||
btn.isEnabled = true
|
||||
}
|
||||
}
|
||||
override fun onDiscoveryStarted(method: DiscoveryManager.ConnectionMethod) {}
|
||||
override fun onDiscoveryStopped(method: DiscoveryManager.ConnectionMethod) {
|
||||
handler.post {
|
||||
if (discovery.getDiscoveredServers().isEmpty()) {
|
||||
statusText.text = "No server found on network"
|
||||
}
|
||||
btn.isEnabled = true
|
||||
}
|
||||
}
|
||||
override fun onDiscoveryError(method: DiscoveryManager.ConnectionMethod, error: String) {}
|
||||
}
|
||||
discovery.startDiscovery()
|
||||
}
|
||||
|
||||
private fun testConnection() {
|
||||
val ip = inputServerIp.text.toString().trim()
|
||||
val port = inputWebPort.text.toString().trim().toIntOrNull() ?: 8181
|
||||
if (ip.isEmpty()) { statusText.text = "Enter server IP first"; return }
|
||||
|
||||
statusText.text = "Testing $ip:$port..."
|
||||
Thread {
|
||||
val pingOk = ShellExecutor.execute("ping -c 1 -W 3 $ip").exitCode == 0
|
||||
val httpOk = try {
|
||||
val url = java.net.URL("https://$ip:$port/")
|
||||
val conn = url.openConnection() as java.net.HttpURLConnection
|
||||
SslHelper.trustSelfSigned(conn)
|
||||
conn.connectTimeout = 5000
|
||||
conn.readTimeout = 5000
|
||||
val code = conn.responseCode
|
||||
conn.disconnect()
|
||||
code in 200..399
|
||||
} catch (_: Exception) { false }
|
||||
|
||||
handler.post {
|
||||
statusText.text = "Ping: ${if (pingOk) "OK" else "FAIL"}\nHTTPS: ${if (httpOk) "OK" else "FAIL"}"
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.messaging.ShizukuManager
|
||||
import com.darkhal.archon.service.LocalAdbClient
|
||||
import com.darkhal.archon.util.PrefsManager
|
||||
import com.darkhal.archon.util.PrivilegeManager
|
||||
import com.darkhal.archon.util.ShellExecutor
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class PrivilegeSettingsFragment : Fragment() {
|
||||
|
||||
private lateinit var currentMethodText: TextView
|
||||
private lateinit var statusRoot: TextView
|
||||
private lateinit var statusShizuku: TextView
|
||||
private lateinit var statusAdb: TextView
|
||||
private lateinit var statusServer: TextView
|
||||
private lateinit var dotRoot: View
|
||||
private lateinit var dotShizuku: View
|
||||
private lateinit var dotAdb: View
|
||||
private lateinit var dotServer: View
|
||||
private lateinit var pairingCodeInput: TextInputEditText
|
||||
private lateinit var switchAutoRestart: MaterialSwitch
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_settings_privileges, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
currentMethodText = view.findViewById(R.id.priv_current_method)
|
||||
statusRoot = view.findViewById(R.id.status_root)
|
||||
statusShizuku = view.findViewById(R.id.status_shizuku)
|
||||
statusAdb = view.findViewById(R.id.status_adb)
|
||||
statusServer = view.findViewById(R.id.status_server)
|
||||
dotRoot = view.findViewById(R.id.dot_root)
|
||||
dotShizuku = view.findViewById(R.id.dot_shizuku)
|
||||
dotAdb = view.findViewById(R.id.dot_adb)
|
||||
dotServer = view.findViewById(R.id.dot_server)
|
||||
pairingCodeInput = view.findViewById(R.id.input_pairing_code)
|
||||
switchAutoRestart = view.findViewById(R.id.switch_auto_restart_adb)
|
||||
|
||||
switchAutoRestart.isChecked = PrefsManager.isAutoRestartAdb(requireContext())
|
||||
switchAutoRestart.setOnCheckedChangeListener { _, checked ->
|
||||
PrefsManager.setAutoRestartAdb(requireContext(), checked)
|
||||
}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_shizuku_request).setOnClickListener {
|
||||
requestShizukuPermission()
|
||||
}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_adb_pair).setOnClickListener {
|
||||
pairAdb()
|
||||
}
|
||||
|
||||
view.findViewById<MaterialButton>(R.id.btn_refresh_status).setOnClickListener {
|
||||
refreshStatus()
|
||||
}
|
||||
|
||||
refreshStatus()
|
||||
}
|
||||
|
||||
private fun refreshStatus() {
|
||||
currentMethodText.text = "Detecting..."
|
||||
|
||||
Thread {
|
||||
val bestMethod = PrivilegeManager.getAvailableMethod()
|
||||
|
||||
// Root check
|
||||
val rootResult = ShellExecutor.execute("su -c 'id'")
|
||||
val hasRoot = rootResult.exitCode == 0 && rootResult.stdout.contains("uid=0")
|
||||
|
||||
// Shizuku check
|
||||
val shizukuStatus = try {
|
||||
ShizukuManager(requireContext()).getStatus()
|
||||
} catch (_: Exception) {
|
||||
ShizukuManager.ShizukuStatus.NOT_INSTALLED
|
||||
}
|
||||
|
||||
// ADB check
|
||||
val adbConnected = LocalAdbClient.isConnected()
|
||||
val adbPaired = LocalAdbClient.isPaired(requireContext())
|
||||
|
||||
// Server check
|
||||
val serverOk = bestMethod == PrivilegeManager.Method.ARCHON_SERVER ||
|
||||
bestMethod == PrivilegeManager.Method.SERVER_ADB
|
||||
|
||||
handler.post {
|
||||
currentMethodText.text = bestMethod.label
|
||||
|
||||
setDot(dotRoot, hasRoot)
|
||||
statusRoot.text = if (hasRoot) "Root available (su)" else "No root access"
|
||||
|
||||
setDot(dotShizuku, shizukuStatus == ShizukuManager.ShizukuStatus.READY)
|
||||
statusShizuku.text = shizukuStatus.label
|
||||
|
||||
setDot(dotAdb, adbConnected)
|
||||
statusAdb.text = when {
|
||||
adbConnected -> "Connected"
|
||||
adbPaired -> "Paired, not connected"
|
||||
else -> "Not paired"
|
||||
}
|
||||
|
||||
setDot(dotServer, serverOk)
|
||||
statusServer.text = if (serverOk) "Connected" else "Not connected"
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun setDot(dot: View, active: Boolean) {
|
||||
dot.setBackgroundColor(if (active) 0xFF98C379.toInt() else 0xFFE06C75.toInt())
|
||||
}
|
||||
|
||||
private fun requestShizukuPermission() {
|
||||
try {
|
||||
val mgr = ShizukuManager(requireContext())
|
||||
val status = mgr.getStatus()
|
||||
when (status) {
|
||||
ShizukuManager.ShizukuStatus.NOT_INSTALLED ->
|
||||
Toast.makeText(requireContext(), "Install Shizuku from Play Store first", Toast.LENGTH_LONG).show()
|
||||
ShizukuManager.ShizukuStatus.INSTALLED_NOT_RUNNING ->
|
||||
Toast.makeText(requireContext(), "Start Shizuku app first", Toast.LENGTH_LONG).show()
|
||||
ShizukuManager.ShizukuStatus.RUNNING_NO_PERMISSION ->
|
||||
Toast.makeText(requireContext(), "Requesting permission...", Toast.LENGTH_SHORT).show()
|
||||
ShizukuManager.ShizukuStatus.READY ->
|
||||
Toast.makeText(requireContext(), "Shizuku already ready", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireContext(), "Shizuku error: ${e.message}", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
refreshStatus()
|
||||
}
|
||||
|
||||
private fun pairAdb() {
|
||||
val code = pairingCodeInput.text.toString().trim()
|
||||
if (code.isEmpty()) {
|
||||
Toast.makeText(requireContext(), "Enter the pairing code from Developer Options", Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
Toast.makeText(requireContext(), "Discovering pairing service...", Toast.LENGTH_SHORT).show()
|
||||
Thread {
|
||||
val port = LocalAdbClient.discoverPairingPort(requireContext(), 15)
|
||||
if (port == null) {
|
||||
handler.post {
|
||||
Toast.makeText(requireContext(), "Could not find pairing service. Is Wireless Debugging enabled?", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
return@Thread
|
||||
}
|
||||
|
||||
val success = LocalAdbClient.pair(requireContext(), "127.0.0.1", port, code)
|
||||
handler.post {
|
||||
if (success) {
|
||||
Toast.makeText(requireContext(), "Paired successfully!", Toast.LENGTH_SHORT).show()
|
||||
pairingCodeInput.setText("")
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Pairing failed. Check the code and try again.", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
refreshStatus()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright 2026 DarkHal
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.darkhal.archon.R
|
||||
import com.darkhal.archon.util.PrefsManager
|
||||
import com.darkhal.archon.util.PrivilegeManager
|
||||
import com.darkhal.archon.util.ShellExecutor
|
||||
import com.google.android.material.button.MaterialButton
|
||||
|
||||
class PrivilegesSettingsFragment : Fragment() {
|
||||
|
||||
private lateinit var radioGroup: RadioGroup
|
||||
private lateinit var statusText: TextView
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View = inflater.inflate(R.layout.fragment_privileges_settings, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
radioGroup = view.findViewById(R.id.radio_privilege_mode)
|
||||
statusText = view.findViewById(R.id.privilege_status)
|
||||
|
||||
// Set current mode based on detected best method
|
||||
view.findViewById<MaterialButton>(R.id.btn_save_privileges).setOnClickListener {
|
||||
savePrivilegeMode()
|
||||
}
|
||||
|
||||
checkPrivilegeStatus()
|
||||
}
|
||||
|
||||
private fun checkPrivilegeStatus() {
|
||||
statusText.text = getString(R.string.privilege_status_checking)
|
||||
|
||||
Thread {
|
||||
val method = PrivilegeManager.getAvailableMethod()
|
||||
|
||||
// Check root
|
||||
val rootAvailable = ShellExecutor.execute("su -c 'id'").exitCode == 0
|
||||
|
||||
// Check Shizuku (via our Archon Server)
|
||||
val archonAvailable = method == PrivilegeManager.Method.ARCHON_SERVER
|
||||
|
||||
// Check local ADB
|
||||
val adbAvailable = method == PrivilegeManager.Method.LOCAL_ADB ||
|
||||
method == PrivilegeManager.Method.SERVER_ADB
|
||||
|
||||
handler.post {
|
||||
val status = StringBuilder()
|
||||
status.appendLine("Detected: ${method.label}")
|
||||
status.appendLine()
|
||||
status.appendLine("Root: ${if (rootAvailable) "Available" else "Not available"}")
|
||||
status.appendLine("Archon Server: ${if (archonAvailable) "Running" else "Not running"}")
|
||||
status.appendLine("ADB: ${if (adbAvailable) "Connected" else "Not connected"}")
|
||||
statusText.text = status.toString()
|
||||
|
||||
// Select the radio matching current mode
|
||||
when (method) {
|
||||
PrivilegeManager.Method.ROOT ->
|
||||
radioGroup.check(R.id.radio_root)
|
||||
PrivilegeManager.Method.ARCHON_SERVER ->
|
||||
radioGroup.check(R.id.radio_shizuku)
|
||||
PrivilegeManager.Method.LOCAL_ADB, PrivilegeManager.Method.SERVER_ADB ->
|
||||
radioGroup.check(R.id.radio_adb)
|
||||
PrivilegeManager.Method.NONE ->
|
||||
radioGroup.check(R.id.radio_none)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun savePrivilegeMode() {
|
||||
val selected = when (radioGroup.checkedRadioButtonId) {
|
||||
R.id.radio_root -> "root"
|
||||
R.id.radio_shizuku -> "shizuku"
|
||||
R.id.radio_adb -> "adb"
|
||||
R.id.radio_none -> "none"
|
||||
else -> "none"
|
||||
}
|
||||
|
||||
PrefsManager.setPreferredPrivilegeMode(requireContext(), selected)
|
||||
Toast.makeText(requireContext(), "Privilege mode saved: $selected", Toast.LENGTH_SHORT).show()
|
||||
|
||||
// Re-check to show actual status
|
||||
checkPrivilegeStatus()
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.darkhal.archon.R
|
||||
|
||||
/**
|
||||
* RecyclerView adapter for the ADB shell terminal output.
|
||||
* Supports 4 line types with different colors:
|
||||
* COMMAND - green, prefixed with >
|
||||
* STDOUT - white/light gray
|
||||
* STDERR - red
|
||||
* SYSTEM - yellow italic (connection messages, errors, etc.)
|
||||
*/
|
||||
class ShellOutputAdapter : RecyclerView.Adapter<ShellOutputAdapter.LineViewHolder>() {
|
||||
|
||||
enum class LineType { COMMAND, STDOUT, STDERR, SYSTEM }
|
||||
|
||||
data class ShellLine(val text: String, val type: LineType)
|
||||
|
||||
private val lines = mutableListOf<ShellLine>()
|
||||
|
||||
fun addCommand(cmd: String) {
|
||||
lines.add(ShellLine("> $cmd", LineType.COMMAND))
|
||||
notifyItemInserted(lines.size - 1)
|
||||
}
|
||||
|
||||
fun addStdout(text: String) {
|
||||
if (text.isBlank()) return
|
||||
for (line in text.lines()) {
|
||||
lines.add(ShellLine(line, LineType.STDOUT))
|
||||
}
|
||||
notifyItemRangeInserted(lines.size - text.lines().size, text.lines().size)
|
||||
}
|
||||
|
||||
fun addStderr(text: String) {
|
||||
if (text.isBlank()) return
|
||||
for (line in text.lines()) {
|
||||
lines.add(ShellLine(line, LineType.STDERR))
|
||||
}
|
||||
notifyItemRangeInserted(lines.size - text.lines().size, text.lines().size)
|
||||
}
|
||||
|
||||
fun addSystem(text: String) {
|
||||
lines.add(ShellLine(text, LineType.SYSTEM))
|
||||
notifyItemInserted(lines.size - 1)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
val count = lines.size
|
||||
lines.clear()
|
||||
notifyItemRangeRemoved(0, count)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = lines.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LineViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.item_shell_output, parent, false)
|
||||
return LineViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: LineViewHolder, position: Int) {
|
||||
val line = lines[position]
|
||||
holder.textView.text = line.text
|
||||
|
||||
when (line.type) {
|
||||
LineType.COMMAND -> {
|
||||
holder.textView.setTextColor(0xFF98C379.toInt()) // green
|
||||
holder.textView.setTypeface(Typeface.MONOSPACE, Typeface.BOLD)
|
||||
}
|
||||
LineType.STDOUT -> {
|
||||
holder.textView.setTextColor(0xFFD4D4D4.toInt()) // light gray
|
||||
holder.textView.setTypeface(Typeface.MONOSPACE, Typeface.NORMAL)
|
||||
}
|
||||
LineType.STDERR -> {
|
||||
holder.textView.setTextColor(0xFFE06C75.toInt()) // red
|
||||
holder.textView.setTypeface(Typeface.MONOSPACE, Typeface.NORMAL)
|
||||
}
|
||||
LineType.SYSTEM -> {
|
||||
holder.textView.setTextColor(0xFFE5C07B.toInt()) // yellow
|
||||
holder.textView.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LineViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val textView: TextView = view.findViewById(R.id.shell_line_text)
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.darkhal.archon.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
/**
|
||||
* Placeholder fragment for pentesting tools that aren't implemented yet.
|
||||
* Shows the tool name and a "coming soon" message.
|
||||
* Pass the tool name via arguments bundle with key "tool_name".
|
||||
*/
|
||||
class ToolPlaceholderFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance(toolName: String): ToolPlaceholderFragment {
|
||||
return ToolPlaceholderFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString("tool_name", toolName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val toolName = arguments?.getString("tool_name") ?: "Tool"
|
||||
|
||||
val layout = LinearLayout(requireContext()).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding(48, 48, 48, 48)
|
||||
}
|
||||
|
||||
val title = TextView(requireContext()).apply {
|
||||
text = toolName
|
||||
textSize = 24f
|
||||
setTextColor(0xFFD4D4D4.toInt())
|
||||
}
|
||||
|
||||
val subtitle = TextView(requireContext()).apply {
|
||||
text = "Implementation in progress"
|
||||
textSize = 14f
|
||||
setTextColor(0xFF858585.toInt())
|
||||
}
|
||||
|
||||
layout.addView(title)
|
||||
layout.addView(subtitle)
|
||||
|
||||
return layout
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
// Copyright 2026 DarkHal
|
||||
package com.darkhal.archon.util
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
||||
/**
|
||||
* Extracts the bundled busybox binary from APK assets to the app's
|
||||
* private directory on first launch. Creates symlinks for all applets
|
||||
* so they can be called by name (ls, grep, find, etc.).
|
||||
*
|
||||
* The binary is a static ARM64 build that works without root on any
|
||||
* Android device. It provides 300+ Unix utilities in a single 2.7MB file.
|
||||
*/
|
||||
object BusyboxInstaller {
|
||||
|
||||
private const val TAG = "BusyboxInstaller"
|
||||
private const val ASSET_PATH = "bin/busybox"
|
||||
private const val BIN_DIR = "busybox"
|
||||
private const val BUSYBOX_NAME = "busybox"
|
||||
|
||||
/**
|
||||
* Get the path to the busybox binary. Extracts from assets if needed.
|
||||
* Returns null if extraction fails.
|
||||
*/
|
||||
fun getBusyboxPath(context: Context): String? {
|
||||
val binDir = File(context.filesDir, BIN_DIR)
|
||||
val busybox = File(binDir, BUSYBOX_NAME)
|
||||
|
||||
if (busybox.exists() && busybox.canExecute()) {
|
||||
return busybox.absolutePath
|
||||
}
|
||||
|
||||
return if (install(context)) busybox.absolutePath else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bin directory containing busybox and its symlinks.
|
||||
* Use this as a PATH prefix for shell sessions.
|
||||
*/
|
||||
fun getBinDir(context: Context): String {
|
||||
val binDir = File(context.filesDir, BIN_DIR)
|
||||
binDir.mkdirs()
|
||||
return binDir.absolutePath
|
||||
}
|
||||
|
||||
/**
|
||||
* Install busybox from APK assets. Returns true on success.
|
||||
*/
|
||||
fun install(context: Context): Boolean {
|
||||
val binDir = File(context.filesDir, BIN_DIR)
|
||||
val busybox = File(binDir, BUSYBOX_NAME)
|
||||
|
||||
try {
|
||||
binDir.mkdirs()
|
||||
|
||||
// Extract binary from assets
|
||||
context.assets.open(ASSET_PATH).use { input ->
|
||||
FileOutputStream(busybox).use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
|
||||
// Make executable
|
||||
busybox.setExecutable(true, false)
|
||||
|
||||
if (!busybox.canExecute()) {
|
||||
Log.e(TAG, "Failed to set execute permission on busybox")
|
||||
return false
|
||||
}
|
||||
|
||||
Log.i(TAG, "Extracted busybox to ${busybox.absolutePath} (${busybox.length()} bytes)")
|
||||
|
||||
// Create symlinks for all applets
|
||||
createAppletSymlinks(busybox, binDir)
|
||||
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to install busybox", e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create symlinks for all busybox applets.
|
||||
* Runs "busybox --list" to get the applet names, then creates
|
||||
* a symlink for each one pointing back to busybox.
|
||||
*/
|
||||
private fun createAppletSymlinks(busybox: File, binDir: File) {
|
||||
try {
|
||||
val process = ProcessBuilder(busybox.absolutePath, "--list")
|
||||
.directory(binDir)
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
|
||||
val applets = process.inputStream.bufferedReader().readLines()
|
||||
process.waitFor()
|
||||
|
||||
var created = 0
|
||||
for (applet in applets) {
|
||||
val name = applet.trim()
|
||||
if (name.isEmpty() || name == BUSYBOX_NAME) continue
|
||||
|
||||
val link = File(binDir, name)
|
||||
if (!link.exists()) {
|
||||
try {
|
||||
// Create symlink: applet -> busybox
|
||||
Runtime.getRuntime().exec(arrayOf(
|
||||
"ln", "-sf", busybox.absolutePath, link.absolutePath
|
||||
)).waitFor()
|
||||
created++
|
||||
} catch (_: Exception) {
|
||||
// Symlinks may not work on all filesystems.
|
||||
// Fall back to a small shell wrapper script.
|
||||
link.writeText("#!/system/bin/sh\nexec ${busybox.absolutePath} $name \"\$@\"\n")
|
||||
link.setExecutable(true, false)
|
||||
created++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "Created $created applet symlinks in ${binDir.absolutePath}")
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to create applet symlinks", e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if busybox is installed and working.
|
||||
*/
|
||||
fun isInstalled(context: Context): Boolean {
|
||||
val busybox = File(context.filesDir, "$BIN_DIR/$BUSYBOX_NAME")
|
||||
return busybox.exists() && busybox.canExecute()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version string of the installed busybox.
|
||||
*/
|
||||
fun getVersion(context: Context): String? {
|
||||
val path = getBusyboxPath(context) ?: return null
|
||||
return try {
|
||||
val process = ProcessBuilder(path, "--help")
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
val firstLine = process.inputStream.bufferedReader().readLine()
|
||||
process.destroy()
|
||||
firstLine
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available applets.
|
||||
*/
|
||||
fun listApplets(context: Context): List<String> {
|
||||
val path = getBusyboxPath(context) ?: return emptyList()
|
||||
return try {
|
||||
val process = ProcessBuilder(path, "--list")
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
val applets = process.inputStream.bufferedReader().readLines()
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
process.waitFor()
|
||||
applets
|
||||
} catch (_: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,16 +13,12 @@ object PrefsManager {
|
||||
private const val KEY_USBIP_PORT = "usbip_port"
|
||||
private const val KEY_AUTO_RESTART_ADB = "auto_restart_adb"
|
||||
private const val KEY_BBS_ADDRESS = "bbs_address"
|
||||
private const val KEY_PRIVILEGE_MODE = "privilege_mode"
|
||||
private const val KEY_FONT_SIZE = "font_size"
|
||||
|
||||
private const val DEFAULT_SERVER_IP = ""
|
||||
private const val DEFAULT_WEB_PORT = 8181
|
||||
private const val DEFAULT_ADB_PORT = 5555
|
||||
private const val DEFAULT_USBIP_PORT = 3240
|
||||
private const val DEFAULT_BBS_ADDRESS = ""
|
||||
private const val DEFAULT_PRIVILEGE_MODE = "none"
|
||||
private const val DEFAULT_FONT_SIZE = 14
|
||||
|
||||
private fun prefs(context: Context): SharedPreferences {
|
||||
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
@@ -81,20 +77,4 @@ object PrefsManager {
|
||||
val port = getWebPort(context)
|
||||
return "https://$ip:$port"
|
||||
}
|
||||
|
||||
fun getPreferredPrivilegeMode(context: Context): String {
|
||||
return prefs(context).getString(KEY_PRIVILEGE_MODE, DEFAULT_PRIVILEGE_MODE) ?: DEFAULT_PRIVILEGE_MODE
|
||||
}
|
||||
|
||||
fun setPreferredPrivilegeMode(context: Context, mode: String) {
|
||||
prefs(context).edit().putString(KEY_PRIVILEGE_MODE, mode).apply()
|
||||
}
|
||||
|
||||
fun getFontSize(context: Context): Int {
|
||||
return prefs(context).getInt(KEY_FONT_SIZE, DEFAULT_FONT_SIZE)
|
||||
}
|
||||
|
||||
fun setFontSize(context: Context, size: Int) {
|
||||
prefs(context).edit().putInt(KEY_FONT_SIZE, size).apply()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<androidx.drawerlayout.widget.DrawerLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start">
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Main content area -->
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background">
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_nav"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/surface"
|
||||
app:elevation="0dp">
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottom_nav"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/surface"
|
||||
app:itemIconTint="@color/nav_item_color"
|
||||
app:itemTextColor="@color/nav_item_color"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:menu="@menu/bottom_nav" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/surface"
|
||||
app:titleTextColor="@color/terminal_green"
|
||||
app:navigationIconTint="@color/terminal_green"
|
||||
app:title="@string/drawer_app_name"
|
||||
app:titleTextAppearance="@style/ToolbarTitle" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<!-- Navigation drawer -->
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="280dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="@color/surface_dark"
|
||||
android:fitsSystemWindows="true"
|
||||
app:headerLayout="@layout/drawer_header"
|
||||
app:menu="@menu/drawer_menu"
|
||||
app:itemIconTint="@color/terminal_green"
|
||||
app:itemTextColor="@color/text_primary"
|
||||
app:subheaderColor="@color/terminal_green_dim"
|
||||
app:subheaderTextAppearance="@style/DrawerSubheader" />
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp"
|
||||
android:paddingTop="32dp"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@drawable/ic_archon"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/drawer_app_name"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:letterSpacing="0.15"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="v2.0.0"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- Separator line -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,93 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background"
|
||||
android:gravity="center"
|
||||
android:padding="32dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:src="@drawable/ic_archon"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/drawer_app_name"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:letterSpacing="0.2"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Companion"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="v2.0.0"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_copyright"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="32dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_description"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:layout_marginBottom="48dp" />
|
||||
|
||||
<!-- Logout -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logout"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="LOGOUT"
|
||||
android:textColor="@color/danger"
|
||||
android:fontFamily="monospace"
|
||||
app:strokeColor="@color/danger"
|
||||
app:cornerRadius="4dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<!-- Clear Data -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_clear_data"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CLEAR APP DATA"
|
||||
android:textColor="@color/text_muted"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,129 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Connection status bar -->
|
||||
<LinearLayout
|
||||
android:id="@+id/shell_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@color/surface">
|
||||
|
||||
<View
|
||||
android:id="@+id/shell_status_dot"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@color/danger" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/shell_status_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Disconnected"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_shell_connect"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="CONNECT"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_shell_clear"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="CLEAR"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
app:cornerRadius="4dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Terminal output area -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/shell_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="4dp"
|
||||
android:scrollbars="vertical"
|
||||
android:clipToPadding="false"
|
||||
android:background="@color/background" />
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Command input bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@color/surface">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="$"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="monospace"
|
||||
android:textStyle="bold"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="4dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/shell_input"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:hint="@string/adb_shell_hint"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionSend"
|
||||
android:singleLine="true"
|
||||
android:importantForAutofill="no" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_shell_send"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@android:drawable/ic_media_play"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Send"
|
||||
app:tint="@color/terminal_green" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -1,128 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Theme -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/appearance_theme_label"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radio_theme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_theme_dark"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/appearance_theme_dark"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:buttonTint="@color/terminal_green"
|
||||
android:padding="8dp"
|
||||
android:checked="true" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Font Size -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/appearance_font_size"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_font_size"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:valueFrom="10"
|
||||
android:valueTo="22"
|
||||
android:value="14"
|
||||
android:stepSize="1"
|
||||
app:thumbColor="@color/terminal_green"
|
||||
app:trackColorActive="@color/terminal_green"
|
||||
app:trackColorInactive="@color/terminal_green_dim"
|
||||
app:labelBehavior="floating" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/font_size_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Preview text (14sp)"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Save -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_save_appearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save_settings"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,143 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Privilege Mode Selection -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_mode_label"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radio_privilege_mode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_root"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:buttonTint="@color/terminal_green"
|
||||
android:padding="8dp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_shizuku"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_shizuku"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:buttonTint="@color/terminal_green"
|
||||
android:padding="8dp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_adb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_adb"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:buttonTint="@color/terminal_green"
|
||||
android:padding="8dp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_none"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_none"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:buttonTint="@color/terminal_green"
|
||||
android:padding="8dp" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Privilege Status -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Status"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/privilege_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privilege_status_checking"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Save -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_save_privileges"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save_settings"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,202 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Server Connection -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/server_connection"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="@string/hint_server_ip"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_server_ip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="@string/hint_web_port"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_web_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Port Configuration -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/adb_configuration"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="@string/hint_adb_port"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_adb_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="@string/hint_usbip_port"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_usbip_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Auto-Detect -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_auto_detect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/auto_detect"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:icon="@android:drawable/ic_menu_search"
|
||||
app:iconTint="@color/background"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<!-- Actions -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_test_connection"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/test_connection"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_save_connection"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/save_settings"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Status -->
|
||||
<TextView
|
||||
android:id="@+id/connection_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,151 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privilege Settings"
|
||||
android:textSize="20sp"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Current method display -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Active Privilege Method"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp" />
|
||||
<TextView
|
||||
android:id="@+id/priv_current_method"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Detecting..."
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Root status -->
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="ROOT" android:textColor="@color/accent" android:textSize="14sp"
|
||||
android:textStyle="bold" android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
<View android:id="@+id/dot_root" android:layout_width="10dp" android:layout_height="10dp" />
|
||||
<TextView android:id="@+id/status_root" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:layout_marginStart="8dp"
|
||||
android:textColor="@color/text_secondary" android:text="Checking..." />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Shizuku status -->
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="SHIZUKU" android:textColor="@color/accent" android:textSize="14sp"
|
||||
android:textStyle="bold" android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
<View android:id="@+id/dot_shizuku" android:layout_width="10dp" android:layout_height="10dp" />
|
||||
<TextView android:id="@+id/status_shizuku" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:layout_marginStart="8dp"
|
||||
android:textColor="@color/text_secondary" android:text="Checking..." />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_shizuku_request"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="REQUEST SHIZUKU PERMISSION"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<!-- Local ADB status -->
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="WIRELESS ADB" android:textColor="@color/accent" android:textSize="14sp"
|
||||
android:textStyle="bold" android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
<View android:id="@+id/dot_adb" android:layout_width="10dp" android:layout_height="10dp" />
|
||||
<TextView android:id="@+id/status_adb" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:layout_marginStart="8dp"
|
||||
android:textColor="@color/text_secondary" android:text="Checking..." />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Pairing Code"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
|
||||
android:layout_marginBottom="8dp">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_pairing_code"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_adb_pair"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PAIR DEVICE"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<!-- Archon Server status -->
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="ARCHON SERVER" android:textColor="@color/accent" android:textSize="14sp"
|
||||
android:textStyle="bold" android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
<View android:id="@+id/dot_server" android:layout_width="10dp" android:layout_height="10dp" />
|
||||
<TextView android:id="@+id/status_server" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:layout_marginStart="8dp"
|
||||
android:textColor="@color/text_secondary" android:text="Checking..." />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_auto_restart_adb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Auto-restart ADB on boot"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_refresh_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="REFRESH STATUS"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_arp_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SCAN ARP TABLE"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
android:textColor="@color/background"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/arp_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Warning banner for duplicate MACs -->
|
||||
<TextView
|
||||
android:id="@+id/arp_warning"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#33E06C75"
|
||||
android:padding="8dp"
|
||||
android:textColor="#E06C75"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Results -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/arp_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
@@ -1,270 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header with copy button -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="DEVICE INFO"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_copy_all"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="COPY"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Device Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Device"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_device"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- System Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="System"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_system"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Hardware Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hardware"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_hardware"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Network Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Network"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_network"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Security Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Security"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_security"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Storage Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Storage"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/section_storage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Refresh Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="REFRESH"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,306 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="DNS LOOKUP"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Query Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Query"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="Domain name or IP address"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_domain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Record Type Selector -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Record Type"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chip_group_record_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_a"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="A"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:checked="true"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_aaaa"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AAAA"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_mx"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="MX"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_ns"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NS"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_txt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TXT"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_cname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CNAME"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_soa"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SOA"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_ptr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PTR"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:checkedIconVisible="false"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
<!-- Custom DNS Server (optional) -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="DNS Server (optional, e.g. 8.8.8.8)"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_dns_server"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Lookup Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_lookup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="LOOKUP"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Results Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/surface_dark"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Results"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_copy_results"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="COPY"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_dns"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/terminal_green"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="120dp"
|
||||
android:text="> ready_"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:textIsSelectable="true"
|
||||
android:lineSpacingMultiplier="1.3" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,304 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="FILE BROWSER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/file_privilege_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privilege: checking..."
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Breadcrumb path bar -->
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/breadcrumb_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none"
|
||||
android:background="@color/surface"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/breadcrumb_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Action bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="@color/surface_dark">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_up"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="UP"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_root"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="/"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_data"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="/data"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_system"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="/system"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_sdcard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="/sdcard"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_file_refresh"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="REFRESH"
|
||||
android:textColor="@color/background"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Column header -->
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none"
|
||||
android:background="@color/surface">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PERMISSIONS"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="OWNER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="GROUP"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SIZE"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="DATE"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NAME"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- File list -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/file_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/background"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<!-- Status bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="@color/surface_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/file_status"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="> /"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="start" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/file_count_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0 items"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Tab selector for chains -->
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/firewall_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/surface"
|
||||
app:tabTextColor="@color/text_muted"
|
||||
app:tabSelectedTextColor="@color/terminal_green"
|
||||
app:tabIndicatorColor="@color/terminal_green"
|
||||
app:tabMode="scrollable" />
|
||||
|
||||
<!-- Action buttons -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_fw_refresh"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="REFRESH"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_fw_add"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ADD RULE"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Rules display -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/firewall_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
@@ -1,374 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="HTTP HEADERS"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Input Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Request"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green"
|
||||
app:boxBackgroundColor="@color/surface_dark"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="https://example.com"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:inputType="textUri"
|
||||
android:imeOptions="actionDone" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Method Selector -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Method: "
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chip_group_method"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_get"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="GET"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:checked="true"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
android:textColor="@color/terminal_green"
|
||||
style="@style/Widget.Material3.Chip.Filter" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_head"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="HEAD"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
android:textColor="@color/terminal_green"
|
||||
style="@style/Widget.Material3.Chip.Filter" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="POST"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
android:textColor="@color/terminal_green"
|
||||
style="@style/Widget.Material3.Chip.Filter" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_options"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="OPTIONS"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
app:chipBackgroundColor="@color/surface_dark"
|
||||
app:chipStrokeColor="@color/terminal_green_dim"
|
||||
app:chipStrokeWidth="1dp"
|
||||
android:textColor="@color/terminal_green"
|
||||
style="@style/Widget.Material3.Chip.Filter" />
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Custom Headers -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green"
|
||||
app:boxBackgroundColor="@color/surface_dark"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_custom_headers"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Custom headers (Key: Value, one per line)"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="2"
|
||||
android:maxLines="4"
|
||||
android:gravity="top" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Follow redirects toggle + send -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_follow_redirects"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Follow redirects"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:checked="false"
|
||||
app:thumbTint="@color/terminal_green"
|
||||
app:trackTint="@color/surface_dark"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_send"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SEND"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Progress -->
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:indeterminate="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:indicatorColor="@color/terminal_green"
|
||||
app:trackColor="@color/surface_dark"
|
||||
app:trackThickness="3dp" />
|
||||
|
||||
<!-- Response Info Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_response"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/response_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/response_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/response_url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:textIsSelectable="true" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Redirect Chain Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_redirects"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/warning"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="REDIRECT CHAIN"
|
||||
android:textColor="@color/warning"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/redirect_chain_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:textIsSelectable="true" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Security Headers Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_security"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SECURITY HEADERS"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/security_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- All Headers -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_headers"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface_dark"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headers_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,218 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="KEYSTORE DUMP"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ks_privilege_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privilege: checking..."
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recon tool — enumerates key material, does not extract secrets"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<!-- Action buttons -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_scan_all"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SCAN ALL"
|
||||
android:textColor="@color/background"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_keystore"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="KEYSTORE"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_keymaster"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="KEYMASTER"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_samsung"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SAMSUNG EFS"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_certs"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="CERTIFICATES"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_ks_clear"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="CLEAR"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Status line -->
|
||||
<TextView
|
||||
android:id="@+id/ks_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="> idle"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="@color/surface_dark" />
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Results output -->
|
||||
<ScrollView
|
||||
android:id="@+id/ks_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/background">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ks_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="> Tap SCAN ALL to enumerate key material\n> Requires root or Archon Server privileges"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:lineSpacingExtra="2dp" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<!-- Bottom info bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="@color/surface_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ks_entry_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="0 entries found"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ks_scan_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,343 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="LOGCAT VIEWER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/logcat_privilege_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privilege: checking..."
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<!-- Control buttons row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logcat_start"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="START"
|
||||
android:textColor="@color/background"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logcat_stop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="STOP"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logcat_clear"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="CLEAR"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logcat_save"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SAVE"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Filter row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TAG:"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginEnd="6dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_logcat_tag"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="filter tag..."
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:inputType="text"
|
||||
android:background="@color/surface_dark"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="MSG:"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="6dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_logcat_msg"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="filter text..."
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:inputType="text"
|
||||
android:background="@color/surface_dark"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:singleLine="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Log level filter buttons -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="LVL:"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginEnd="6dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_v"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="V"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/logcat_verbose"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_d"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="D"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/logcat_debug"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_i"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="I"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/logcat_info"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_w"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="W"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/logcat_warn"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_e"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="E"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/logcat_error"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_level_f"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:text="F"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/logcat_fatal"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_logcat_autoscroll"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="AUTO"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Status line -->
|
||||
<TextView
|
||||
android:id="@+id/logcat_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="> stopped"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="@color/surface_dark" />
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Log output -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/logcat_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/background"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<!-- Bottom info bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="@color/surface_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/logcat_line_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="0 lines"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/logcat_filter_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="min: V"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="WiFi Monitor Mode"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Status card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/monitor_chip_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:text="Detecting WiFi chip..." />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/monitor_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:text="Status: Unknown" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/monitor_firmware"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Controls -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_monitor_enable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ENABLE MONITOR MODE"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
android:textColor="@color/background"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_monitor_disable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="DISABLE MONITOR MODE"
|
||||
android:fontFamily="monospace"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="false" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_monitor_check"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CHECK STATUS"
|
||||
android:fontFamily="monospace"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Log output -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/monitor_log"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
@@ -1,241 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NETWORK SCANNER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/netscan_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Local network device discovery"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<!-- Subnet input row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SUBNET:"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_subnet"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="192.168.1"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="monospace"
|
||||
android:inputType="text"
|
||||
android:background="@color/surface_dark"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=".0/24"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Action buttons row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SCAN"
|
||||
android:textColor="@color/background"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_arp_only"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="ARP CACHE"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_clear"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="CLEAR"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<ProgressBar
|
||||
android:id="@+id/scan_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp"
|
||||
android:max="254"
|
||||
android:progress="0"
|
||||
android:progressTint="@color/terminal_green"
|
||||
android:progressBackgroundTint="@color/surface"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Status line -->
|
||||
<TextView
|
||||
android:id="@+id/scan_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="> idle"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="@color/surface_dark" />
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Results count header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:background="@color/surface">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/results_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="0 devices found"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/scan_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Device list -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/device_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/background"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="16dp" />
|
||||
|
||||
<!-- Bottom log area -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
app:cardBackgroundColor="@color/surface_dark"
|
||||
app:cardCornerRadius="4dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/scan_log"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:maxHeight="96dp"
|
||||
android:padding="8dp"
|
||||
android:text="> ready"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:scrollbars="vertical"
|
||||
android:lineSpacingExtra="1dp" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,106 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Interface and filter -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/pcap_interface"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/pcap_filter"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:hint="Filter (e.g. port 80, host 10.0.0.1)"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:background="@android:color/transparent"
|
||||
android:singleLine="true"
|
||||
android:layout_marginStart="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Controls -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_pcap_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="START"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
android:textColor="@color/background"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_pcap_stop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="STOP"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
app:cornerRadius="4dp"
|
||||
android:enabled="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pcap_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:text="0 packets" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<!-- Packet output -->
|
||||
<ScrollView
|
||||
android:id="@+id/pcap_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pcap_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
@@ -1,258 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="0dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PORT SCANNER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Target Host Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Target"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:hint="Host / IP address"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_target_host"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Port Range Row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:hint="Start port"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_port_start"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:text="1"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:hint="End port"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_port_end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:text="1024"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_common_ports"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="COMMON"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Scan / Stop Buttons -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="SCAN"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_stop"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="STOP"
|
||||
android:textColor="@color/danger"
|
||||
android:fontFamily="monospace"
|
||||
android:enabled="false"
|
||||
app:strokeColor="@color/danger"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Progress Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_progress_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Scanning..."
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_progress_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="0 / 0"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:progressTint="@color/terminal_green"
|
||||
android:progressBackgroundTint="@color/surface_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_open_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="Open: 0"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Results List -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:background="@color/background" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,359 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PROCESS INSPECTOR"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/proc_privilege_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privilege: checking..."
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<!-- Search bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_proc_search"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="Filter processes..."
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:textSize="13sp"
|
||||
android:fontFamily="monospace"
|
||||
android:inputType="text"
|
||||
android:background="@color/surface_dark"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:singleLine="true" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_proc_refresh"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="REFRESH"
|
||||
android:textColor="@color/background"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Sort buttons row -->
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_pid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="PID"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_user"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="USER"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_cpu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="CPU%"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_mem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="MEM%"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_vsz"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="VSZ"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_rss"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="RSS"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_cmd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:text="CMD"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:minWidth="0dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
app:backgroundTint="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Status line -->
|
||||
<TextView
|
||||
android:id="@+id/proc_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="> idle"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="@color/surface_dark" />
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Column header row -->
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none"
|
||||
android:background="@color/surface">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PID"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="USER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CPU%"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="MEM%"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="VSZ"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="RSS"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="STAT"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="COMMAND"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!-- Separator -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/terminal_green_dim" />
|
||||
|
||||
<!-- Process list -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/proc_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/background"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<!-- Bottom status bar -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="@color/surface_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/proc_count_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="0 processes"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/proc_sort_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="sort: PID"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,273 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SSL/TLS CHECK"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Input Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Target"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green"
|
||||
app:boxBackgroundColor="@color/surface_dark"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_hostname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="hostname (e.g. example.com)"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:inputType="textUri"
|
||||
android:imeOptions="actionDone" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green"
|
||||
app:boxBackgroundColor="@color/surface_dark"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="port (443)"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:inputType="number" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_check"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="CHECK"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Status Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/status_dot"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@color/status_offline"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Checking..."
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_protocol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="2dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_cipher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="2dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Issues Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_issues"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/danger"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ISSUES"
|
||||
android:textColor="@color/danger"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/issues_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/danger"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Certificate Chain -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_chain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CERTIFICATE CHAIN"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/chain_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Progress -->
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:indeterminate="true"
|
||||
app:indicatorColor="@color/terminal_green"
|
||||
app:trackColor="@color/surface_dark"
|
||||
app:trackThickness="3dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,177 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="WHOIS LOOKUP"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Input Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Domain / IP"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:boxStrokeColor="@color/terminal_green"
|
||||
app:hintTextColor="@color/terminal_green"
|
||||
app:boxBackgroundColor="@color/surface_dark"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_domain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="example.com or 93.184.216.34"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:inputType="textUri"
|
||||
android:imeOptions="actionDone" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_lookup"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="LOOKUP"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_raw"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="RAW"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:thumbTint="@color/terminal_green"
|
||||
app:trackTint="@color/surface_dark" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Progress -->
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:indeterminate="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:indicatorColor="@color/terminal_green"
|
||||
app:trackColor="@color/surface_dark"
|
||||
app:trackThickness="3dp" />
|
||||
|
||||
<!-- Parsed Results Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_parsed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PARSED"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/parsed_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Raw Output -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_raw"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/surface_dark"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/raw_output"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,326 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="WIFI ANALYZER"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Current Connection Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_current_connection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:strokeColor="@color/terminal_green"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Current Connection"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<!-- SSID -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SSID"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_ssid"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- BSSID -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BSSID"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_bssid"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Frequency -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Frequency"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_freq"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Channel -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Channel"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_channel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Signal Strength -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Signal"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_signal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Signal Bar -->
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_conn_signal"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:progressTint="@color/terminal_green"
|
||||
android:progressBackgroundTint="@color/surface_dark"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<!-- Link Speed -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Link Speed"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_speed"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- IP Address -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="IP Address"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_conn_ip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="--"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Scan Controls -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SCAN"
|
||||
android:textColor="@color/background"
|
||||
android:fontFamily="monospace"
|
||||
app:backgroundTint="@color/terminal_green"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_signal"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="dBm"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp"
|
||||
android:layout_marginEnd="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sort_channel"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CH"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:cornerRadius="4dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Network Count -->
|
||||
<TextView
|
||||
android:id="@+id/tv_network_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Nearby Networks (0)"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- Scan Results List -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_networks"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false" />
|
||||
|
||||
<!-- Status Text -->
|
||||
<TextView
|
||||
android:id="@+id/tv_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="> WiFi analyzer ready_"
|
||||
android:textColor="@color/terminal_green_dim"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginTop="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -1,76 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="12dp"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<!-- Status dot -->
|
||||
<View
|
||||
android:id="@+id/device_status_dot"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_marginEnd="12dp" />
|
||||
|
||||
<!-- Device info -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- IP address -->
|
||||
<TextView
|
||||
android:id="@+id/device_ip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:singleLine="true" />
|
||||
|
||||
<!-- Hostname -->
|
||||
<TextView
|
||||
android:id="@+id/device_hostname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="monospace"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginTop="2dp" />
|
||||
|
||||
<!-- MAC + Vendor -->
|
||||
<TextView
|
||||
android:id="@+id/device_mac"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="11sp"
|
||||
android:fontFamily="monospace"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginTop="1dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Vendor badge -->
|
||||
<TextView
|
||||
android:id="@+id/device_vendor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text_muted"
|
||||
android:textSize="10sp"
|
||||
android:fontFamily="monospace"
|
||||
android:gravity="end"
|
||||
android:maxWidth="100dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/shell_line_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="13sp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="1dp"
|
||||
android:paddingBottom="1dp"
|
||||
android:textColor="#D4D4D4"
|
||||
android:background="@android:color/transparent"
|
||||
android:textIsSelectable="true" />
|
||||
@@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="6dp"
|
||||
app:strokeColor="@color/terminal_green_dim"
|
||||
app:strokeWidth="1dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<!-- Signal bar column -->
|
||||
<LinearLayout
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:layout_marginEnd="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_signal_dbm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="-50"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_signal"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="4dp"
|
||||
android:max="100"
|
||||
android:progress="50"
|
||||
android:progressTint="@color/terminal_green"
|
||||
android:progressBackgroundTint="@color/surface_dark"
|
||||
android:layout_marginTop="2dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Network info column -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_ssid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NetworkName"
|
||||
android:textColor="@color/text_primary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_bssid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="00:00:00:00:00:00"
|
||||
android:textColor="@color/text_muted"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<!-- Security badge -->
|
||||
<TextView
|
||||
android:id="@+id/tv_security"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="WPA2"
|
||||
android:textColor="@color/terminal_green"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@color/surface_dark"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingTop="1dp"
|
||||
android:paddingBottom="1dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<!-- Channel -->
|
||||
<TextView
|
||||
android:id="@+id/tv_channel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CH 6"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<!-- Frequency band -->
|
||||
<TextView
|
||||
android:id="@+id/tv_band"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="2.4 GHz"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:fontFamily="monospace"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -1,153 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<group android:id="@+id/group_main"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_dashboard"
|
||||
android:icon="@android:drawable/ic_menu_compass"
|
||||
android:title="@string/nav_dashboard" />
|
||||
<item
|
||||
android:id="@+id/nav_adb_shell"
|
||||
android:icon="@android:drawable/ic_menu_sort_by_size"
|
||||
android:title="@string/nav_adb_shell" />
|
||||
</group>
|
||||
|
||||
<item android:title="@string/drawer_header_tools">
|
||||
<menu>
|
||||
<group android:id="@+id/group_tools"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_modules"
|
||||
android:icon="@android:drawable/ic_menu_manage"
|
||||
android:title="@string/nav_modules" />
|
||||
<item
|
||||
android:id="@+id/nav_messaging"
|
||||
android:icon="@android:drawable/ic_dialog_email"
|
||||
android:title="@string/nav_messaging" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:title="NON-ROOTED TOOLS">
|
||||
<menu>
|
||||
<group android:id="@+id/group_noroot_tools"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_tool_netscan"
|
||||
android:icon="@android:drawable/ic_menu_mapmode"
|
||||
android:title="Network Scanner" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_portscan"
|
||||
android:icon="@android:drawable/ic_menu_sort_by_size"
|
||||
android:title="Port Scanner" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_wifi"
|
||||
android:icon="@android:drawable/ic_menu_compass"
|
||||
android:title="WiFi Analyzer" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_dns"
|
||||
android:icon="@android:drawable/ic_menu_search"
|
||||
android:title="DNS Lookup" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_whois"
|
||||
android:icon="@android:drawable/ic_menu_info_details"
|
||||
android:title="Whois" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_ssl"
|
||||
android:icon="@android:drawable/ic_secure"
|
||||
android:title="SSL/TLS Check" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_headers"
|
||||
android:icon="@android:drawable/ic_menu_recent_history"
|
||||
android:title="HTTP Headers" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_devinfo"
|
||||
android:icon="@android:drawable/ic_menu_myplaces"
|
||||
android:title="Device Info" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:title="ROOTED TOOLS">
|
||||
<menu>
|
||||
<group android:id="@+id/group_root_tools"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_tool_pcap"
|
||||
android:icon="@android:drawable/ic_menu_upload"
|
||||
android:title="Packet Capture" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_monitor"
|
||||
android:icon="@android:drawable/ic_menu_view"
|
||||
android:title="WiFi Monitor" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_arp"
|
||||
android:icon="@android:drawable/ic_menu_mapmode"
|
||||
android:title="ARP Scanner" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_firewall"
|
||||
android:icon="@android:drawable/ic_lock_lock"
|
||||
android:title="Firewall Rules" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_processes"
|
||||
android:icon="@android:drawable/ic_menu_manage"
|
||||
android:title="Process Inspector" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_files"
|
||||
android:icon="@android:drawable/ic_menu_agenda"
|
||||
android:title="File Browser" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_logcat"
|
||||
android:icon="@android:drawable/ic_menu_sort_alphabetically"
|
||||
android:title="Logcat Viewer" />
|
||||
<item
|
||||
android:id="@+id/nav_tool_keystore"
|
||||
android:icon="@android:drawable/ic_menu_close_clear_cancel"
|
||||
android:title="Keystore Dump" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:title="@string/drawer_header_setup">
|
||||
<menu>
|
||||
<group android:id="@+id/group_setup"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_setup"
|
||||
android:icon="@drawable/ic_setup"
|
||||
android:title="@string/nav_device_setup" />
|
||||
<item
|
||||
android:id="@+id/nav_links"
|
||||
android:icon="@android:drawable/ic_menu_share"
|
||||
android:title="@string/nav_links" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:title="@string/drawer_header_settings">
|
||||
<menu>
|
||||
<group android:id="@+id/group_settings"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_settings_connection"
|
||||
android:icon="@android:drawable/ic_menu_preferences"
|
||||
android:title="@string/nav_settings_connection" />
|
||||
<item
|
||||
android:id="@+id/nav_settings_privileges"
|
||||
android:icon="@android:drawable/ic_lock_lock"
|
||||
android:title="@string/nav_settings_privileges" />
|
||||
<item
|
||||
android:id="@+id/nav_settings_appearance"
|
||||
android:icon="@android:drawable/ic_menu_view"
|
||||
android:title="@string/nav_settings_appearance" />
|
||||
<item
|
||||
android:id="@+id/nav_about"
|
||||
android:icon="@android:drawable/ic_menu_info_details"
|
||||
android:title="@string/nav_about" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
@@ -1,131 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<navigation
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/nav_graph"
|
||||
app:startDestination="@id/nav_dashboard">
|
||||
|
||||
<!-- MAIN -->
|
||||
<fragment
|
||||
android:id="@+id/nav_dashboard"
|
||||
android:name="com.darkhal.archon.ui.DashboardFragment"
|
||||
android:label="@string/nav_dashboard" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_adb_shell"
|
||||
android:name="com.darkhal.archon.ui.AdbShellFragment"
|
||||
android:label="@string/nav_adb_shell" />
|
||||
|
||||
<!-- TOOLS -->
|
||||
<fragment
|
||||
android:id="@+id/nav_modules"
|
||||
android:name="com.darkhal.archon.ui.ModulesFragment"
|
||||
android:label="@string/nav_modules" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_messaging"
|
||||
android:name="com.darkhal.archon.ui.MessagingFragment"
|
||||
android:label="@string/nav_messaging" />
|
||||
|
||||
<!-- NON-ROOTED TOOLS -->
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_netscan"
|
||||
android:name="com.darkhal.archon.ui.tools.NetworkScannerFragment"
|
||||
android:label="Network Scanner" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_portscan"
|
||||
android:name="com.darkhal.archon.ui.tools.PortScannerFragment"
|
||||
android:label="Port Scanner" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_wifi"
|
||||
android:name="com.darkhal.archon.ui.tools.WifiAnalyzerFragment"
|
||||
android:label="WiFi Analyzer" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_dns"
|
||||
android:name="com.darkhal.archon.ui.tools.DnsLookupFragment"
|
||||
android:label="DNS Lookup" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_whois"
|
||||
android:name="com.darkhal.archon.ui.tools.WhoisFragment"
|
||||
android:label="Whois" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_ssl"
|
||||
android:name="com.darkhal.archon.ui.tools.SslCheckFragment"
|
||||
android:label="SSL/TLS Check" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_headers"
|
||||
android:name="com.darkhal.archon.ui.tools.HttpHeadersFragment"
|
||||
android:label="HTTP Headers" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_devinfo"
|
||||
android:name="com.darkhal.archon.ui.tools.DeviceInfoFragment"
|
||||
android:label="Device Info" />
|
||||
|
||||
<!-- ROOTED TOOLS -->
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_pcap"
|
||||
android:name="com.darkhal.archon.ui.ToolPlaceholderFragment"
|
||||
android:label="Packet Capture" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_monitor"
|
||||
android:name="com.darkhal.archon.ui.ToolPlaceholderFragment"
|
||||
android:label="WiFi Monitor" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_arp"
|
||||
android:name="com.darkhal.archon.ui.ToolPlaceholderFragment"
|
||||
android:label="ARP Scanner" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_firewall"
|
||||
android:name="com.darkhal.archon.ui.ToolPlaceholderFragment"
|
||||
android:label="Firewall Rules" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_processes"
|
||||
android:name="com.darkhal.archon.ui.tools.ProcessInspectorFragment"
|
||||
android:label="Process Inspector" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_files"
|
||||
android:name="com.darkhal.archon.ui.tools.FileBrowserFragment"
|
||||
android:label="File Browser" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_logcat"
|
||||
android:name="com.darkhal.archon.ui.tools.LogcatViewerFragment"
|
||||
android:label="Logcat Viewer" />
|
||||
<fragment
|
||||
android:id="@+id/nav_tool_keystore"
|
||||
android:name="com.darkhal.archon.ui.tools.KeystoreDumpFragment"
|
||||
android:label="Keystore Dump" />
|
||||
|
||||
<!-- SETUP -->
|
||||
<fragment
|
||||
android:id="@+id/nav_setup"
|
||||
android:name="com.darkhal.archon.ui.SetupFragment"
|
||||
android:label="@string/nav_device_setup" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_links"
|
||||
android:name="com.darkhal.archon.ui.LinksFragment"
|
||||
android:label="@string/nav_links" />
|
||||
|
||||
<!-- SETTINGS -->
|
||||
<fragment
|
||||
android:id="@+id/nav_settings_connection"
|
||||
android:name="com.darkhal.archon.ui.ConnectionSettingsFragment"
|
||||
android:label="@string/nav_settings_connection" />
|
||||
android:id="@+id/nav_modules"
|
||||
android:name="com.darkhal.archon.ui.ModulesFragment"
|
||||
android:label="@string/nav_modules" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_settings_privileges"
|
||||
android:name="com.darkhal.archon.ui.PrivilegesSettingsFragment"
|
||||
android:label="@string/nav_settings_privileges" />
|
||||
android:id="@+id/nav_setup"
|
||||
android:name="com.darkhal.archon.ui.SetupFragment"
|
||||
android:label="@string/nav_setup" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_settings_appearance"
|
||||
android:name="com.darkhal.archon.ui.AppearanceSettingsFragment"
|
||||
android:label="@string/nav_settings_appearance" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_about"
|
||||
android:name="com.darkhal.archon.ui.AboutFragment"
|
||||
android:label="@string/nav_about" />
|
||||
android:id="@+id/nav_settings"
|
||||
android:name="com.darkhal.archon.ui.SettingsFragment"
|
||||
android:label="@string/nav_settings" />
|
||||
|
||||
</navigation>
|
||||
|
||||
@@ -15,17 +15,4 @@
|
||||
<color name="warning">#FFFFAA00</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="nav_item_color">#FF00FF41</color>
|
||||
|
||||
<!-- Logcat level colors -->
|
||||
<color name="logcat_verbose">#FF888888</color>
|
||||
<color name="logcat_debug">#FF5599FF</color>
|
||||
<color name="logcat_info">#FF00CC44</color>
|
||||
<color name="logcat_warn">#FFFFAA00</color>
|
||||
<color name="logcat_error">#FFFF4444</color>
|
||||
<color name="logcat_fatal">#FFFF2222</color>
|
||||
|
||||
<!-- File browser -->
|
||||
<color name="file_directory">#FF00CCFF</color>
|
||||
<color name="file_symlink">#FFCC66FF</color>
|
||||
<color name="file_executable">#FF00FF41</color>
|
||||
</resources>
|
||||
|
||||
@@ -2,31 +2,13 @@
|
||||
<resources>
|
||||
<string name="app_name">Archon</string>
|
||||
|
||||
<!-- Navigation - Drawer -->
|
||||
<!-- Navigation -->
|
||||
<string name="nav_dashboard">Dashboard</string>
|
||||
<string name="nav_adb_shell">ADB Shell</string>
|
||||
<string name="nav_modules">Modules</string>
|
||||
<string name="nav_device_setup">Device Setup</string>
|
||||
<string name="nav_links">Links</string>
|
||||
<string name="nav_settings_connection">Connection</string>
|
||||
<string name="nav_settings_privileges">Privileges</string>
|
||||
<string name="nav_settings_appearance">Appearance</string>
|
||||
<string name="nav_about">About</string>
|
||||
|
||||
<!-- Legacy (kept for bottom_nav.xml compatibility) -->
|
||||
<string name="nav_modules">Modules</string>
|
||||
<string name="nav_setup">Setup</string>
|
||||
<string name="nav_settings">Settings</string>
|
||||
|
||||
<!-- Drawer section headers -->
|
||||
<string name="drawer_header_tools">TOOLS</string>
|
||||
<string name="drawer_header_setup">SETUP</string>
|
||||
<string name="drawer_header_settings">SETTINGS</string>
|
||||
|
||||
<!-- Drawer header -->
|
||||
<string name="drawer_app_name">AUTARCH</string>
|
||||
<string name="drawer_open">Open navigation</string>
|
||||
<string name="drawer_close">Close navigation</string>
|
||||
|
||||
<!-- Discovery -->
|
||||
<string name="server_discovery">Server Discovery</string>
|
||||
<string name="discovery_idle">Tap SCAN to find AUTARCH</string>
|
||||
@@ -105,32 +87,4 @@
|
||||
<string name="auto_detect">AUTO-DETECT SERVER</string>
|
||||
<string name="test_connection">TEST</string>
|
||||
<string name="save_settings">SAVE</string>
|
||||
|
||||
<!-- ADB Shell -->
|
||||
<string name="adb_shell_title">ADB SHELL</string>
|
||||
<string name="adb_shell_hint">Enter command...</string>
|
||||
<string name="adb_shell_run">RUN</string>
|
||||
<string name="adb_shell_clear">CLEAR</string>
|
||||
<string name="adb_shell_welcome">> ADB shell ready. Type a command.\n</string>
|
||||
|
||||
<!-- Privileges -->
|
||||
<string name="privileges_title">PRIVILEGES</string>
|
||||
<string name="privilege_mode_label">Privilege Mode</string>
|
||||
<string name="privilege_root">Root</string>
|
||||
<string name="privilege_shizuku">Shizuku</string>
|
||||
<string name="privilege_adb">ADB</string>
|
||||
<string name="privilege_none">None (standard)</string>
|
||||
<string name="privilege_status_checking">Checking privilege status...</string>
|
||||
|
||||
<!-- Appearance -->
|
||||
<string name="appearance_title">APPEARANCE</string>
|
||||
<string name="appearance_theme_label">Theme</string>
|
||||
<string name="appearance_theme_dark">Terminal Dark</string>
|
||||
<string name="appearance_font_size">Font Size</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about_title">ABOUT</string>
|
||||
<string name="about_version_label">Version</string>
|
||||
<string name="about_copyright">Copyright 2026 DarkHal</string>
|
||||
<string name="about_description">AUTARCH Companion\nRemote device management and security toolkit.</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 DarkHal -->
|
||||
<resources>
|
||||
<style name="Theme.Archon" parent="Theme.Material3.Dark.NoActionBar">
|
||||
<item name="colorPrimary">@color/terminal_green</item>
|
||||
@@ -13,27 +12,5 @@
|
||||
<item name="android:statusBarColor">@color/background</item>
|
||||
<item name="android:navigationBarColor">@color/surface</item>
|
||||
<item name="android:windowBackground">@color/background</item>
|
||||
<item name="drawerLayoutStyle">@style/Widget.Archon.DrawerLayout</item>
|
||||
</style>
|
||||
|
||||
<!-- Toolbar title style -->
|
||||
<style name="ToolbarTitle" parent="TextAppearance.Material3.TitleLarge">
|
||||
<item name="android:fontFamily">monospace</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:letterSpacing">0.1</item>
|
||||
</style>
|
||||
|
||||
<!-- Drawer subheader text style -->
|
||||
<style name="DrawerSubheader" parent="TextAppearance.Material3.LabelSmall">
|
||||
<item name="android:fontFamily">monospace</item>
|
||||
<item name="android:textSize">11sp</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:letterSpacing">0.15</item>
|
||||
</style>
|
||||
|
||||
<!-- DrawerLayout scrim -->
|
||||
<style name="Widget.Archon.DrawerLayout" parent="Widget.Material3.DrawerLayout">
|
||||
<item name="scrimColor">#CC000000</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
# Linking Archon as a Git Submodule of AUTARCH
|
||||
|
||||
This guide walks through setting up Archon (the Android companion app) as a git submodule inside the AUTARCH repository, hosted on a self-hosted Gitea instance.
|
||||
|
||||
**Assumed URLs:**
|
||||
- AUTARCH: `https://gitea.example.com/you/autarch`
|
||||
- Archon: `https://gitea.example.com/you/archon`
|
||||
|
||||
---
|
||||
|
||||
## 1. Initial Setup — Create Both Repos on Gitea
|
||||
|
||||
### Create the repos on Gitea
|
||||
|
||||
Log into your Gitea instance and create two repositories:
|
||||
|
||||
1. Go to `https://gitea.example.com` → **+** → **New Repository**
|
||||
2. Create `autarch` (do not initialize with README if you already have local files)
|
||||
3. Repeat for `archon`
|
||||
|
||||
### Push AUTARCH
|
||||
|
||||
```bash
|
||||
cd /path/to/autarch
|
||||
git init # if not already a git repo
|
||||
git remote add origin https://gitea.example.com/you/autarch.git
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### Push Archon
|
||||
|
||||
```bash
|
||||
cd /path/to/archon
|
||||
git init
|
||||
git remote add origin https://gitea.example.com/you/archon.git
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Add Archon as a Submodule
|
||||
|
||||
From the **AUTARCH repository root**, run:
|
||||
|
||||
```bash
|
||||
cd /path/to/autarch
|
||||
git submodule add https://gitea.example.com/you/archon.git Archon
|
||||
```
|
||||
|
||||
This does three things:
|
||||
- Clones the Archon repo into `autarch/Archon/`
|
||||
- Creates (or updates) `.gitmodules` in the AUTARCH root
|
||||
- Stages both `.gitmodules` and the new `Archon` directory pointer
|
||||
|
||||
If you prefer SSH instead of HTTPS:
|
||||
|
||||
```bash
|
||||
git submodule add git@gitea.example.com:you/archon.git Archon
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Commit the Submodule Reference
|
||||
|
||||
After adding the submodule, two things are staged:
|
||||
|
||||
- `.gitmodules` — a config file mapping the submodule path to its URL
|
||||
- `Archon` — not the Archon files themselves, but a **pointer** (a specific commit hash) to the Archon repo
|
||||
|
||||
Commit both:
|
||||
|
||||
```bash
|
||||
git status
|
||||
# On branch main
|
||||
# Changes to be committed:
|
||||
# new file: .gitmodules
|
||||
# new file: Archon
|
||||
|
||||
git commit -m "Add Archon as git submodule"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
AUTARCH's repo now contains a reference to a specific commit in Archon — not the Archon files directly. This is intentional: submodules are pinned to a commit, not a branch.
|
||||
|
||||
---
|
||||
|
||||
## 4. `.gitmodules` Example
|
||||
|
||||
After running `git submodule add`, your `.gitmodules` file will look like this:
|
||||
|
||||
```ini
|
||||
[submodule "Archon"]
|
||||
path = Archon
|
||||
url = https://gitea.example.com/you/archon.git
|
||||
```
|
||||
|
||||
If you want to track a specific branch (optional, see pitfalls):
|
||||
|
||||
```ini
|
||||
[submodule "Archon"]
|
||||
path = Archon
|
||||
url = https://gitea.example.com/you/archon.git
|
||||
branch = main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Cloning AUTARCH with Archon
|
||||
|
||||
### Option A — Clone everything at once (recommended)
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://gitea.example.com/you/autarch.git
|
||||
```
|
||||
|
||||
This clones AUTARCH and immediately initializes and checks out Archon at the pinned commit.
|
||||
|
||||
### Option B — Clone AUTARCH first, pull Archon later
|
||||
|
||||
```bash
|
||||
git clone https://gitea.example.com/you/autarch.git
|
||||
cd autarch
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
`--init` is needed the first time because the submodule isn't initialized yet. After that, use `git submodule update` without `--init`.
|
||||
|
||||
To also pull nested submodules (if Archon ever gains its own submodules):
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Updating Archon to a Newer Commit
|
||||
|
||||
The submodule is pinned to a specific commit. To move AUTARCH's pointer to a newer Archon commit:
|
||||
|
||||
```bash
|
||||
# Step into the submodule
|
||||
cd Archon
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
# Step back out to AUTARCH
|
||||
cd ..
|
||||
|
||||
# The submodule pointer has changed — stage and commit it
|
||||
git add Archon
|
||||
git commit -m "Update Archon submodule to latest"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
After this, anyone who runs `git submodule update` in their AUTARCH clone will get the newer Archon commit.
|
||||
|
||||
---
|
||||
|
||||
## 7. Gitea UI — How Submodules Are Displayed
|
||||
|
||||
When you browse to `https://gitea.example.com/you/autarch` in the Gitea web UI, the `Archon` directory will appear in the file list with a special icon and a label like:
|
||||
|
||||
```
|
||||
Archon @ a3f92c1
|
||||
```
|
||||
|
||||
The `@ a3f92c1` is a clickable link that takes you directly to that commit in the `archon` repository. Gitea resolves the link automatically as long as both repos are on the same Gitea instance and the URL in `.gitmodules` matches.
|
||||
|
||||
If the submodule URL points to an external host (e.g., GitHub), Gitea will still show the `@ hash` label but the link will point to the external URL.
|
||||
|
||||
---
|
||||
|
||||
## 8. CI/CD — Checking Out Submodules in Gitea Actions
|
||||
|
||||
If you use Gitea Actions (workflow syntax is identical to GitHub Actions), the default `actions/checkout` step does **not** pull submodules. Add `submodules: true` to fix this:
|
||||
|
||||
```yaml
|
||||
name: AUTARCH CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout AUTARCH with submodules
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true # fetches Archon at the pinned commit
|
||||
# submodules: recursive # use this if submodules have their own submodules
|
||||
|
||||
- name: Build
|
||||
run: make build
|
||||
```
|
||||
|
||||
For private submodules on the same Gitea instance, you may need to configure an SSH key or access token in the workflow secrets and set the submodule URL to use SSH.
|
||||
|
||||
---
|
||||
|
||||
## 9. Common Pitfalls
|
||||
|
||||
### Detached HEAD in the submodule
|
||||
|
||||
When you run `git submodule update`, the submodule is checked out at a specific commit — not a branch. This is called a **detached HEAD** state. If you `cd Archon` and make commits while in detached HEAD, those commits are not on any branch and can be lost.
|
||||
|
||||
Fix: before making changes inside the submodule, always check out a branch first:
|
||||
|
||||
```bash
|
||||
cd Archon
|
||||
git checkout main
|
||||
# now make changes, commit, push
|
||||
```
|
||||
|
||||
### Forgot to commit after updating the submodule
|
||||
|
||||
Running `cd Archon && git pull` updates the Archon files locally but does **not** automatically update AUTARCH's pointer to the new commit. You must come back to the AUTARCH root and commit:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
git add Archon
|
||||
git commit -m "Update Archon submodule"
|
||||
```
|
||||
|
||||
If you push AUTARCH without doing this, the pointer still points to the old Archon commit and collaborators won't get the update.
|
||||
|
||||
### SSH vs HTTPS
|
||||
|
||||
Choose one scheme and be consistent. If your team uses SSH keys for Gitea authentication, use the SSH URL in `.gitmodules`:
|
||||
|
||||
```ini
|
||||
url = git@gitea.example.com:you/archon.git
|
||||
```
|
||||
|
||||
If you use HTTPS with a token, use the HTTPS URL. Mixing them causes authentication failures for people whose environment only has one configured.
|
||||
|
||||
You can override the URL locally (without touching `.gitmodules`) using:
|
||||
|
||||
```bash
|
||||
git config submodule.Archon.url git@gitea.example.com:you/archon.git
|
||||
```
|
||||
|
||||
This writes to `.git/config` and is not committed, so it only affects your local clone.
|
||||
|
||||
### Cloning without `--recurse-submodules`
|
||||
|
||||
If someone clones AUTARCH normally and then tries to build, the `Archon/` directory will exist but be **empty**. They need to run:
|
||||
|
||||
```bash
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
Document this in your project README so contributors know to expect it.
|
||||
@@ -2,4 +2,3 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
android.useAndroidX=true
|
||||
kotlin.code.style=official
|
||||
android.nonTransitiveRClass=true
|
||||
android.aapt2FromMavenOverride=/home/snake/android-sdk/build-tools/36.0.0/aapt2
|
||||
|
||||
0
autarch_companion/gradlew.bat
vendored
Executable file → Normal file
0
autarch_companion/gradlew.bat
vendored
Executable file → Normal file
@@ -1 +1 @@
|
||||
sdk.dir=/home/snake/android-sdk
|
||||
sdk.dir=C:/Users/mdavi/AppData/Local/Android/Sdk
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolution {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
rootProject.name = "ArchonCompose"
|
||||
include(":app")
|
||||
@@ -1,5 +1,5 @@
|
||||
[llama]
|
||||
model_path = C:\Track 1\model\sssnake7070\HauhauCS\Qwen3.5-9B-Uncensored-HauhauCS-Aggressive\Qwen3.5-9B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf
|
||||
model_path = C:\she\autarch\models\darkHal.gguf
|
||||
n_ctx = 2048
|
||||
n_threads = 4
|
||||
n_gpu_layers = -1
|
||||
@@ -29,7 +29,7 @@ no_banner = false
|
||||
host = 127.0.0.1
|
||||
port = 55553
|
||||
username = msf
|
||||
password = msf
|
||||
password = msdf
|
||||
ssl = true
|
||||
|
||||
[osint]
|
||||
@@ -76,7 +76,7 @@ default_port = 80
|
||||
execution_timeout = 120
|
||||
|
||||
[upnp]
|
||||
enabled = false
|
||||
enabled = true
|
||||
internal_ip = 10.0.0.26
|
||||
refresh_hours = 12
|
||||
mappings = 443:TCP,51820:UDP,8080:TCP
|
||||
@@ -108,7 +108,7 @@ bt_require_security = true
|
||||
[web]
|
||||
host = 0.0.0.0
|
||||
port = 8181
|
||||
secret_key =
|
||||
secret_key = 23088243f11ce0b135c64413073c8c9fc0ecf83711d5f892b68f95b348a54007
|
||||
mcp_port = 8081
|
||||
|
||||
[revshell]
|
||||
@@ -150,18 +150,18 @@ threat_threshold_auto_respond = 40
|
||||
log_max_entries = 1000
|
||||
|
||||
[agents]
|
||||
backend = claude
|
||||
local_max_steps = 200
|
||||
backend = local
|
||||
local_max_steps = 20
|
||||
local_verbose = true
|
||||
claude_enabled = false
|
||||
claude_model = claude-sonnet-4-6
|
||||
claude_max_tokens = 16384
|
||||
claude_max_steps = 200
|
||||
claude_max_steps = 30
|
||||
openai_enabled = false
|
||||
openai_model = gpt-4o
|
||||
openai_base_url = https://api.openai.com/v1
|
||||
openai_max_tokens = 16384
|
||||
openai_max_steps = 200
|
||||
openai_max_steps = 30
|
||||
|
||||
[mcp]
|
||||
enabled = false
|
||||
|
||||
@@ -80,7 +80,7 @@ PARAMS: {{"question": "your question"}}
|
||||
self,
|
||||
llm: LLM = None,
|
||||
tools: ToolRegistry = None,
|
||||
max_steps: int = 200,
|
||||
max_steps: int = 20,
|
||||
verbose: bool = True
|
||||
):
|
||||
"""Initialize the agent.
|
||||
|
||||
@@ -1,871 +0,0 @@
|
||||
"""
|
||||
Autarch Android Forensics — forensic acquisition and IOC scanning for Android devices.
|
||||
by: SsSnake
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
_manager = None
|
||||
|
||||
|
||||
def get_android_forensics_manager():
|
||||
global _manager
|
||||
if _manager is None:
|
||||
_manager = AutarchAndroidManager()
|
||||
return _manager
|
||||
|
||||
|
||||
class AutarchAndroidManager:
|
||||
"""Forensic acquisition and IOC scanning for Android devices."""
|
||||
|
||||
IOC_DATA_DIR = Path(__file__).parent.parent / 'data' / 'ioc'
|
||||
ACQ_DATA_DIR = Path(__file__).parent.parent / 'data' / 'android_forensics'
|
||||
|
||||
def __init__(self):
|
||||
self._ioc_db = None # lazy-loaded
|
||||
|
||||
# ── Helpers ─────────────────────────────────────────────────────
|
||||
|
||||
def _hw(self):
|
||||
from core.hardware import get_hardware_manager
|
||||
return get_hardware_manager()
|
||||
|
||||
def _adb(self, serial, cmd, timeout=60):
|
||||
"""Run an ADB shell command, return stdout string."""
|
||||
result = self._hw().adb_shell_raw(serial, cmd, timeout=timeout)
|
||||
if isinstance(result, dict):
|
||||
return result.get('output', '') or ''
|
||||
return str(result or '')
|
||||
|
||||
def _acq_dir(self, serial, acq_id):
|
||||
d = self.ACQ_DATA_DIR / serial / acq_id
|
||||
d.mkdir(parents=True, exist_ok=True)
|
||||
return d
|
||||
|
||||
def _new_acq_id(self):
|
||||
return datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
|
||||
# ── IOC Database ────────────────────────────────────────────────
|
||||
|
||||
def load_ioc_database(self, force=False):
|
||||
"""Lazy-load and merge all IOC data from data/ioc/. Returns merged dict."""
|
||||
if self._ioc_db is not None and not force:
|
||||
return self._ioc_db
|
||||
|
||||
db = {
|
||||
'packages': {}, # pkg_name -> {name, source, severity}
|
||||
'certs': {}, # sha1/sha256 -> {name, source}
|
||||
'domains': {}, # domain -> {name, source}
|
||||
'ips': set(),
|
||||
'file_paths': {}, # path -> {name, source}
|
||||
'processes': {}, # proc_name -> {name, source}
|
||||
'hashes': {}, # sha256 -> {name, source}
|
||||
}
|
||||
|
||||
# 1. Stalkerware ioc.yaml + watchware.yaml
|
||||
for fname in ('ioc.yaml', 'watchware.yaml'):
|
||||
fpath = self.IOC_DATA_DIR / 'stalkerware' / fname
|
||||
if fpath.exists():
|
||||
self._parse_stalkerware_yaml(fpath, db)
|
||||
|
||||
# 2. Amnesty investigations
|
||||
amnesty_dir = self.IOC_DATA_DIR / 'spyware' / 'amnesty'
|
||||
if amnesty_dir.exists():
|
||||
for campaign_dir in sorted(amnesty_dir.iterdir()):
|
||||
if campaign_dir.is_dir():
|
||||
self._parse_investigation(campaign_dir, db)
|
||||
|
||||
# 3. MVT indicators
|
||||
mvt_dir = self.IOC_DATA_DIR / 'spyware' / 'mvt'
|
||||
if mvt_dir.exists():
|
||||
for campaign_dir in sorted(mvt_dir.iterdir()):
|
||||
if campaign_dir.is_dir():
|
||||
self._parse_investigation(campaign_dir, db)
|
||||
|
||||
# 4. Citizen Lab campaigns
|
||||
cl_dir = self.IOC_DATA_DIR / 'spyware' / 'citizen_lab'
|
||||
if cl_dir.exists():
|
||||
for campaign_dir in sorted(cl_dir.iterdir()):
|
||||
if campaign_dir.is_dir():
|
||||
self._parse_investigation(campaign_dir, db)
|
||||
|
||||
# 5. iMazing indicators (recursive)
|
||||
imazing_dir = self.IOC_DATA_DIR / 'spyware' / 'imazing'
|
||||
if imazing_dir.exists():
|
||||
for item in imazing_dir.rglob('*'):
|
||||
if item.is_dir():
|
||||
self._parse_investigation(item, db)
|
||||
|
||||
# 6. Existing stalkerware_signatures.json
|
||||
sigs_path = Path(__file__).parent.parent / 'data' / 'stalkerware_signatures.json'
|
||||
if sigs_path.exists():
|
||||
self._parse_sigs_json(sigs_path, db)
|
||||
|
||||
# Convert ips set to list for JSON serialisation
|
||||
db['ips'] = list(db['ips'])
|
||||
|
||||
self._ioc_db = db
|
||||
self._save_index(db)
|
||||
return db
|
||||
|
||||
def _parse_stalkerware_yaml(self, path, db):
|
||||
"""Parse stalkerware/watchware ioc.yaml into db."""
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
return
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
data = yaml.safe_load(f)
|
||||
if not isinstance(data, dict):
|
||||
return
|
||||
for vendor, info in data.items():
|
||||
if not isinstance(info, dict):
|
||||
continue
|
||||
source = f'stalkerware/{path.name}:{vendor}'
|
||||
for pkg in info.get('packages', []) or []:
|
||||
if pkg:
|
||||
db['packages'][pkg] = {'name': vendor, 'source': source, 'severity': 'high'}
|
||||
for cert in info.get('certificates', []) or []:
|
||||
if cert:
|
||||
db['certs'][cert.lower()] = {'name': vendor, 'source': source}
|
||||
for domain in (info.get('domains', []) or []) + (info.get('c2', []) or []) + (info.get('website', []) or []):
|
||||
if domain:
|
||||
db['domains'][domain.lower()] = {'name': vendor, 'source': source}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_investigation(self, campaign_dir, db):
|
||||
"""Parse a campaign directory for IOC text files and STIX2."""
|
||||
name = campaign_dir.name
|
||||
source = f'spyware/{campaign_dir.parent.name}/{name}'
|
||||
|
||||
for f in campaign_dir.iterdir():
|
||||
if not f.is_file():
|
||||
continue
|
||||
fname = f.name.lower()
|
||||
|
||||
if fname in ('domains.txt', 'domains'):
|
||||
self._load_txt_lines(f, db['domains'], name, source)
|
||||
elif fname in ('package_names.txt', 'package_names'):
|
||||
self._load_txt_lines(f, db['packages'], name, source, extra={'severity': 'critical'})
|
||||
elif fname in ('processes.txt', 'processes'):
|
||||
self._load_txt_lines(f, db['processes'], name, source)
|
||||
elif fname in ('file_paths.txt', 'file_paths'):
|
||||
self._load_txt_lines(f, db['file_paths'], name, source)
|
||||
elif fname in ('ips.txt', 'ip_addresses.txt', 'ip-addresses.txt'):
|
||||
self._load_txt_set(f, db['ips'])
|
||||
elif fname.endswith('.stix2') or fname.endswith('_stix.json'):
|
||||
self._parse_stix(f, db, name, source)
|
||||
elif fname in ('sha256.txt', 'sha256.csv'):
|
||||
self._load_hashes(f, db['hashes'], name, source)
|
||||
elif fname == 'package_cert_hashes.txt':
|
||||
self._load_txt_lines(f, db['certs'], name, source)
|
||||
elif fname.endswith('.json') and 'ioc' in fname:
|
||||
self._parse_ioc_json(f, db, name, source)
|
||||
elif fname.endswith('.csv') and 'ioc' in fname:
|
||||
self._parse_ioc_csv(f, db, name, source)
|
||||
|
||||
def _load_txt_lines(self, path, target_dict, name, source, extra=None):
|
||||
"""Load one-indicator-per-line text file into a dict."""
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
for line in f:
|
||||
line = line.strip().lower()
|
||||
if line and not line.startswith('#'):
|
||||
entry = {'name': name, 'source': source}
|
||||
if extra:
|
||||
entry.update(extra)
|
||||
target_dict[line] = entry
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _load_txt_set(self, path, target_set):
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#'):
|
||||
target_set.add(line)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _load_hashes(self, path, target_dict, name, source):
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(',')
|
||||
h = parts[0].strip().lower()
|
||||
if h and len(h) in (32, 40, 64):
|
||||
target_dict[h] = {'name': name, 'source': source}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_stix(self, path, db, name, source):
|
||||
"""Parse a STIX2 JSON file for indicators."""
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
data = json.load(f)
|
||||
objects = data.get('objects', []) if isinstance(data, dict) else []
|
||||
for obj in objects:
|
||||
if obj.get('type') != 'indicator':
|
||||
continue
|
||||
pattern = obj.get('pattern', '')
|
||||
for m in re.findall(r"domain-name:value\s*=\s*'([^']+)'", pattern):
|
||||
db['domains'][m.lower()] = {'name': name, 'source': source}
|
||||
for m in re.findall(r"file:hashes\.'[^']+'\s*=\s*'([a-fA-F0-9]+)'", pattern):
|
||||
db['hashes'][m.lower()] = {'name': name, 'source': source}
|
||||
for m in re.findall(r"process:name\s*=\s*'([^']+)'", pattern):
|
||||
db['processes'][m.lower()] = {'name': name, 'source': source}
|
||||
for m in re.findall(r"(?:file:name|directory:path)\s*=\s*'([^']+)'", pattern):
|
||||
db['file_paths'][m] = {'name': name, 'source': source}
|
||||
for m in re.findall(r"ipv[46]-addr:value\s*=\s*'([^']+)'", pattern):
|
||||
db['ips'].add(m)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_ioc_json(self, path, db, name, source):
|
||||
try:
|
||||
with open(path, encoding='utf-8', errors='ignore') as f:
|
||||
data = json.load(f)
|
||||
items = data.get('items', data.get('iocs', [])) if isinstance(data, dict) else data
|
||||
if not isinstance(items, list):
|
||||
return
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
itype = item.get('type', '').lower()
|
||||
val = str(item.get('value', item.get('indicator', ''))).strip().lower()
|
||||
if not val:
|
||||
continue
|
||||
if 'domain' in itype:
|
||||
db['domains'][val] = {'name': name, 'source': source}
|
||||
elif 'ip' in itype:
|
||||
db['ips'].add(val)
|
||||
elif 'hash' in itype or 'sha' in itype or 'md5' in itype:
|
||||
db['hashes'][val] = {'name': name, 'source': source}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_ioc_csv(self, path, db, name, source):
|
||||
try:
|
||||
import csv
|
||||
with open(path, encoding='utf-8', errors='ignore', newline='') as f:
|
||||
reader = csv.DictReader(f)
|
||||
for row in reader:
|
||||
val = (row.get('value') or row.get('indicator') or row.get('domain') or '').strip().lower()
|
||||
itype = (row.get('type') or row.get('indicator_type') or '').lower()
|
||||
if not val:
|
||||
continue
|
||||
if 'domain' in itype:
|
||||
db['domains'][val] = {'name': name, 'source': source}
|
||||
elif 'hash' in itype or 'sha256' in itype:
|
||||
db['hashes'][val] = {'name': name, 'source': source}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_sigs_json(self, path, db):
|
||||
"""Merge existing stalkerware_signatures.json into db."""
|
||||
try:
|
||||
with open(path, encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
for vendor, info in data.get('stalkerware', {}).items():
|
||||
source = f'stalkerware_signatures.json:{vendor}'
|
||||
sev = info.get('severity', 'high')
|
||||
for pkg in info.get('packages', []):
|
||||
if pkg and pkg not in db['packages']:
|
||||
db['packages'][pkg] = {'name': vendor, 'source': source, 'severity': sev}
|
||||
for spyware in data.get('government_spyware', []):
|
||||
name = spyware.get('name', 'unknown')
|
||||
source = f'stalkerware_signatures.json:{name}'
|
||||
for ind in spyware.get('indicators', []):
|
||||
itype = ind.get('type', '')
|
||||
val = ind.get('value', '')
|
||||
if not val:
|
||||
continue
|
||||
if itype == 'process':
|
||||
db['processes'][val.lower()] = {'name': name, 'source': source}
|
||||
elif itype == 'domain':
|
||||
db['domains'][val.lower()] = {'name': name, 'source': source, 'severity': 'critical'}
|
||||
elif itype == 'file_path':
|
||||
db['file_paths'][val] = {'name': name, 'source': source}
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _save_index(self, db):
|
||||
try:
|
||||
def _count_dirs(d):
|
||||
return sum(1 for p in d.iterdir() if p.is_dir()) if d.exists() else 0
|
||||
|
||||
ips = db.get('ips', [])
|
||||
index = {
|
||||
'generated': datetime.now().isoformat(),
|
||||
'counts': {
|
||||
'packages': len(db.get('packages', {})),
|
||||
'certs': len(db.get('certs', {})),
|
||||
'domains': len(db.get('domains', {})),
|
||||
'ips': len(ips) if not isinstance(ips, set) else len(ips),
|
||||
'file_paths': len(db.get('file_paths', {})),
|
||||
'processes': len(db.get('processes', {})),
|
||||
'hashes': len(db.get('hashes', {})),
|
||||
},
|
||||
'sources': {
|
||||
'stalkerware_ioc_yaml': (self.IOC_DATA_DIR / 'stalkerware' / 'ioc.yaml').exists(),
|
||||
'amnesty_investigations': _count_dirs(self.IOC_DATA_DIR / 'spyware' / 'amnesty'),
|
||||
'mvt_campaigns': _count_dirs(self.IOC_DATA_DIR / 'spyware' / 'mvt'),
|
||||
'citizen_lab_campaigns': _count_dirs(self.IOC_DATA_DIR / 'spyware' / 'citizen_lab'),
|
||||
'yara_rules': sum(1 for _ in (self.IOC_DATA_DIR / 'yara').rglob('*.yar*'))
|
||||
if (self.IOC_DATA_DIR / 'yara').exists() else 0,
|
||||
},
|
||||
}
|
||||
self.IOC_DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||
with open(self.IOC_DATA_DIR / 'index.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(index, f, indent=2)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def get_ioc_stats(self):
|
||||
"""Return IOC database statistics (from index.json if available)."""
|
||||
idx_path = self.IOC_DATA_DIR / 'index.json'
|
||||
if idx_path.exists():
|
||||
try:
|
||||
with open(idx_path, encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
db = self.load_ioc_database()
|
||||
return {'counts': {k: len(v) for k, v in db.items() if isinstance(v, (dict, list))}}
|
||||
|
||||
def reload_ioc_database(self):
|
||||
"""Force reload all IOC data from disk."""
|
||||
self._ioc_db = None
|
||||
return self.load_ioc_database(force=True)
|
||||
|
||||
# ── Acquisition Methods ─────────────────────────────────────────
|
||||
|
||||
def acquire_packages(self, serial):
|
||||
"""Get list of installed packages with paths and system/user classification."""
|
||||
try:
|
||||
all_out = self._adb(serial, 'pm list packages -f', timeout=30)
|
||||
sys_out = self._adb(serial, 'pm list packages -s', timeout=30)
|
||||
|
||||
# Build system package set from -s output (format: "package:com.pkg.name")
|
||||
sys_pkgs = set()
|
||||
for line in sys_out.splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith('package:'):
|
||||
sys_pkgs.add(line[8:].strip())
|
||||
|
||||
# Parse -f output (format: "package:/path/to/base.apk=com.pkg.name")
|
||||
packages = []
|
||||
for line in all_out.splitlines():
|
||||
line = line.strip()
|
||||
if not line.startswith('package:'):
|
||||
continue
|
||||
line = line[8:] # strip "package:"
|
||||
# Split on last '=' to handle paths that may contain '='
|
||||
eq_pos = line.rfind('=')
|
||||
if eq_pos == -1:
|
||||
pkg_name = line
|
||||
apk_path = ''
|
||||
else:
|
||||
apk_path = line[:eq_pos]
|
||||
pkg_name = line[eq_pos + 1:]
|
||||
pkg_name = pkg_name.strip()
|
||||
if pkg_name:
|
||||
packages.append({
|
||||
'package': pkg_name,
|
||||
'path': apk_path.strip(),
|
||||
'system': pkg_name in sys_pkgs,
|
||||
})
|
||||
return {'ok': True, 'packages': packages, 'total': len(packages)}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'packages': []}
|
||||
|
||||
def acquire_processes(self, serial):
|
||||
"""Get list of running processes."""
|
||||
try:
|
||||
out = self._adb(serial, 'ps -A', timeout=30)
|
||||
lines = [l for l in out.splitlines() if l.strip()]
|
||||
return {'ok': True, 'output': out, 'count': max(0, len(lines) - 1)}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_getprop(self, serial):
|
||||
"""Get all system properties via getprop."""
|
||||
try:
|
||||
out = self._adb(serial, 'getprop', timeout=30)
|
||||
props = {}
|
||||
for line in out.splitlines():
|
||||
m = re.match(r'\[(.+)\]:\s*\[(.*)\]\s*$', line)
|
||||
if m:
|
||||
props[m.group(1)] = m.group(2)
|
||||
return {'ok': True, 'props': props, 'output': out}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'props': {}}
|
||||
|
||||
def acquire_settings(self, serial):
|
||||
"""Get global, secure, and system settings."""
|
||||
try:
|
||||
result = {}
|
||||
for ns in ('global', 'secure', 'system'):
|
||||
out = self._adb(serial, f'settings list {ns}', timeout=30)
|
||||
settings = {}
|
||||
for line in out.splitlines():
|
||||
if '=' in line:
|
||||
k, _, v = line.partition('=')
|
||||
settings[k.strip()] = v.strip()
|
||||
result[ns] = settings
|
||||
return {'ok': True, 'settings': result}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'settings': {}}
|
||||
|
||||
def acquire_services(self, serial):
|
||||
"""List all running Android services."""
|
||||
try:
|
||||
out = self._adb(serial, 'service list', timeout=30)
|
||||
return {'ok': True, 'output': out, 'count': len(out.splitlines())}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_dumpsys(self, serial):
|
||||
"""Full dumpsys output (may be large)."""
|
||||
try:
|
||||
out = self._adb(serial, 'dumpsys', timeout=180)
|
||||
return {'ok': True, 'output': out, 'size': len(out)}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_logcat(self, serial):
|
||||
"""Recent logcat entries (last 1000 lines)."""
|
||||
try:
|
||||
out = self._adb(serial, 'logcat -d -t 1000', timeout=60)
|
||||
return {'ok': True, 'output': out, 'lines': len(out.splitlines())}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_tmp_files(self, serial):
|
||||
"""List files in /data/local/tmp/."""
|
||||
try:
|
||||
out = self._adb(serial, 'ls -la /data/local/tmp/ 2>/dev/null', timeout=15)
|
||||
return {'ok': True, 'output': out, 'lines': len(out.splitlines())}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_files(self, serial, max_depth=5):
|
||||
"""Recursive file listing from common paths."""
|
||||
try:
|
||||
paths = ['/data/local/tmp', '/sdcard/Android/data', '/data/data',
|
||||
'/system/app', '/data/app']
|
||||
results = []
|
||||
for base in paths:
|
||||
out = self._adb(
|
||||
serial,
|
||||
f'find {base} -maxdepth {max_depth} -type f 2>/dev/null | head -500',
|
||||
timeout=30,
|
||||
)
|
||||
for line in out.splitlines():
|
||||
line = line.strip()
|
||||
if line:
|
||||
results.append({'path': line})
|
||||
return {'ok': True, 'files': results, 'total': len(results)}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'files': []}
|
||||
|
||||
def acquire_logs(self, serial):
|
||||
"""Full logcat with thread-time format (last 2000 lines)."""
|
||||
try:
|
||||
out = self._adb(serial, 'logcat -d -v threadtime -t 2000', timeout=90)
|
||||
return {'ok': True, 'output': out, 'lines': len(out.splitlines())}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'output': ''}
|
||||
|
||||
def acquire_bugreport_info(self, serial):
|
||||
"""Collect bugreport header info (device state, battery, memory) without full zip."""
|
||||
try:
|
||||
sections = {}
|
||||
for name, cmd in [
|
||||
('memory', 'cat /proc/meminfo'),
|
||||
('cpuinfo', 'cat /proc/cpuinfo | head -40'),
|
||||
('uptime', 'cat /proc/uptime'),
|
||||
('mounts', 'cat /proc/mounts'),
|
||||
]:
|
||||
sections[name] = self._adb(serial, cmd, timeout=15)
|
||||
return {'ok': True, 'sections': sections}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'sections': {}}
|
||||
|
||||
# ── IOC Scanning ────────────────────────────────────────────────
|
||||
|
||||
def scan_packages(self, serial, packages_data=None):
|
||||
"""Match installed packages against IOC package names."""
|
||||
db = self.load_ioc_database()
|
||||
if packages_data is None:
|
||||
result = self.acquire_packages(serial)
|
||||
if not result.get('ok'):
|
||||
return {'ok': False, 'error': result.get('error'), 'findings': []}
|
||||
packages_data = result['packages']
|
||||
|
||||
findings = []
|
||||
for pkg_info in packages_data:
|
||||
pkg = pkg_info.get('package', '').strip()
|
||||
if pkg and pkg in db['packages']:
|
||||
match = db['packages'][pkg]
|
||||
findings.append({
|
||||
'package': pkg,
|
||||
'path': pkg_info.get('path', ''),
|
||||
'system': pkg_info.get('system', False),
|
||||
'threat_name': match['name'],
|
||||
'source': match['source'],
|
||||
'severity': match.get('severity', 'high'),
|
||||
'type': 'package_match',
|
||||
})
|
||||
return {
|
||||
'ok': True,
|
||||
'total_scanned': len(packages_data),
|
||||
'findings': findings,
|
||||
'clean': len(findings) == 0,
|
||||
}
|
||||
|
||||
def scan_certificates(self, serial):
|
||||
"""Check APK signing cert hashes against known-bad certs in IOC database."""
|
||||
db = self.load_ioc_database()
|
||||
findings = []
|
||||
if not db.get('certs'):
|
||||
return {'ok': True, 'findings': [], 'note': 'No cert IOCs loaded'}
|
||||
try:
|
||||
pkg_result = self.acquire_packages(serial)
|
||||
# Only check user-installed (non-system) packages; limit to 100 for speed
|
||||
packages = [p for p in pkg_result.get('packages', []) if not p.get('system')][:100]
|
||||
for pkg_info in packages:
|
||||
pkg = pkg_info.get('package', '')
|
||||
if not pkg:
|
||||
continue
|
||||
out = self._adb(serial, f'pm dump {pkg} 2>/dev/null | grep -A2 "Signing"', timeout=15)
|
||||
for line in out.splitlines():
|
||||
m = re.search(r'([a-fA-F0-9]{40,64})', line)
|
||||
if m:
|
||||
cert_hash = m.group(1).lower()
|
||||
if cert_hash in db['certs']:
|
||||
match = db['certs'][cert_hash]
|
||||
findings.append({
|
||||
'package': pkg,
|
||||
'cert_hash': cert_hash,
|
||||
'threat_name': match['name'],
|
||||
'source': match['source'],
|
||||
'severity': 'critical',
|
||||
'type': 'cert_match',
|
||||
})
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'findings': findings}
|
||||
return {'ok': True, 'findings': findings, 'clean': len(findings) == 0}
|
||||
|
||||
def scan_network_indicators(self, serial):
|
||||
"""Check DNS/proxy settings and active TCP connections against IOC domains/IPs."""
|
||||
db = self.load_ioc_database()
|
||||
findings = []
|
||||
try:
|
||||
props = self.acquire_getprop(serial).get('props', {})
|
||||
for key, val in props.items():
|
||||
if 'dns' in key.lower() and val and val.lower() in db['domains']:
|
||||
match = db['domains'][val.lower()]
|
||||
findings.append({
|
||||
'type': 'dns_property', 'key': key, 'value': val,
|
||||
'threat_name': match['name'], 'source': match['source'], 'severity': 'high',
|
||||
})
|
||||
|
||||
ioc_ips = set(db.get('ips', []))
|
||||
if ioc_ips:
|
||||
tcp_out = self._adb(serial, 'cat /proc/net/tcp 2>/dev/null', timeout=15)
|
||||
for line in tcp_out.splitlines()[1:]:
|
||||
parts = line.strip().split()
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
try:
|
||||
remote_hex = parts[2]
|
||||
ip_hex, port_hex = remote_hex.split(':')
|
||||
# /proc/net/tcp stores IPs in little-endian hex
|
||||
ip = '.'.join(str(int(ip_hex[i:i+2], 16)) for i in (6, 4, 2, 0))
|
||||
port = int(port_hex, 16)
|
||||
if ip not in ('0.0.0.0', '127.0.0.1') and ip in ioc_ips:
|
||||
findings.append({
|
||||
'type': 'tcp_connection', 'remote_ip': ip, 'remote_port': port,
|
||||
'severity': 'critical', 'source': 'network_scan',
|
||||
'threat_name': 'Known malicious IP',
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'findings': findings}
|
||||
return {'ok': True, 'findings': findings, 'clean': len(findings) == 0}
|
||||
|
||||
def scan_file_indicators(self, serial):
|
||||
"""Check device for known spyware artifact file paths."""
|
||||
db = self.load_ioc_database()
|
||||
if not db.get('file_paths'):
|
||||
return {'ok': True, 'findings': [], 'note': 'No file path IOCs loaded'}
|
||||
findings = []
|
||||
try:
|
||||
for fpath, match in list(db['file_paths'].items())[:200]:
|
||||
out = self._adb(serial, f'ls "{fpath}" 2>/dev/null', timeout=5)
|
||||
if out.strip() and 'No such file' not in out:
|
||||
findings.append({
|
||||
'type': 'file_path',
|
||||
'path': fpath,
|
||||
'threat_name': match['name'],
|
||||
'source': match['source'],
|
||||
'severity': 'critical',
|
||||
})
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'findings': findings}
|
||||
return {'ok': True, 'findings': findings, 'clean': len(findings) == 0}
|
||||
|
||||
def scan_process_indicators(self, serial):
|
||||
"""Cross-reference running processes against known spyware process names."""
|
||||
db = self.load_ioc_database()
|
||||
if not db.get('processes'):
|
||||
return {'ok': True, 'findings': [], 'note': 'No process IOCs loaded'}
|
||||
findings = []
|
||||
try:
|
||||
proc_output = self.acquire_processes(serial).get('output', '').lower()
|
||||
for proc_name, match in db['processes'].items():
|
||||
if proc_name and proc_name in proc_output:
|
||||
findings.append({
|
||||
'type': 'process_match',
|
||||
'process': proc_name,
|
||||
'threat_name': match['name'],
|
||||
'source': match['source'],
|
||||
'severity': 'critical',
|
||||
})
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e), 'findings': findings}
|
||||
return {'ok': True, 'findings': findings, 'clean': len(findings) == 0}
|
||||
|
||||
# ── SLM Heuristic Scanner ────────────────────────────────────────
|
||||
|
||||
def _heuristic_scan(self, data_type, items, threshold=0.65):
|
||||
"""Run SLM heuristic pass on a list of items via the local LLM.
|
||||
data_type: 'packages' | 'processes' | 'network' | 'files'
|
||||
Returns list of {item, score, reason, category} for items scoring >= threshold."""
|
||||
if not items:
|
||||
return []
|
||||
try:
|
||||
from core.llm import get_llm, LLMError
|
||||
llm = get_llm()
|
||||
if not llm or not llm.is_loaded:
|
||||
return []
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
prompts = {
|
||||
'packages': (
|
||||
'Classify each Android package name for stalkerware/spyware/adware risk. '
|
||||
'Score 0.0-1.0. High risk: names impersonating system apps, random strings, '
|
||||
'unknown publishers with device-admin-sounding names. '
|
||||
'Return only a JSON array: [{"item":"...","score":0.0,"reason":"...","category":"stalkerware|adware|suspicious|clean"}]'
|
||||
),
|
||||
'processes': (
|
||||
'Classify each Android process name for malware risk. Score 0.0-1.0. '
|
||||
'Suspicious: random hex strings, names mimicking system processes with slight misspellings. '
|
||||
'Return only a JSON array: [{"item":"...","score":0.0,"reason":"...","category":"malware|suspicious|clean"}]'
|
||||
),
|
||||
'network': (
|
||||
'Classify each domain or IP for C2/malware beacon risk. Score 0.0-1.0. '
|
||||
'High risk: DGA-looking names, dynamic DNS (duckdns, no-ip, ddns), unusual TLDs, high-entropy subdomains. '
|
||||
'Return only a JSON array: [{"item":"...","score":0.0,"reason":"...","category":"c2_beacon|dga_domain|suspicious|clean"}]'
|
||||
),
|
||||
'files': (
|
||||
'Classify each Android file path for spyware/stalkerware artifact risk. Score 0.0-1.0. '
|
||||
'High risk: hidden directories, paths in /data/local/tmp, surveillance-sounding names. '
|
||||
'Return only a JSON array: [{"item":"...","score":0.0,"reason":"...","category":"spyware|suspicious|clean"}]'
|
||||
),
|
||||
}
|
||||
base_prompt = prompts.get(data_type, prompts['packages'])
|
||||
|
||||
findings = []
|
||||
# Process in chunks of 50 (on-device SLM token budget)
|
||||
for i in range(0, len(items), 50):
|
||||
chunk = items[i:i + 50]
|
||||
prompt = f'{base_prompt}\n\nItems:\n' + '\n'.join(str(x) for x in chunk)
|
||||
try:
|
||||
raw = get_llm().generate(prompt, max_tokens=800)
|
||||
# Extract JSON array from response
|
||||
m = re.search(r'\[.*\]', raw, re.DOTALL)
|
||||
if not m:
|
||||
continue
|
||||
parsed = json.loads(m.group(0))
|
||||
for entry in parsed:
|
||||
if isinstance(entry, dict) and float(entry.get('score', 0)) >= threshold:
|
||||
findings.append({
|
||||
'item': str(entry.get('item', '')),
|
||||
'score': float(entry.get('score', 0)),
|
||||
'reason': str(entry.get('reason', '')),
|
||||
'category': str(entry.get('category', 'suspicious')),
|
||||
'confidence': float(entry.get('score', 0)),
|
||||
'heuristic': True,
|
||||
'data_type': data_type,
|
||||
})
|
||||
except Exception:
|
||||
continue
|
||||
return findings
|
||||
|
||||
# ── Composite Operations ─────────────────────────────────────────
|
||||
|
||||
def full_acquisition(self, serial):
|
||||
"""Run all acquisition modules and all IOC scans. Save results to disk."""
|
||||
acq_id = self._new_acq_id()
|
||||
acq_dir = self._acq_dir(serial, acq_id)
|
||||
|
||||
report = {
|
||||
'acq_id': acq_id,
|
||||
'serial': serial,
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'modules': {},
|
||||
'ioc_findings': [],
|
||||
}
|
||||
|
||||
module_map = {
|
||||
'packages': self.acquire_packages,
|
||||
'processes': self.acquire_processes,
|
||||
'getprop': self.acquire_getprop,
|
||||
'settings': self.acquire_settings,
|
||||
'services': self.acquire_services,
|
||||
'logcat': self.acquire_logcat,
|
||||
'tmp_files': self.acquire_tmp_files,
|
||||
'files': self.acquire_files,
|
||||
'logs': self.acquire_logs,
|
||||
'bugreport': self.acquire_bugreport_info,
|
||||
}
|
||||
|
||||
for mod_name, func in module_map.items():
|
||||
try:
|
||||
result = func(serial)
|
||||
report['modules'][mod_name] = result
|
||||
with open(acq_dir / f'{mod_name}.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, indent=2, default=str)
|
||||
except Exception as e:
|
||||
report['modules'][mod_name] = {'ok': False, 'error': str(e)}
|
||||
|
||||
# IOC scans — reuse already-acquired package list
|
||||
packages_data = report['modules'].get('packages', {}).get('packages', [])
|
||||
all_findings = []
|
||||
for scan_name, scan_func in [
|
||||
('packages', lambda s: self.scan_packages(s, packages_data)),
|
||||
('network', self.scan_network_indicators),
|
||||
('files', self.scan_file_indicators),
|
||||
('processes', self.scan_process_indicators),
|
||||
]:
|
||||
try:
|
||||
scan_result = scan_func(serial)
|
||||
for finding in scan_result.get('findings', []):
|
||||
finding['scan_type'] = scan_name
|
||||
all_findings.append(finding)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
report['ioc_findings'] = all_findings
|
||||
report['scan_summary'] = {
|
||||
'total_findings': len(all_findings),
|
||||
'critical': sum(1 for f in all_findings if f.get('severity') == 'critical'),
|
||||
'high': sum(1 for f in all_findings if f.get('severity') == 'high'),
|
||||
'clean': len(all_findings) == 0,
|
||||
}
|
||||
|
||||
with open(acq_dir / 'report.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
|
||||
return report
|
||||
|
||||
def get_acquisition_list(self, serial):
|
||||
"""List past acquisitions for a device."""
|
||||
device_dir = self.ACQ_DATA_DIR / serial
|
||||
if not device_dir.exists():
|
||||
return []
|
||||
acquisitions = []
|
||||
for acq_dir in sorted(device_dir.iterdir(), reverse=True):
|
||||
if not acq_dir.is_dir():
|
||||
continue
|
||||
report_path = acq_dir / 'report.json'
|
||||
entry = {'acq_id': acq_dir.name, 'has_report': report_path.exists()}
|
||||
if report_path.exists():
|
||||
try:
|
||||
with open(report_path, encoding='utf-8') as f:
|
||||
r = json.load(f)
|
||||
entry['timestamp'] = r.get('timestamp', acq_dir.name)
|
||||
entry['modules'] = list(r.get('modules', {}).keys())
|
||||
entry['findings'] = r.get('scan_summary', {}).get('total_findings', 0)
|
||||
except Exception:
|
||||
pass
|
||||
acquisitions.append(entry)
|
||||
return acquisitions
|
||||
|
||||
def export_report(self, serial, acq_id):
|
||||
"""Load a saved acquisition report from disk."""
|
||||
report_path = self.ACQ_DATA_DIR / serial / acq_id / 'report.json'
|
||||
if not report_path.exists():
|
||||
return {'ok': False, 'error': 'Report not found'}
|
||||
try:
|
||||
with open(report_path, encoding='utf-8') as f:
|
||||
return {'ok': True, 'report': json.load(f), 'path': str(report_path)}
|
||||
except Exception as e:
|
||||
return {'ok': False, 'error': str(e)}
|
||||
|
||||
# ── Direct (WebUSB) Mode ─────────────────────────────────────────
|
||||
|
||||
def get_direct_commands(self, operation):
|
||||
"""Return ADB shell commands for browser-side WebUSB execution."""
|
||||
commands = {
|
||||
'packages': 'pm list packages -f',
|
||||
'packages_sys': 'pm list packages -s',
|
||||
'processes': 'ps -A',
|
||||
'getprop': 'getprop',
|
||||
'settings_global': 'settings list global',
|
||||
'settings_secure': 'settings list secure',
|
||||
'settings_system': 'settings list system',
|
||||
'services': 'service list',
|
||||
'logcat': 'logcat -d -t 1000',
|
||||
'tmp_files': 'ls -la /data/local/tmp/ 2>/dev/null',
|
||||
'tcp_connections': 'cat /proc/net/tcp 2>/dev/null',
|
||||
}
|
||||
if operation == 'full':
|
||||
return commands
|
||||
cmd = commands.get(operation)
|
||||
return {operation: cmd} if cmd else {}
|
||||
|
||||
def parse_direct_output(self, operation, raw_output):
|
||||
"""Parse raw ADB output returned from a WebUSB browser client."""
|
||||
if operation == 'packages':
|
||||
packages = []
|
||||
for line in raw_output.splitlines():
|
||||
line = line.strip()
|
||||
if not line.startswith('package:'):
|
||||
continue
|
||||
line = line[8:]
|
||||
eq_pos = line.rfind('=')
|
||||
if eq_pos == -1:
|
||||
pkg_name, apk_path = line, ''
|
||||
else:
|
||||
apk_path, pkg_name = line[:eq_pos], line[eq_pos + 1:]
|
||||
pkg_name = pkg_name.strip()
|
||||
if pkg_name:
|
||||
packages.append({'package': pkg_name, 'path': apk_path.strip(), 'system': False})
|
||||
return {'ok': True, 'packages': packages, 'total': len(packages)}
|
||||
|
||||
elif operation == 'processes':
|
||||
lines = [l for l in raw_output.splitlines() if l.strip()]
|
||||
return {'ok': True, 'output': raw_output, 'count': max(0, len(lines) - 1)}
|
||||
|
||||
elif operation == 'getprop':
|
||||
props = {}
|
||||
for line in raw_output.splitlines():
|
||||
m = re.match(r'\[(.+)\]:\s*\[(.*)\]\s*$', line)
|
||||
if m:
|
||||
props[m.group(1)] = m.group(2)
|
||||
return {'ok': True, 'props': props, 'output': raw_output}
|
||||
|
||||
else:
|
||||
return {'ok': True, 'output': raw_output}
|
||||
@@ -405,18 +405,10 @@ class AutonomyDaemon:
|
||||
return
|
||||
|
||||
try:
|
||||
# Read step limit from config based on the active LLM backend
|
||||
from core.config import Config
|
||||
cfg = Config()
|
||||
backend = cfg.get('autarch', 'llm_backend', fallback='local')
|
||||
step_key = f'{backend}_max_steps'
|
||||
agent_settings = cfg.get_agent_settings()
|
||||
max_steps = agent_settings.get(step_key, agent_settings.get('local_max_steps', 200))
|
||||
|
||||
agent = Agent(
|
||||
llm=llm_inst,
|
||||
tools=get_tool_registry(),
|
||||
max_steps=max_steps,
|
||||
max_steps=15,
|
||||
verbose=False,
|
||||
)
|
||||
result = agent.run(task)
|
||||
|
||||
@@ -140,17 +140,17 @@ class Config:
|
||||
},
|
||||
'agents': {
|
||||
'backend': 'local',
|
||||
'local_max_steps': '200',
|
||||
'local_max_steps': '20',
|
||||
'local_verbose': 'true',
|
||||
'claude_enabled': 'false',
|
||||
'claude_model': 'claude-sonnet-4-6',
|
||||
'claude_max_tokens': '16384',
|
||||
'claude_max_steps': '200',
|
||||
'claude_max_steps': '30',
|
||||
'openai_enabled': 'false',
|
||||
'openai_model': 'gpt-4o',
|
||||
'openai_base_url': 'https://api.openai.com/v1',
|
||||
'openai_max_tokens': '16384',
|
||||
'openai_max_steps': '200',
|
||||
'openai_max_steps': '30',
|
||||
},
|
||||
'hal_memory': {
|
||||
'max_bytes': str(4 * 1024 * 1024 * 1024), # 4GB default
|
||||
@@ -539,17 +539,17 @@ class Config:
|
||||
"""Get agent configuration settings."""
|
||||
return {
|
||||
'backend': self.get('agents', 'backend', 'local'),
|
||||
'local_max_steps': self.get_int('agents', 'local_max_steps', 200),
|
||||
'local_max_steps': self.get_int('agents', 'local_max_steps', 20),
|
||||
'local_verbose': self.get_bool('agents', 'local_verbose', True),
|
||||
'claude_enabled': self.get_bool('agents', 'claude_enabled', False),
|
||||
'claude_model': self.get('agents', 'claude_model', 'claude-sonnet-4-6'),
|
||||
'claude_max_tokens': self.get_int('agents', 'claude_max_tokens', 16384),
|
||||
'claude_max_steps': self.get_int('agents', 'claude_max_steps', 200),
|
||||
'claude_max_steps': self.get_int('agents', 'claude_max_steps', 30),
|
||||
'openai_enabled': self.get_bool('agents', 'openai_enabled', False),
|
||||
'openai_model': self.get('agents', 'openai_model', 'gpt-4o'),
|
||||
'openai_base_url': self.get('agents', 'openai_base_url', 'https://api.openai.com/v1'),
|
||||
'openai_max_tokens': self.get_int('agents', 'openai_max_tokens', 16384),
|
||||
'openai_max_steps': self.get_int('agents', 'openai_max_steps', 200),
|
||||
'openai_max_steps': self.get_int('agents', 'openai_max_steps', 30),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
||||
258
core/cve_db.py
258
core/cve_db.py
@@ -1,258 +0,0 @@
|
||||
"""
|
||||
Autarch CVE Database — CVE lookup for Android packages via OSV.dev.
|
||||
by: SsSnake
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
_db_instance = None
|
||||
_db_lock = threading.Lock()
|
||||
|
||||
|
||||
def get_cve_db():
|
||||
global _db_instance
|
||||
if _db_instance is None:
|
||||
with _db_lock:
|
||||
if _db_instance is None:
|
||||
_db_instance = CveDatabase()
|
||||
return _db_instance
|
||||
|
||||
|
||||
class CveDatabase:
|
||||
"""CVE lookup for Android packages. Uses OSV.dev as primary data source."""
|
||||
|
||||
DATA_DIR = Path(__file__).parent.parent / 'data' / 'ioc' / 'cve'
|
||||
OSV_QUERY_URL = 'https://api.osv.dev/v1/query'
|
||||
OSV_BATCH_URL = 'https://api.osv.dev/v1/querybatch'
|
||||
|
||||
def __init__(self):
|
||||
self.DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||
self._cache = {} # package_name -> [vuln_dicts]
|
||||
self._stats_cache = None
|
||||
self._lock = threading.Lock()
|
||||
self._last_query = None
|
||||
|
||||
def get_cve_for_package(self, package_name, version=None) -> list:
|
||||
"""Query OSV.dev for CVEs affecting an Android package."""
|
||||
with self._lock:
|
||||
if package_name in self._cache:
|
||||
return self._cache[package_name]
|
||||
|
||||
try:
|
||||
body = {
|
||||
"package": {
|
||||
"name": package_name,
|
||||
"ecosystem": "Android"
|
||||
}
|
||||
}
|
||||
if version is not None:
|
||||
body["version"] = version
|
||||
|
||||
response = self._query_osv(body)
|
||||
vulns = response.get("vulns", [])
|
||||
|
||||
results = []
|
||||
for vuln in vulns:
|
||||
parsed = self._parse_vuln(vuln, package_name)
|
||||
results.append(parsed)
|
||||
|
||||
with self._lock:
|
||||
self._cache[package_name] = results
|
||||
self._last_query = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
return results
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def get_cve_for_android_sdk(self, sdk_version) -> list:
|
||||
"""Query OSV.dev for CVEs affecting a specific Android SDK version."""
|
||||
package_name = f"android:{sdk_version}"
|
||||
try:
|
||||
body = {
|
||||
"package": {
|
||||
"name": package_name,
|
||||
"ecosystem": "Android"
|
||||
}
|
||||
}
|
||||
|
||||
response = self._query_osv(body)
|
||||
vulns = response.get("vulns", [])
|
||||
|
||||
results = []
|
||||
for vuln in vulns:
|
||||
parsed = self._parse_vuln(vuln, package_name)
|
||||
results.append(parsed)
|
||||
|
||||
with self._lock:
|
||||
self._cache[package_name] = results
|
||||
self._last_query = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
return results
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def check_packages_batch(self, packages: list) -> dict:
|
||||
"""Query OSV.dev for CVEs affecting multiple Android packages at once."""
|
||||
if not packages:
|
||||
return {}
|
||||
|
||||
try:
|
||||
results = {}
|
||||
# Split into chunks of 50
|
||||
chunk_size = 50
|
||||
for i in range(0, len(packages), chunk_size):
|
||||
chunk = packages[i:i + chunk_size]
|
||||
queries = [
|
||||
{"package": {"name": p["name"], "ecosystem": "Android"}}
|
||||
for p in chunk
|
||||
]
|
||||
body = {"queries": queries}
|
||||
|
||||
data = json.dumps(body).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
self.OSV_BATCH_URL,
|
||||
data=data,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "Autarch/1.0"
|
||||
},
|
||||
method="POST"
|
||||
)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||
response = json.loads(resp.read().decode("utf-8"))
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
batch_results = response.get("results", [])
|
||||
for idx, result in enumerate(batch_results):
|
||||
if idx >= len(chunk):
|
||||
break
|
||||
pkg_name = chunk[idx]["name"]
|
||||
vulns = result.get("vulns", [])
|
||||
parsed_vulns = [self._parse_vuln(v, pkg_name) for v in vulns]
|
||||
results[pkg_name] = parsed_vulns
|
||||
|
||||
with self._lock:
|
||||
self._cache[pkg_name] = parsed_vulns
|
||||
|
||||
with self._lock:
|
||||
if results:
|
||||
self._last_query = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
return results
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
def get_stats(self) -> dict:
|
||||
"""Return basic stats about the CVE database cache."""
|
||||
with self._lock:
|
||||
return {
|
||||
"total_cached": len(self._cache),
|
||||
"last_query": self._last_query,
|
||||
"data_dir": str(self.DATA_DIR)
|
||||
}
|
||||
|
||||
def _query_osv(self, body: dict) -> dict:
|
||||
"""POST a JSON body to the OSV.dev query endpoint. Returns parsed JSON or {}."""
|
||||
try:
|
||||
data = json.dumps(body).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
self.OSV_QUERY_URL,
|
||||
data=data,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "Autarch/1.0"
|
||||
},
|
||||
method="POST"
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||
return json.loads(resp.read().decode("utf-8"))
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
def _parse_vuln(self, vuln: dict, package_name: str) -> dict:
|
||||
"""Extract standardised CVE fields from an OSV vulnerability object."""
|
||||
# cve_id: prefer alias starting with "CVE-", else use vuln id
|
||||
cve_id = vuln.get("id", "UNKNOWN")
|
||||
for alias in vuln.get("aliases", []):
|
||||
if alias.startswith("CVE-"):
|
||||
cve_id = alias
|
||||
break
|
||||
|
||||
# severity: try database_specific first, then severity array score, normalise
|
||||
raw_severity = (
|
||||
vuln.get("database_specific", {}).get("severity")
|
||||
or vuln.get("severity", [{}])[0].get("score", "UNKNOWN")
|
||||
)
|
||||
severity = self._normalise_severity(raw_severity)
|
||||
|
||||
# description: summary or details, capped at 500 chars
|
||||
description = vuln.get("summary", vuln.get("details", ""))[:500]
|
||||
|
||||
# patched_version: look for a "fixed" event in affected ranges
|
||||
patched_version = "unknown"
|
||||
affected_list = vuln.get("affected", [{}])
|
||||
if affected_list:
|
||||
ranges = affected_list[0].get("ranges", [])
|
||||
for r in ranges:
|
||||
for event in r.get("events", []):
|
||||
if "fixed" in event:
|
||||
patched_version = event["fixed"]
|
||||
break
|
||||
if patched_version != "unknown":
|
||||
break
|
||||
|
||||
return {
|
||||
"package": package_name,
|
||||
"cve_id": cve_id,
|
||||
"severity": severity,
|
||||
"description": description,
|
||||
"patched_version": patched_version,
|
||||
"source": "osv.dev"
|
||||
}
|
||||
|
||||
def _normalise_severity(self, raw) -> str:
|
||||
"""Map a raw severity string or CVSS score to critical/high/medium/low."""
|
||||
if raw is None or raw == "UNKNOWN":
|
||||
return "medium"
|
||||
|
||||
raw_str = str(raw).strip().upper()
|
||||
|
||||
# Direct label match
|
||||
label_map = {
|
||||
"CRITICAL": "critical",
|
||||
"HIGH": "high",
|
||||
"MEDIUM": "medium",
|
||||
"MODERATE": "medium",
|
||||
"LOW": "low",
|
||||
"NONE": "low"
|
||||
}
|
||||
if raw_str in label_map:
|
||||
return label_map[raw_str]
|
||||
|
||||
# Try numeric CVSS score
|
||||
try:
|
||||
score = float(raw_str)
|
||||
if score >= 9.0:
|
||||
return "critical"
|
||||
elif score >= 7.0:
|
||||
return "high"
|
||||
elif score >= 4.0:
|
||||
return "medium"
|
||||
else:
|
||||
return "low"
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# CVSS vector strings often start with digits after the last colon
|
||||
# e.g. "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
|
||||
# Fall back to medium if we can't parse it
|
||||
return "medium"
|
||||
259
core/keystore.py
259
core/keystore.py
@@ -1,259 +0,0 @@
|
||||
"""
|
||||
AUTARCH Encrypted Keystore
|
||||
Per-user encrypted storage for API keys, passwords, and credentials.
|
||||
|
||||
Stores secrets in keystore.xml in the user data directory using AES-256-CBC
|
||||
encryption from the existing vault module. Secrets are separated by user
|
||||
account so multi-user deployments don't leak across accounts.
|
||||
|
||||
The keystore file format is XML for human-inspectability of the structure
|
||||
(though all values are encrypted). Each entry has:
|
||||
- A unique key name
|
||||
- The encrypted value (base64-encoded)
|
||||
- The user who owns it
|
||||
- A timestamp
|
||||
- An optional category (api_key, password, token, certificate, etc.)
|
||||
|
||||
Usage:
|
||||
from core.keystore import get_keystore
|
||||
|
||||
ks = get_keystore()
|
||||
|
||||
# Store a secret for the current user
|
||||
ks.set('claude_api_key', 'sk-ant-...', category='api_key')
|
||||
|
||||
# Retrieve it
|
||||
key = ks.get('claude_api_key') # Returns '' if not set
|
||||
|
||||
# List all keys for the current user
|
||||
ks.keys() # ['claude_api_key', 'openai_api_key']
|
||||
|
||||
# Store for a specific user
|
||||
ks.set('shodan_key', 'abc123', user='admin', category='api_key')
|
||||
|
||||
# Delete
|
||||
ks.delete('old_key')
|
||||
"""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
from xml.dom import minidom
|
||||
|
||||
_log = logging.getLogger('autarch.keystore')
|
||||
|
||||
# Import encryption functions from the existing vault
|
||||
from core.vault import _derive_key, _encrypt, _decrypt
|
||||
|
||||
|
||||
def _get_default_user() -> str:
|
||||
"""Get the current user identity for key ownership."""
|
||||
from core.paths import get_user_profile_path
|
||||
profile_path = get_user_profile_path()
|
||||
if profile_path.exists():
|
||||
try:
|
||||
with open(profile_path) as f:
|
||||
profile = json.load(f)
|
||||
return profile.get('username', 'default')
|
||||
except Exception:
|
||||
pass
|
||||
return 'default'
|
||||
|
||||
|
||||
class Keystore:
|
||||
"""Encrypted per-user secrets keystore backed by XML."""
|
||||
|
||||
def __init__(self, keystore_path: Path = None, master_password: str = ''):
|
||||
from core.paths import get_keystore_path
|
||||
self._path = keystore_path or get_keystore_path()
|
||||
self._master = master_password
|
||||
self._salt = None
|
||||
self._entries: Dict[str, Dict] = {} # key -> {value, user, category, timestamp, salt}
|
||||
self._load()
|
||||
|
||||
def _load(self):
|
||||
"""Load and decrypt the keystore from disk."""
|
||||
if not self._path.exists():
|
||||
_log.info(f'No keystore found at {self._path}, starting fresh')
|
||||
return
|
||||
|
||||
try:
|
||||
tree = ET.parse(str(self._path))
|
||||
root = tree.getroot()
|
||||
|
||||
self._salt = base64.b64decode(root.get('salt', ''))
|
||||
|
||||
for entry in root.findall('entry'):
|
||||
key_name = entry.get('name', '')
|
||||
if not key_name:
|
||||
continue
|
||||
|
||||
self._entries[key_name] = {
|
||||
'encrypted_value': entry.get('value', ''),
|
||||
'user': entry.get('user', 'default'),
|
||||
'category': entry.get('category', ''),
|
||||
'timestamp': entry.get('timestamp', ''),
|
||||
'iv': entry.get('iv', ''),
|
||||
}
|
||||
|
||||
_log.info(f'Loaded keystore with {len(self._entries)} entries')
|
||||
except Exception as e:
|
||||
_log.error(f'Failed to load keystore: {e}')
|
||||
|
||||
def _save(self):
|
||||
"""Encrypt and save the keystore to disk."""
|
||||
try:
|
||||
root = ET.Element('keystore')
|
||||
root.set('version', '1')
|
||||
|
||||
if self._salt is None:
|
||||
self._salt = os.urandom(32)
|
||||
root.set('salt', base64.b64encode(self._salt).decode())
|
||||
root.set('updated', str(int(time.time())))
|
||||
|
||||
for key_name, data in sorted(self._entries.items()):
|
||||
entry = ET.SubElement(root, 'entry')
|
||||
entry.set('name', key_name)
|
||||
entry.set('value', data.get('encrypted_value', ''))
|
||||
entry.set('iv', data.get('iv', ''))
|
||||
entry.set('user', data.get('user', 'default'))
|
||||
entry.set('category', data.get('category', ''))
|
||||
entry.set('timestamp', data.get('timestamp', ''))
|
||||
|
||||
# Pretty-print the XML
|
||||
rough = ET.tostring(root, encoding='unicode')
|
||||
parsed = minidom.parseString(rough)
|
||||
pretty = parsed.toprettyxml(indent=' ', encoding='utf-8')
|
||||
|
||||
self._path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self._path, 'wb') as f:
|
||||
f.write(pretty)
|
||||
|
||||
_log.info(f'Saved keystore with {len(self._entries)} entries')
|
||||
except Exception as e:
|
||||
_log.error(f'Failed to save keystore: {e}')
|
||||
|
||||
def set(self, key: str, value: str, user: str = None, category: str = ''):
|
||||
"""Store an encrypted secret."""
|
||||
if user is None:
|
||||
user = _get_default_user()
|
||||
|
||||
if self._salt is None:
|
||||
self._salt = os.urandom(32)
|
||||
|
||||
# Derive encryption key from salt + master password
|
||||
enc_key = _derive_key(self._salt, self._master)
|
||||
|
||||
# Encrypt the value
|
||||
iv, ciphertext = _encrypt(value.encode('utf-8'), enc_key)
|
||||
|
||||
self._entries[key] = {
|
||||
'encrypted_value': base64.b64encode(ciphertext).decode(),
|
||||
'iv': base64.b64encode(iv).decode(),
|
||||
'user': user,
|
||||
'category': category,
|
||||
'timestamp': str(int(time.time())),
|
||||
}
|
||||
|
||||
self._save()
|
||||
_log.info(f'Stored secret: {key} (user={user}, category={category})')
|
||||
|
||||
def get(self, key: str, user: str = None) -> str:
|
||||
"""Retrieve a decrypted secret. Returns '' if not found."""
|
||||
if user is None:
|
||||
user = _get_default_user()
|
||||
|
||||
entry = self._entries.get(key)
|
||||
if not entry:
|
||||
return ''
|
||||
|
||||
# Check user ownership
|
||||
if entry['user'] != user and entry['user'] != 'shared':
|
||||
_log.warning(f'Access denied: {key} belongs to {entry["user"]}, not {user}')
|
||||
return ''
|
||||
|
||||
try:
|
||||
enc_key = _derive_key(self._salt, self._master)
|
||||
iv = base64.b64decode(entry['iv'])
|
||||
ciphertext = base64.b64decode(entry['encrypted_value'])
|
||||
plaintext = _decrypt(iv, ciphertext, enc_key)
|
||||
return plaintext.decode('utf-8')
|
||||
except Exception as e:
|
||||
_log.error(f'Failed to decrypt {key}: {e}')
|
||||
return ''
|
||||
|
||||
def delete(self, key: str, user: str = None):
|
||||
"""Delete a secret."""
|
||||
if user is None:
|
||||
user = _get_default_user()
|
||||
|
||||
entry = self._entries.get(key)
|
||||
if entry and (entry['user'] == user or entry['user'] == 'shared'):
|
||||
del self._entries[key]
|
||||
self._save()
|
||||
_log.info(f'Deleted secret: {key}')
|
||||
|
||||
def keys(self, user: str = None, category: str = None) -> List[str]:
|
||||
"""List key names for a user, optionally filtered by category."""
|
||||
if user is None:
|
||||
user = _get_default_user()
|
||||
|
||||
result = []
|
||||
for key, data in self._entries.items():
|
||||
if data['user'] != user and data['user'] != 'shared':
|
||||
continue
|
||||
if category and data.get('category', '') != category:
|
||||
continue
|
||||
result.append(key)
|
||||
return sorted(result)
|
||||
|
||||
def get_all_for_user(self, user: str = None) -> Dict[str, str]:
|
||||
"""Get all decrypted secrets for a user as a dict."""
|
||||
if user is None:
|
||||
user = _get_default_user()
|
||||
return {k: self.get(k, user) for k in self.keys(user)}
|
||||
|
||||
def get_metadata(self, key: str) -> Optional[Dict]:
|
||||
"""Get metadata (user, category, timestamp) for a key without decrypting."""
|
||||
entry = self._entries.get(key)
|
||||
if not entry:
|
||||
return None
|
||||
return {
|
||||
'user': entry['user'],
|
||||
'category': entry.get('category', ''),
|
||||
'timestamp': entry.get('timestamp', ''),
|
||||
}
|
||||
|
||||
def migrate_from_vault(self):
|
||||
"""Import secrets from the old vault.enc into the new keystore."""
|
||||
from core.vault import get_vault
|
||||
vault = get_vault()
|
||||
migrated = 0
|
||||
for key in vault.keys():
|
||||
value = vault.get(key)
|
||||
if value and key not in self._entries:
|
||||
# Guess category from key name
|
||||
category = 'api_key' if 'api_key' in key else 'credential'
|
||||
self.set(key, value, user='default', category=category)
|
||||
migrated += 1
|
||||
if migrated:
|
||||
_log.info(f'Migrated {migrated} secrets from vault to keystore')
|
||||
return migrated
|
||||
|
||||
|
||||
# Singleton
|
||||
_keystore_instance: Optional[Keystore] = None
|
||||
|
||||
|
||||
def get_keystore(master_password: str = '') -> Keystore:
|
||||
"""Get the global keystore instance."""
|
||||
global _keystore_instance
|
||||
if _keystore_instance is None:
|
||||
_keystore_instance = Keystore(master_password=master_password)
|
||||
return _keystore_instance
|
||||
@@ -1,280 +0,0 @@
|
||||
"""
|
||||
AUTARCH Local Agent
|
||||
Lightweight client that runs on the user's machine and executes
|
||||
commands locally, streaming results back to the AUTARCH server.
|
||||
|
||||
This makes the web UI feel like AUTARCH is running on the user's
|
||||
machine — scans, tool output, file operations all happen locally.
|
||||
|
||||
Usage:
|
||||
python3 autarch-agent.py --server https://10.0.0.1:8181
|
||||
|
||||
The agent:
|
||||
1. Connects to the AUTARCH server via WebSocket
|
||||
2. Authenticates with the user's token
|
||||
3. Receives command requests from the server
|
||||
4. Executes them locally (subprocess)
|
||||
5. Streams stdout/stderr back in real-time
|
||||
6. Reports system info (OS, arch, hostname, IP) on connect
|
||||
|
||||
Protocol:
|
||||
Server -> Agent: {"type": "exec", "id": "xxx", "command": "nmap -sV 10.0.0.1"}
|
||||
Agent -> Server: {"type": "output", "id": "xxx", "stream": "stdout", "data": "..."}
|
||||
Agent -> Server: {"type": "output", "id": "xxx", "stream": "stderr", "data": "..."}
|
||||
Agent -> Server: {"type": "done", "id": "xxx", "exit_code": 0}
|
||||
Agent -> Server: {"type": "sysinfo", "hostname": "...", "os": "...", ...}
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import socket
|
||||
import subprocess
|
||||
import ssl
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import websockets
|
||||
except ImportError:
|
||||
print("Installing websockets...")
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "websockets", "-q"])
|
||||
import websockets
|
||||
|
||||
|
||||
def get_system_info():
|
||||
"""Collect local system information to send on connect."""
|
||||
info = {
|
||||
"hostname": socket.gethostname(),
|
||||
"os": platform.system(),
|
||||
"os_version": platform.version(),
|
||||
"arch": platform.machine(),
|
||||
"python": platform.python_version(),
|
||||
"username": os.getenv("USER", os.getenv("USERNAME", "unknown")),
|
||||
"home": str(Path.home()),
|
||||
"cwd": os.getcwd(),
|
||||
"pid": os.getpid(),
|
||||
}
|
||||
|
||||
# Network interfaces
|
||||
try:
|
||||
info["ip"] = socket.gethostbyname(socket.gethostname())
|
||||
except Exception:
|
||||
info["ip"] = "unknown"
|
||||
|
||||
# Available tools
|
||||
tools = {}
|
||||
for tool in ["nmap", "tcpdump", "wireshark", "python3", "git", "curl",
|
||||
"wget", "ssh", "netstat", "ss", "ip", "ifconfig", "arp",
|
||||
"dig", "nslookup", "traceroute", "ping", "whois",
|
||||
"openssl", "nikto", "sqlmap", "hydra", "john", "hashcat"]:
|
||||
path = shutil.which(tool)
|
||||
if path:
|
||||
tools[tool] = path
|
||||
info["tools"] = tools
|
||||
|
||||
# Disk usage
|
||||
try:
|
||||
usage = shutil.disk_usage("/")
|
||||
info["disk_total"] = usage.total
|
||||
info["disk_free"] = usage.free
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return info
|
||||
|
||||
|
||||
async def execute_command(command, cmd_id, websocket):
|
||||
"""Execute a command locally and stream output back."""
|
||||
try:
|
||||
process = await asyncio.create_subprocess_shell(
|
||||
command,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
|
||||
# Stream stdout
|
||||
async def read_stream(stream, name):
|
||||
while True:
|
||||
line = await stream.readline()
|
||||
if not line:
|
||||
break
|
||||
await websocket.send(json.dumps({
|
||||
"type": "output",
|
||||
"id": cmd_id,
|
||||
"stream": name,
|
||||
"data": line.decode("utf-8", errors="replace"),
|
||||
}))
|
||||
|
||||
# Run both streams concurrently
|
||||
await asyncio.gather(
|
||||
read_stream(process.stdout, "stdout"),
|
||||
read_stream(process.stderr, "stderr"),
|
||||
)
|
||||
|
||||
exit_code = await process.wait()
|
||||
|
||||
await websocket.send(json.dumps({
|
||||
"type": "done",
|
||||
"id": cmd_id,
|
||||
"exit_code": exit_code,
|
||||
}))
|
||||
|
||||
except Exception as e:
|
||||
await websocket.send(json.dumps({
|
||||
"type": "error",
|
||||
"id": cmd_id,
|
||||
"message": str(e),
|
||||
}))
|
||||
|
||||
|
||||
async def read_file(path, cmd_id, websocket):
|
||||
"""Read a file and send its contents back."""
|
||||
try:
|
||||
p = Path(path).expanduser()
|
||||
if not p.exists():
|
||||
await websocket.send(json.dumps({
|
||||
"type": "error", "id": cmd_id,
|
||||
"message": f"File not found: {path}"
|
||||
}))
|
||||
return
|
||||
|
||||
if p.is_dir():
|
||||
# List directory
|
||||
entries = []
|
||||
for entry in sorted(p.iterdir()):
|
||||
stat = entry.stat()
|
||||
entries.append({
|
||||
"name": entry.name,
|
||||
"is_dir": entry.is_dir(),
|
||||
"size": stat.st_size,
|
||||
"modified": stat.st_mtime,
|
||||
})
|
||||
await websocket.send(json.dumps({
|
||||
"type": "dirlist", "id": cmd_id,
|
||||
"path": str(p), "entries": entries,
|
||||
}))
|
||||
else:
|
||||
# Read file (limit to 10MB)
|
||||
size = p.stat().st_size
|
||||
if size > 10 * 1024 * 1024:
|
||||
await websocket.send(json.dumps({
|
||||
"type": "error", "id": cmd_id,
|
||||
"message": f"File too large: {size} bytes"
|
||||
}))
|
||||
return
|
||||
|
||||
content = p.read_text(encoding="utf-8", errors="replace")
|
||||
await websocket.send(json.dumps({
|
||||
"type": "file", "id": cmd_id,
|
||||
"path": str(p), "content": content,
|
||||
"size": size,
|
||||
}))
|
||||
|
||||
except Exception as e:
|
||||
await websocket.send(json.dumps({
|
||||
"type": "error", "id": cmd_id,
|
||||
"message": str(e),
|
||||
}))
|
||||
|
||||
|
||||
async def agent_loop(server_url, token):
|
||||
"""Main agent loop - connect to server and process commands."""
|
||||
# Allow self-signed certs
|
||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ssl_context.check_hostname = False
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
|
||||
ws_url = server_url.replace("https://", "wss://").replace("http://", "ws://")
|
||||
ws_url = f"{ws_url}/ws/agent"
|
||||
|
||||
print(f"Connecting to {ws_url}...")
|
||||
|
||||
while True:
|
||||
try:
|
||||
async with websockets.connect(ws_url, ssl=ssl_context,
|
||||
extra_headers={"Authorization": f"Bearer {token}"}) as ws:
|
||||
print("Connected to AUTARCH server")
|
||||
|
||||
# Send system info on connect
|
||||
sysinfo = get_system_info()
|
||||
sysinfo["type"] = "sysinfo"
|
||||
await ws.send(json.dumps(sysinfo))
|
||||
|
||||
# Send heartbeat periodically
|
||||
async def heartbeat():
|
||||
while True:
|
||||
await asyncio.sleep(30)
|
||||
try:
|
||||
await ws.send(json.dumps({"type": "heartbeat", "time": time.time()}))
|
||||
except Exception:
|
||||
break
|
||||
|
||||
heartbeat_task = asyncio.create_task(heartbeat())
|
||||
|
||||
# Process commands
|
||||
try:
|
||||
async for message in ws:
|
||||
try:
|
||||
msg = json.loads(message)
|
||||
msg_type = msg.get("type", "")
|
||||
cmd_id = msg.get("id", "")
|
||||
|
||||
if msg_type == "exec":
|
||||
command = msg.get("command", "")
|
||||
if command:
|
||||
print(f" Executing: {command[:80]}")
|
||||
asyncio.create_task(execute_command(command, cmd_id, ws))
|
||||
|
||||
elif msg_type == "read":
|
||||
path = msg.get("path", "")
|
||||
if path:
|
||||
asyncio.create_task(read_file(path, cmd_id, ws))
|
||||
|
||||
elif msg_type == "ping":
|
||||
await ws.send(json.dumps({"type": "pong", "id": cmd_id}))
|
||||
|
||||
elif msg_type == "kill":
|
||||
# Server wants us to disconnect
|
||||
print("Server requested disconnect")
|
||||
break
|
||||
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
finally:
|
||||
heartbeat_task.cancel()
|
||||
|
||||
except (websockets.exceptions.ConnectionClosed,
|
||||
ConnectionRefusedError, OSError) as e:
|
||||
print(f"Connection lost: {e}. Reconnecting in 5s...")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nAgent stopped")
|
||||
break
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="AUTARCH Local Agent")
|
||||
parser.add_argument("--server", "-s", required=True,
|
||||
help="AUTARCH server URL (e.g. https://10.0.0.1:8181)")
|
||||
parser.add_argument("--token", "-t", default="",
|
||||
help="Authentication token")
|
||||
args = parser.parse_args()
|
||||
|
||||
print("AUTARCH Local Agent")
|
||||
print(f"Server: {args.server}")
|
||||
print(f"System: {platform.system()} {platform.machine()}")
|
||||
print(f"Host: {socket.gethostname()}")
|
||||
print()
|
||||
|
||||
asyncio.run(agent_loop(args.server, args.token))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -76,49 +76,6 @@ def get_data_dir() -> Path:
|
||||
return d
|
||||
|
||||
|
||||
def get_user_data_dir() -> Path:
|
||||
"""Return the platform-specific user data directory.
|
||||
Created as a hidden folder on first call.
|
||||
|
||||
Windows: %APPDATA%/Autarch/
|
||||
Linux: ~/.autarch/
|
||||
macOS: ~/Library/Application Support/Autarch/
|
||||
"""
|
||||
system = platform.system()
|
||||
if system == 'Windows':
|
||||
base = os.environ.get('APPDATA', '')
|
||||
if base:
|
||||
d = Path(base) / 'Autarch'
|
||||
else:
|
||||
d = Path.home() / 'AppData' / 'Roaming' / 'Autarch'
|
||||
elif system == 'Darwin':
|
||||
d = Path.home() / 'Library' / 'Application Support' / 'Autarch'
|
||||
else:
|
||||
# Linux and others - hidden dotfolder in home
|
||||
d = Path.home() / '.autarch'
|
||||
|
||||
d.mkdir(parents=True, exist_ok=True)
|
||||
return d
|
||||
|
||||
|
||||
def get_keystore_path() -> Path:
|
||||
"""Return the path to the encrypted keystore file.
|
||||
Stored in the user data directory, separate from the app install."""
|
||||
return get_user_data_dir() / 'keystore.xml'
|
||||
|
||||
|
||||
def get_user_profile_path() -> Path:
|
||||
"""Return the path to the user profile file."""
|
||||
return get_user_data_dir() / 'profile.json'
|
||||
|
||||
|
||||
def get_user_sessions_dir() -> Path:
|
||||
"""Return the directory for user session data (chat history, agent memory)."""
|
||||
d = get_user_data_dir() / 'sessions'
|
||||
d.mkdir(parents=True, exist_ok=True)
|
||||
return d
|
||||
|
||||
|
||||
def get_config_path() -> Path:
|
||||
"""Return config path. Writable copy lives next to the exe;
|
||||
falls back to the bundled default if the writable copy doesn't exist yet."""
|
||||
|
||||
184
core/sites_db.py
184
core/sites_db.py
@@ -49,12 +49,6 @@ class SitesDatabase:
|
||||
self._conn = None
|
||||
self._lock = threading.Lock()
|
||||
|
||||
# Ensure the schema exists, then seed from the master dh.json the first
|
||||
# time (or whenever the cache is empty). dh.json is the source of truth;
|
||||
# dh_sites.db is a fast local query cache rebuilt from it automatically.
|
||||
self._ensure_schema()
|
||||
self._auto_populate()
|
||||
|
||||
def _get_connection(self) -> sqlite3.Connection:
|
||||
"""Get thread-safe database connection."""
|
||||
if self._conn is None:
|
||||
@@ -62,48 +56,6 @@ class SitesDatabase:
|
||||
self._conn.row_factory = sqlite3.Row
|
||||
return self._conn
|
||||
|
||||
def _ensure_schema(self) -> None:
|
||||
"""Create the sites table and indexes if they don't already exist."""
|
||||
with self._lock:
|
||||
conn = self._get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS sites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
url_template TEXT NOT NULL,
|
||||
category TEXT DEFAULT 'other',
|
||||
source TEXT DEFAULT 'dh',
|
||||
nsfw INTEGER DEFAULT 0,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
error_type TEXT,
|
||||
error_code INTEGER,
|
||||
error_string TEXT,
|
||||
match_code INTEGER,
|
||||
match_string TEXT
|
||||
)
|
||||
""")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sites_category ON sites(category)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sites_source ON sites(source)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sites_enabled ON sites(enabled)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sites_nsfw ON sites(nsfw)")
|
||||
conn.commit()
|
||||
|
||||
def _auto_populate(self) -> None:
|
||||
"""Seed the cache from the master dh.json when the sites table is empty."""
|
||||
with self._lock:
|
||||
conn = self._get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM sites")
|
||||
count = cursor.fetchone()[0]
|
||||
|
||||
if count > 0:
|
||||
return
|
||||
|
||||
json_path = self.data_dir / "dh.json"
|
||||
if json_path.exists():
|
||||
self.load_from_json(json_path)
|
||||
|
||||
def get_stats(self) -> Dict[str, Any]:
|
||||
"""Get database statistics."""
|
||||
with self._lock:
|
||||
@@ -438,142 +390,6 @@ class SitesDatabase:
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def add_sites_bulk(self, sites: List[Dict], overwrite: bool = False) -> Dict[str, int]:
|
||||
"""Bulk-insert sites in a single transaction.
|
||||
|
||||
By default only sites with a NOT-yet-seen name are added; existing
|
||||
names are left untouched (INSERT OR IGNORE). Pass overwrite=True to
|
||||
replace existing rows instead.
|
||||
|
||||
Args:
|
||||
sites: List of site dicts. Recognised keys: name, url_template
|
||||
(or url), category, source, nsfw, enabled, error_type,
|
||||
error_code, error_string, match_code, match_string.
|
||||
overwrite: Replace existing rows sharing the same name.
|
||||
|
||||
Returns:
|
||||
Stats dict: {'total', 'added', 'skipped', 'errors'}.
|
||||
"""
|
||||
stats = {'total': len(sites), 'added': 0, 'skipped': 0, 'errors': 0}
|
||||
verb = "INSERT OR REPLACE" if overwrite else "INSERT OR IGNORE"
|
||||
|
||||
with self._lock:
|
||||
conn = self._get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
for site in sites:
|
||||
name = site.get('name')
|
||||
url = site.get('url_template') or site.get('url')
|
||||
if not name or not url:
|
||||
stats['errors'] += 1
|
||||
continue
|
||||
|
||||
try:
|
||||
cursor.execute(f"""
|
||||
{verb} INTO sites
|
||||
(name, url_template, category, source, nsfw, enabled,
|
||||
error_type, error_code, error_string, match_code, match_string)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
name,
|
||||
url,
|
||||
site.get('category', 'other'),
|
||||
site.get('source', 'custom'),
|
||||
1 if site.get('nsfw') else 0,
|
||||
0 if site.get('enabled', 1) in (0, False) else 1,
|
||||
site.get('error_type'),
|
||||
site.get('error_code'),
|
||||
site.get('error_string'),
|
||||
site.get('match_code'),
|
||||
site.get('match_string'),
|
||||
))
|
||||
if cursor.rowcount > 0:
|
||||
stats['added'] += 1
|
||||
else:
|
||||
stats['skipped'] += 1
|
||||
except Exception:
|
||||
stats['errors'] += 1
|
||||
|
||||
conn.commit()
|
||||
|
||||
return stats
|
||||
|
||||
@staticmethod
|
||||
def _normalize_url(url: str) -> str:
|
||||
"""Normalise a URL template for duplicate detection.
|
||||
|
||||
Strips scheme, leading www., case, and trailing slash so that
|
||||
http/https, www/non-www and case variants of the same profile URL
|
||||
collapse to one key.
|
||||
"""
|
||||
if not url:
|
||||
return ''
|
||||
u = url.strip().lower()
|
||||
for scheme in ('https://', 'http://'):
|
||||
if u.startswith(scheme):
|
||||
u = u[len(scheme):]
|
||||
break
|
||||
if u.startswith('www.'):
|
||||
u = u[4:]
|
||||
return u.rstrip('/')
|
||||
|
||||
def deduplicate(self) -> Dict[str, int]:
|
||||
"""Remove duplicate sites that share the same (normalised) URL template.
|
||||
|
||||
Names are already unique via the schema constraint; this collapses rows
|
||||
whose URL templates point at the same profile page. For each duplicate
|
||||
group the best row is kept (prefer enabled, then having a detection
|
||||
pattern, then the oldest/lowest id) and the rest are deleted.
|
||||
|
||||
Returns:
|
||||
Stats dict: {'duplicate_groups', 'removed', 'remaining'}.
|
||||
"""
|
||||
with self._lock:
|
||||
conn = self._get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute(
|
||||
"SELECT id, url_template, error_type, error_string, match_string, enabled FROM sites"
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
groups: Dict[str, list] = {}
|
||||
for r in rows:
|
||||
key = self._normalize_url(r['url_template'])
|
||||
if not key:
|
||||
continue
|
||||
groups.setdefault(key, []).append(r)
|
||||
|
||||
def score(r):
|
||||
has_detection = bool(r['error_string'] or r['match_string'] or r['error_type'])
|
||||
# Higher tuple wins; -id keeps the lowest (oldest) id.
|
||||
return (1 if r['enabled'] else 0, 1 if has_detection else 0, -r['id'])
|
||||
|
||||
to_delete = []
|
||||
dup_groups = 0
|
||||
for members in groups.values():
|
||||
if len(members) < 2:
|
||||
continue
|
||||
dup_groups += 1
|
||||
members_sorted = sorted(members, key=score, reverse=True)
|
||||
to_delete.extend(r['id'] for r in members_sorted[1:])
|
||||
|
||||
for i in range(0, len(to_delete), 500):
|
||||
chunk = to_delete[i:i + 500]
|
||||
placeholders = ','.join('?' * len(chunk))
|
||||
cursor.execute(f"DELETE FROM sites WHERE id IN ({placeholders})", chunk)
|
||||
|
||||
conn.commit()
|
||||
|
||||
cursor.execute("SELECT COUNT(*) FROM sites")
|
||||
remaining = cursor.fetchone()[0]
|
||||
|
||||
return {
|
||||
'duplicate_groups': dup_groups,
|
||||
'removed': len(to_delete),
|
||||
'remaining': remaining,
|
||||
}
|
||||
|
||||
def update_detection(
|
||||
self,
|
||||
name: str,
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
"""
|
||||
AUTARCH User Profile Manager
|
||||
Handles user identity, preferences, and session management.
|
||||
|
||||
On first launch, creates a default profile in the user data directory.
|
||||
Supports multiple users for shared deployments.
|
||||
|
||||
The profile stores non-sensitive user info (username, display name, role, etc.)
|
||||
Sensitive data (API keys, passwords) goes in the keystore.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
|
||||
_log = logging.getLogger('autarch.user_profile')
|
||||
|
||||
|
||||
class UserProfile:
|
||||
"""User profile and preferences."""
|
||||
|
||||
def __init__(self, profile_path: Path = None):
|
||||
from core.paths import get_user_profile_path
|
||||
self._path = profile_path or get_user_profile_path()
|
||||
self._data: Dict = {}
|
||||
self._load()
|
||||
|
||||
def _load(self):
|
||||
"""Load profile from disk, or create default."""
|
||||
if self._path.exists():
|
||||
try:
|
||||
with open(self._path) as f:
|
||||
self._data = json.load(f)
|
||||
_log.info(f'Loaded profile for {self._data.get("username", "unknown")}')
|
||||
return
|
||||
except Exception as e:
|
||||
_log.error(f'Failed to load profile: {e}')
|
||||
|
||||
# Create default profile
|
||||
self._data = self._create_default()
|
||||
self._save()
|
||||
_log.info('Created default user profile')
|
||||
|
||||
def _create_default(self) -> Dict:
|
||||
"""Create the default user profile."""
|
||||
username = os.getenv('USER', os.getenv('USERNAME', 'operator'))
|
||||
return {
|
||||
'username': username,
|
||||
'display_name': username.capitalize(),
|
||||
'role': 'admin',
|
||||
'created': int(time.time()),
|
||||
'last_login': int(time.time()),
|
||||
'preferences': {
|
||||
'theme': 'dark',
|
||||
'llm_backend': 'local',
|
||||
'hal_auto_analyze': True,
|
||||
'hal_max_steps': 200,
|
||||
'verbose': False,
|
||||
'default_scan_target': 'local', # 'local' scans user device, 'server' scans server
|
||||
'chat_memory_enabled': True,
|
||||
},
|
||||
'session': {
|
||||
'last_module': '',
|
||||
'last_target': '',
|
||||
'last_scan_type': '',
|
||||
},
|
||||
}
|
||||
|
||||
def _save(self):
|
||||
"""Save profile to disk."""
|
||||
try:
|
||||
self._path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self._path, 'w') as f:
|
||||
json.dump(self._data, f, indent=2)
|
||||
except Exception as e:
|
||||
_log.error(f'Failed to save profile: {e}')
|
||||
|
||||
@property
|
||||
def username(self) -> str:
|
||||
return self._data.get('username', 'default')
|
||||
|
||||
@property
|
||||
def display_name(self) -> str:
|
||||
return self._data.get('display_name', self.username)
|
||||
|
||||
@property
|
||||
def role(self) -> str:
|
||||
return self._data.get('role', 'user')
|
||||
|
||||
def get_preference(self, key: str, default=None):
|
||||
"""Get a user preference value."""
|
||||
return self._data.get('preferences', {}).get(key, default)
|
||||
|
||||
def set_preference(self, key: str, value):
|
||||
"""Set a user preference and save."""
|
||||
if 'preferences' not in self._data:
|
||||
self._data['preferences'] = {}
|
||||
self._data['preferences'][key] = value
|
||||
self._save()
|
||||
|
||||
def get_session(self, key: str, default='') -> str:
|
||||
"""Get a session value (non-persistent state hints)."""
|
||||
return self._data.get('session', {}).get(key, default)
|
||||
|
||||
def set_session(self, key: str, value: str):
|
||||
"""Set a session value."""
|
||||
if 'session' not in self._data:
|
||||
self._data['session'] = {}
|
||||
self._data['session'][key] = value
|
||||
self._save()
|
||||
|
||||
def update_last_login(self):
|
||||
"""Record login timestamp."""
|
||||
self._data['last_login'] = int(time.time())
|
||||
self._save()
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
"""Export profile as a dict (for API/display)."""
|
||||
return {
|
||||
'username': self.username,
|
||||
'display_name': self.display_name,
|
||||
'role': self.role,
|
||||
'created': self._data.get('created', 0),
|
||||
'last_login': self._data.get('last_login', 0),
|
||||
'preferences': self._data.get('preferences', {}),
|
||||
}
|
||||
|
||||
|
||||
# Singleton
|
||||
_profile_instance: Optional[UserProfile] = None
|
||||
|
||||
|
||||
def get_profile() -> UserProfile:
|
||||
"""Get the global user profile instance."""
|
||||
global _profile_instance
|
||||
if _profile_instance is None:
|
||||
_profile_instance = UserProfile()
|
||||
return _profile_instance
|
||||
|
||||
|
||||
def init_profile_on_launch():
|
||||
"""Called at app startup to ensure profile exists and update login time."""
|
||||
profile = get_profile()
|
||||
profile.update_last_login()
|
||||
|
||||
# Migrate old vault secrets to new keystore if needed
|
||||
from core.paths import get_keystore_path
|
||||
ks_path = get_keystore_path()
|
||||
if not ks_path.exists():
|
||||
from core.keystore import get_keystore
|
||||
ks = get_keystore()
|
||||
migrated = ks.migrate_from_vault()
|
||||
if migrated:
|
||||
_log.info(f'Migrated {migrated} secrets from vault to keystore on first run')
|
||||
|
||||
return profile
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"listen_dns": "420.420.420.420:53",
|
||||
"listen_dns": "10.0.0.56:53",
|
||||
"listen_api": "127.0.0.1:5380",
|
||||
"api_token": "",
|
||||
"api_token": "5ed79350fed2490d2aca6f3b29776365",
|
||||
"upstream": [],
|
||||
"cache_ttl": 300,
|
||||
"zones_dir": "/home/snake/autarch/data/dns/zones",
|
||||
"dnssec_keys_dir": "/home/snake/autarch/data/dns/keys",
|
||||
"zones_dir": "C:\\she\\autarch\\data\\dns\\zones",
|
||||
"dnssec_keys_dir": "C:\\she\\autarch\\data\\dns\\keys",
|
||||
"log_queries": true
|
||||
}
|
||||
@@ -7,7 +7,7 @@ You are Hal, the AI security agent for AUTARCH — built by darkHal Security Gro
|
||||
3. DETECT THE OS FIRST before running any command. Use the shell tool to run "uname -s" or check if you're on Windows. Then ONLY run commands for THAT operating system. Never list commands for multiple distros or platforms in one response.
|
||||
4. On Linux: detect the distro (cat /etc/os-release). Use apt for Debian/Ubuntu, dnf for Fedora, pacman for Arch. Do NOT guess — check first.
|
||||
5. On Windows: use PowerShell or cmd commands. Do NOT mix in Linux commands.
|
||||
6. For commands that need root/admin: you CAN use sudo. The system has a privileged daemon that handles elevation, so sudo will work without password prompts. Use sudo when commands require elevated privileges.
|
||||
6. For commands that need root/admin: use the shell tool directly — the system has a privileged daemon that handles elevation automatically. NEVER prefix commands with "sudo". Just run the command.
|
||||
7. Run ONE command at a time. Verify it worked before running the next one.
|
||||
8. Keep responses short and direct. No filler, no preamble.
|
||||
9. When asked to do something, DO IT. Don't explain how it would be done on 5 different OSes.
|
||||
@@ -19,15 +19,15 @@ You can read files, write files, execute shell commands, search the codebase, an
|
||||
## Common Commands by OS
|
||||
|
||||
Linux (Debian/Ubuntu):
|
||||
sudo apt update && sudo apt install <package>
|
||||
sudo systemctl start/stop/status <service>
|
||||
sudo iptables -A INPUT -s <ip> -j DROP
|
||||
apt update && apt install <package>
|
||||
systemctl start/stop/status <service>
|
||||
iptables -A INPUT -s <ip> -j DROP
|
||||
ip addr / ip route / ip neigh / ss -tunap
|
||||
|
||||
Linux (Fedora/RHEL):
|
||||
sudo dnf install <package>
|
||||
sudo systemctl start/stop/status <service>
|
||||
sudo firewall-cmd --add-rich-rule='rule family=ipv4 source address=<ip> drop'
|
||||
dnf install <package>
|
||||
systemctl start/stop/status <service>
|
||||
firewall-cmd --add-rich-rule='rule family=ipv4 source address=<ip> drop'
|
||||
|
||||
Windows:
|
||||
Get-NetFirewallRule / New-NetFirewallRule
|
||||
@@ -55,8 +55,8 @@ For tasks: use tools. Run one command, check the result, then continue.
|
||||
For module creation: use create_module tool.
|
||||
|
||||
When running shell commands — ALWAYS detect OS first, then:
|
||||
CORRECT: sudo iptables -L -n (after confirming Linux)
|
||||
CORRECT: iptables -L -n (also works, daemon handles elevation)
|
||||
CORRECT: iptables -L -n (after confirming Linux)
|
||||
WRONG: sudo iptables -L -n
|
||||
WRONG: Here's how to do it on Linux, Windows, and macOS...
|
||||
|
||||
When explaining results:
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"generated": "2026-07-13T15:40:17.978877",
|
||||
"counts": {
|
||||
"packages": 300,
|
||||
"certs": 11,
|
||||
"domains": 5793,
|
||||
"ips": 65,
|
||||
"file_paths": 19,
|
||||
"processes": 84,
|
||||
"hashes": 318
|
||||
},
|
||||
"sources": {
|
||||
"stalkerware_ioc_yaml": true,
|
||||
"amnesty_investigations": 16,
|
||||
"mvt_campaigns": 8,
|
||||
"citizen_lab_campaigns": 21,
|
||||
"yara_rules": 52
|
||||
}
|
||||
}
|
||||
@@ -1,605 +0,0 @@
|
||||
domain_name,ip_address
|
||||
"14-tracking.com","191.101.31.25"
|
||||
"1minto-start.com","185.94.190.203"
|
||||
"24-7clinic.com","46.183.219.79"
|
||||
"3driving.com","185.106.120.130"
|
||||
"456h612i458g.com","81.22.255.180"
|
||||
"7style.org","109.200.24.106"
|
||||
"800health.net","185.189.112.199"
|
||||
"access.dynamic-dns.net","95.183.51.199"
|
||||
"accountnotify.com","185.130.184.35"
|
||||
"activate-discount.com","200.7.97.228"
|
||||
"actorsshop.net","31.184.198.149"
|
||||
"actu24.online","185.156.175.219"
|
||||
"addmyid.net","46.22.223.209"
|
||||
"adeal4u.co","217.112.131.120"
|
||||
"afriquenouvelle.com","185.94.191.69"
|
||||
"aircraftsxhibition.com","108.170.31.100"
|
||||
"ajelnews.net","109.200.24.72"
|
||||
"akhbara-aalawsat.com","185.243.115.100"
|
||||
"akhbar-aliqtisad.com","185.94.191.23"
|
||||
"akhbar-arabia.com","200.7.97.216"
|
||||
"albumphotopro.biz","185.45.192.134"
|
||||
"alive2plunge.com","173.254.248.104"
|
||||
"allafricaninfo.com","5.102.146.87"
|
||||
"allbeautifularts.com","185.94.191.73"
|
||||
"alldaycooking.co","217.112.131.103"
|
||||
"allfadiha.co","217.64.113.254"
|
||||
"allladiesloveme.com","38.132.118.108"
|
||||
"all-sales.info","88.119.179.165"
|
||||
"allthecolorsyoulike.com","185.225.68.6"
|
||||
"allthegamesyouneed.com","185.195.200.43"
|
||||
"allthemakeupyouneed.com","185.195.200.51"
|
||||
"allthesongsyoulike.com","46.183.216.141"
|
||||
"alluneed4home.net","109.200.24.48"
|
||||
"android-core.org","109.200.24.112"
|
||||
"android-updates.net","185.225.68.229"
|
||||
"apiapple.com","185.141.26.50"
|
||||
"apiwacdn.com","206.189.108.245"
|
||||
"appointments-online.com","88.150.227.120"
|
||||
"arabnews365.com","88.119.179.166"
|
||||
"arab-share.com","46.21.147.141"
|
||||
"arabworld.biz","46.21.147.224"
|
||||
"arabworldnews.info","185.230.124.235"
|
||||
"around-theglobe.co","185.82.202.32"
|
||||
"ar-tweets.com","109.200.24.76"
|
||||
"atlaslions.info","82.211.31.177"
|
||||
"autodiscount.info","88.150.227.105"
|
||||
"banca-movil.com","149.255.36.138"
|
||||
"bargainservice.online","83.221.132.157"
|
||||
"beautifulhousesaroundme.com","185.225.68.2"
|
||||
"beethoventopsymphonies.com","80.255.12.246"
|
||||
"benjamin-taganga.info","217.112.131.176"
|
||||
"bestadventures4u.com","93.158.203.142"
|
||||
"bestcandyever.com","5.149.250.2"
|
||||
"bestfoods.co","200.7.98.133"
|
||||
"bestfriendneedshelp.com","88.150.138.66"
|
||||
"bestheadphones4u.com","93.158.203.140"
|
||||
"besthotelsaroundme.com","5.149.252.157"
|
||||
"bestperfumesnow.com","89.249.65.165"
|
||||
"bestpresents4all.net","94.177.236.235"
|
||||
"bestsalesaroundme.com","89.33.246.112"
|
||||
"beststores4u.com","185.94.189.198"
|
||||
"bestsushiever.com","88.150.138.106"
|
||||
"better-deal.info","217.112.131.147"
|
||||
"bicyclerentalnow.com","5.149.254.5"
|
||||
"biggunsarefun.com","200.7.105.3"
|
||||
"blackwhitebags.com","185.206.224.41"
|
||||
"blcheck.utensils.pro","164.132.138.55"
|
||||
"blue.911hig11carcay959454.com","54.37.104.101"
|
||||
"booking-tables.com","109.200.24.59"
|
||||
"boysrbabies.co","38.132.118.111"
|
||||
"breakfastisgood.com","5.102.147.114"
|
||||
"breaking-extranews.online","185.141.27.124"
|
||||
"breakingnewsasia.com","200.7.111.156"
|
||||
"breaking-news.co","88.150.189.108"
|
||||
"breakthenews.net","81.95.5.165"
|
||||
"br-hashtags.com","191.101.31.21"
|
||||
"brighttooth.net","185.189.112.200"
|
||||
"brownandblueeyes.com","185.29.11.165"
|
||||
"browser-update.online","191.101.31.114"
|
||||
"br-travels.com","81.95.7.58"
|
||||
"buildurlife.net","5.149.255.198"
|
||||
"bunchi.club","5.149.249.174"
|
||||
"businesssupportme.com","5.149.255.69"
|
||||
"bussybeesallover.com","195.12.48.42"
|
||||
"buymanuel.co","185.117.75.84"
|
||||
"buypresent4me.net","94.177.239.30"
|
||||
"calendarsapp.com","185.117.72.120"
|
||||
"captcha.bl33pon6373.com","88.99.107.18"
|
||||
"carrefour-des-affaires.com","5.102.146.126"
|
||||
"cars-to-buy.com","217.112.131.146"
|
||||
"cashandlife.com","185.82.200.233"
|
||||
"casia-news.info","185.198.58.158"
|
||||
"catfoodstorage.net","217.61.5.131"
|
||||
"catsndogsproducts.com","88.119.179.226"
|
||||
"cdnupdateweb.com","190.97.165.115"
|
||||
"cdnwa.com","185.141.25.30"
|
||||
"cell-abonnes.com","5.102.147.82"
|
||||
"cellphonesprices.com","93.158.200.205"
|
||||
"cellular-updates.com","176.223.111.159"
|
||||
"cellularupdates.info","185.77.129.136"
|
||||
"cellular-updates.online","154.16.37.40"
|
||||
"centrasia-news.com","185.225.68.125"
|
||||
"cheapapartmentsaroundme.com","88.119.179.140"
|
||||
"cheaphostingtoday.com","5.102.146.49"
|
||||
"cheapmotelz.net","185.106.120.173"
|
||||
"cheapsolutions4u.com","141.255.161.88"
|
||||
"cheaptransporting.net","185.156.173.118"
|
||||
"check-my-internetspeed.com","200.7.97.229"
|
||||
"chocolateicecreamlovers.com","88.150.138.74"
|
||||
"chocollife.me","185.94.191.123"
|
||||
"chubaka.org","185.225.68.124"
|
||||
"classic-furnitures.com","185.183.107.43"
|
||||
"clickrighthere.online","138.59.17.76"
|
||||
"coffecups.online","31.3.232.125"
|
||||
"coffee2go.org","86.105.18.222"
|
||||
"colorfulnotebooks.com","185.195.200.38"
|
||||
"colorsoflife.online","62.113.232.221"
|
||||
"columbus-parking.com","154.16.37.39"
|
||||
"coolasiankitchen.com","5.102.146.91"
|
||||
"coolbbqtools.net","217.112.131.108"
|
||||
"coolmath4us.net","217.112.131.227"
|
||||
"cool-smartphone-apps.com","217.112.131.58"
|
||||
"coupedumondepro.com","188.215.229.213"
|
||||
"couponshops.info","37.220.31.114"
|
||||
"cpr-appointments.com","88.150.227.121"
|
||||
"cryptocurrecny.com","185.225.68.77"
|
||||
"cryptokoinz.com","5.149.254.24"
|
||||
"cryptopcoinz.com","217.61.7.152"
|
||||
"csomagodjott.com","200.7.97.238"
|
||||
"daily-sport.news","200.7.97.214"
|
||||
"dancinglife.co","89.249.65.206"
|
||||
"deal4unow.com","185.134.29.146"
|
||||
"delivery-24-7.com","81.92.202.222"
|
||||
"dental-care-spa.net","185.225.68.202"
|
||||
"deportesinfo.com","149.255.35.115"
|
||||
"diaspora-news.com","81.95.5.144"
|
||||
"dinneraroundyou.com","217.112.131.208"
|
||||
"discountmarkets.info","88.150.138.69"
|
||||
"discountstores.info","109.200.24.73"
|
||||
"discoveredworld-news.com","185.236.202.184"
|
||||
"dogfoodstorage.net","217.61.104.60"
|
||||
"dogopics.com","5.102.145.183"
|
||||
"doitformom.com","89.34.111.212"
|
||||
"doitforthefame-now.com","88.150.138.82"
|
||||
"do-itonyour-own.com","5.102.145.64"
|
||||
"domain-redirect.com","109.200.24.122"
|
||||
"domainsearching.net","185.117.89.251"
|
||||
"domainsearching.net","80.211.250.229"
|
||||
"domain-security.org","109.200.24.2"
|
||||
"donateabox.co","5.102.146.82"
|
||||
"donateaflower.com","104.216.8.34"
|
||||
"done.events","130.185.250.200"
|
||||
"dowhatyouneed.com","5.102.145.130"
|
||||
"easybett.online","46.183.221.185"
|
||||
"easy-pay.info","89.249.65.193"
|
||||
"ecommerce-ads.org","46.183.223.249"
|
||||
"economic-news.co","185.230.124.234"
|
||||
"editorscolumn.net","89.238.138.141"
|
||||
"egov-online.com","88.150.227.122"
|
||||
"egov-segek.info","185.195.200.47"
|
||||
"egov-sergek.info","185.195.200.47"
|
||||
"ehistorybooks.com","185.109.168.29"
|
||||
"ehistorybooks.com","78.142.25.30"
|
||||
"elitecarz.net","5.102.147.163"
|
||||
"eltiempo-news.com","38.84.132.165"
|
||||
"emonitoring-paczki.pl","86.105.18.121"
|
||||
"entertainmentinat.com","5.149.254.12"
|
||||
"e-prokuror.info","5.102.145.72"
|
||||
"e-sveiciens.com","5.149.254.14"
|
||||
"eura-cell.com","88.150.227.98"
|
||||
"eurasianupdate.com","88.150.227.110"
|
||||
"eurosportnews.info","217.64.114.179"
|
||||
"event-reg.info","185.77.131.10"
|
||||
"ex-forexlive.com","5.102.147.73"
|
||||
"extrahoney.net","77.245.76.109"
|
||||
"ezdropshipping.net","23.107.197.107"
|
||||
"fabric-shops.com","185.225.68.176"
|
||||
"face-image.com","185.225.68.128"
|
||||
"fadi7apress.com","5.102.145.26"
|
||||
"fantastic-gardens.com","185.94.189.208"
|
||||
"fashion-live.net","37.220.31.78"
|
||||
"fashion-online.net","217.112.131.136"
|
||||
"fashionpark.info","185.94.191.124"
|
||||
"fastfixs.net","37.220.31.80"
|
||||
"femmedaffaire.com","5.102.146.93"
|
||||
"fiestamaghreb.com","188.215.229.216"
|
||||
"files-downloads.com","217.61.96.219"
|
||||
"findavoucher.online","185.198.58.196"
|
||||
"findgoodfood.co","185.94.189.207"
|
||||
"finditout-now.com","5.102.147.51"
|
||||
"findmyass.org","8.39.147.100"
|
||||
"findmyfriendsnow.com","179.43.169.41"
|
||||
"findmylunch.org","38.132.118.116"
|
||||
"findmymind.co","185.230.124.241"
|
||||
"findmyplants.com","46.21.147.65"
|
||||
"findouthere.org","83.221.132.104"
|
||||
"fishingtrickz.com","185.244.150.68"
|
||||
"fitness-for-ever.com","185.77.131.109"
|
||||
"flights-report.com","217.112.131.42"
|
||||
"flights-todays.com","88.150.227.103"
|
||||
"flying-free.online","154.16.37.35"
|
||||
"fofopiko.org","217.112.131.158"
|
||||
"foodforyou.info","88.150.138.78"
|
||||
"foodiez.online","46.183.221.187"
|
||||
"foto-top.info","185.225.68.133"
|
||||
"foudefoot.live","185.45.193.210"
|
||||
"freedominfo.net","46.21.147.123"
|
||||
"freelancers-team.org","5.102.147.106"
|
||||
"free-local-events.info","185.225.68.207"
|
||||
"freshandsoftbread.com","188.215.229.222"
|
||||
"freshsaladtoday.com","200.7.97.254"
|
||||
"fundum8430.com","163.172.140.159"
|
||||
"funinat.com","46.21.147.46"
|
||||
"funinthesun4u.com","185.198.58.144"
|
||||
"funintheuk.com","185.117.75.228"
|
||||
"funnytvclips.com","200.7.111.155"
|
||||
"fwupdating.com","5.135.199.22"
|
||||
"gadgetsshop.info","185.225.68.158"
|
||||
"getagift.info","185.225.68.159"
|
||||
"getoutofyourmind.com","5.149.254.18"
|
||||
"getphotosinstant.net","5.102.147.51"
|
||||
"glassesofwine.com","38.132.118.117"
|
||||
"globalsupporteam.com","80.255.6.24"
|
||||
"golf-news.live","167.88.5.222"
|
||||
"goodcookingonline.com","5.102.146.90"
|
||||
"goodflowersinside.com","37.220.31.19"
|
||||
"good-games.org","80.255.3.111"
|
||||
"goodthoughts4u.com","5.102.147.254"
|
||||
"goroskop.co","5.149.255.19"
|
||||
"gostatspro.com","81.17.30.45"
|
||||
"go-trip.online","200.7.111.11"
|
||||
"gulfca.net","88.150.227.115"
|
||||
"gulf-financials.com","82.211.30.122"
|
||||
"gulf-news.info","185.230.124.233"
|
||||
"hairdresseraroundme.com","31.3.232.116"
|
||||
"halal-place.com","89.249.65.234"
|
||||
"handcreamforyou.com","185.81.113.105"
|
||||
"handymanwood.com","77.73.65.47"
|
||||
"happiness4us.com","5.149.254.20"
|
||||
"hdsoccerstream.com","195.12.50.179"
|
||||
"health-club.online","86.105.18.212"
|
||||
"hellomydaddy.com","200.7.97.168"
|
||||
"hellomymommy.com","200.7.97.167"
|
||||
"highclassdining.net","109.200.24.58"
|
||||
"holiday4u.work","5.102.146.184"
|
||||
"homeishere.co","31.3.232.126"
|
||||
"homemadecandies.net","195.12.50.177"
|
||||
"host-one-more.com","185.156.173.70"
|
||||
"hotelsauto.co","185.198.57.144"
|
||||
"hotels-review.org","217.112.131.90"
|
||||
"hotelstax.co","188.215.229.205"
|
||||
"hotelsurvey.info","185.225.68.205"
|
||||
"hothdwallpaperz.com","5.102.145.37"
|
||||
"hotinfosource.com","217.112.131.111"
|
||||
"hot-motors.com","185.117.89.231"
|
||||
"housesfurniture.com","185.94.192.106"
|
||||
"housing-update.com","88.150.227.117"
|
||||
"howisurday.com","185.198.58.195"
|
||||
"howtoexplorebirds.com","88.150.227.99"
|
||||
"howtomakeavocadotoastandegg.com","84.38.129.195"
|
||||
"hracingtips.com","185.117.89.220"
|
||||
"icecreamlovesme.com","155.94.160.126"
|
||||
"igiheonline.com","5.102.147.250"
|
||||
"ilovemybeatifulnails.com","109.200.24.10"
|
||||
"ilovemymilf.com","5.102.146.72"
|
||||
"income-tax.online","103.199.16.153"
|
||||
"indrive.info","185.225.68.141"
|
||||
"ineediscounts.com","185.117.72.113"
|
||||
"info24.live","185.141.27.116"
|
||||
"infospotpro.com","217.112.131.20"
|
||||
"infospress.com","5.102.146.241"
|
||||
"insta-foto.net","185.141.26.39"
|
||||
"internetmobilespeed.com","91.219.238.77"
|
||||
"intim-media.net","185.225.68.126"
|
||||
"investigationews.com","185.82.200.187"
|
||||
"in-weather.com","103.199.17.206"
|
||||
"islamic-news-today.com","103.199.16.88"
|
||||
"islamiyaat.com","89.249.65.146"
|
||||
"islam-today.info","185.198.58.151"
|
||||
"islam-world.net","200.7.97.242"
|
||||
"istgr-foto.com","185.225.68.131"
|
||||
"iwantitallnow.com","173.254.248.105"
|
||||
"jaimelire.net","185.183.97.196"
|
||||
"just-one-left.com","46.21.147.14"
|
||||
"karbalaeyat.com","191.101.31.29"
|
||||
"kaspi-payment.com","185.94.191.114"
|
||||
"keyindoors.com","66.85.157.84"
|
||||
"kingdom-deals.com","200.7.97.212"
|
||||
"kingdom-news.com","191.101.31.118"
|
||||
"klientuserviss.com","185.198.58.178"
|
||||
"koramaghreb.com","188.215.229.214"
|
||||
"kurjerserviss.com","185.198.58.177"
|
||||
"labonneforme.net","185.183.97.194"
|
||||
"leadersnews.org","5.102.147.105"
|
||||
"leggingsjustforyou.com","5.149.250.18"
|
||||
"legyelvodas.com","185.117.89.252"
|
||||
"legyelvodas.com","80.211.254.70"
|
||||
"legyelvodas.net","185.117.89.253"
|
||||
"leleader.org","185.106.120.35"
|
||||
"leprotestant.com","185.106.120.34"
|
||||
"lesbonnesaffaires.online","5.102.146.123"
|
||||
"lesportail.biz","185.117.75.165"
|
||||
"liam-ryan.co","185.141.26.49"
|
||||
"lifedonor.net","88.150.138.111"
|
||||
"like-the-rest.com","185.225.68.68"
|
||||
"live-once.net","185.183.97.117"
|
||||
"loading-images.com","5.102.147.172"
|
||||
"loading-pag.net","8.28.175.73"
|
||||
"localgreenflowers.com","185.225.68.198"
|
||||
"loisiragogo.com","5.102.146.128"
|
||||
"lonely-place.com","5.102.146.116"
|
||||
"looking-for-two.com","5.102.145.8"
|
||||
"lookitupnow.website","185.81.113.81"
|
||||
"look-outsidenow.com","89.33.246.113"
|
||||
"loschismescalientes.com","149.255.35.106"
|
||||
"losnegocios.biz","23.227.207.174"
|
||||
"lost-n-found.net","185.183.96.140"
|
||||
"loveandhatenow.com","5.102.147.219"
|
||||
"maghrebfoot.com","185.117.75.169"
|
||||
"maghrebfunny.biz","185.94.189.214"
|
||||
"mamba-live.com","217.112.131.106"
|
||||
"mapupdatezone.com","185.193.38.159"
|
||||
"massagetax.co","5.102.145.98"
|
||||
"maymknch2026.co","188.215.229.212"
|
||||
"medical-updates.com","185.77.129.103"
|
||||
"megacenter.info","217.112.131.95"
|
||||
"mercedesbenz-vip.com","185.77.131.103"
|
||||
"mideast-today.com","88.119.179.176"
|
||||
"miles-club.com","217.112.131.91"
|
||||
"miralo-rapidamente.com","46.21.150.144"
|
||||
"mobile-softs.com","5.149.255.18"
|
||||
"mobile-update.online","185.198.57.43"
|
||||
"mobile-updates.info","217.112.131.61"
|
||||
"mobileweatherweb.com","185.44.105.35"
|
||||
"mobi-up.net","81.92.202.215"
|
||||
"moh-followup.com","88.150.227.118"
|
||||
"moh-online.com","109.200.24.71"
|
||||
"mondaymornings.co","176.223.111.231"
|
||||
"moneycoincurrency.com","185.225.68.201"
|
||||
"moneydigitalcurrency.com","185.225.68.200"
|
||||
"moneyxchanges.com","109.200.24.19"
|
||||
"mosque-salah.com","109.200.24.64"
|
||||
"mosque-salah.net","185.225.68.5"
|
||||
"mosquesfinder.com","194.187.249.106"
|
||||
"motordeal.info","88.150.227.104"
|
||||
"movie-tickets.online","103.199.16.11"
|
||||
"moyfoto.net","185.141.26.18"
|
||||
"m-resume.com","185.225.68.135"
|
||||
"muftyat.com","217.112.131.16"
|
||||
"muslim-world.info","200.7.97.215"
|
||||
"muzicclips.com","200.7.97.248"
|
||||
"mybrightidea.co","185.117.72.10"
|
||||
"mydailycooking.net","89.249.65.138"
|
||||
"myfiles.photos","130.185.250.199"
|
||||
"myfreecharge.online","103.199.16.111"
|
||||
"mygreathat.com","109.200.24.126"
|
||||
"mykaspi.com","217.112.131.39"
|
||||
"mylovelypet.net","62.113.232.197"
|
||||
"mymobile-cell.com","217.61.4.34"
|
||||
"mypostservice.online","192.52.243.110"
|
||||
"my-privacy.co","103.199.16.15"
|
||||
"mysadaga.com","31.3.232.108"
|
||||
"myshoesforever.com","185.225.68.177"
|
||||
"myshop4u.net","77.73.65.210"
|
||||
"mystulchik.com","5.102.145.14"
|
||||
"mysuperheadphones.co","179.43.169.8"
|
||||
"mysuperheadphones.co","52.54.37.95"
|
||||
"myukadventures.com","185.94.189.204"
|
||||
"nation24.info","5.102.147.235"
|
||||
"nationalleagues.net","5.102.146.124"
|
||||
"nbrowser.org","109.200.24.102"
|
||||
"newandfresh.com","185.82.202.29"
|
||||
"newandroidapps.net","185.181.10.64"
|
||||
"newarrivals.club","185.109.168.12"
|
||||
"newarrivals.club","88.119.179.102"
|
||||
"newcooking.org","109.200.24.11"
|
||||
"newdailycoupons.com","88.150.227.77"
|
||||
"newmodel.online","185.109.168.18"
|
||||
"newmodel.online","88.119.179.168"
|
||||
"newnhotapps.com","217.112.131.137"
|
||||
"news-alert.org","200.7.111.124"
|
||||
"newscurrent.info","185.134.29.144"
|
||||
"newsdirect.online","185.243.112.77"
|
||||
"news-gazette.info","88.119.179.164"
|
||||
"newsofficial.info","87.121.98.39"
|
||||
"newsofgames.com","154.16.37.11"
|
||||
"newsofthemoment.net","38.132.118.114"
|
||||
"newworld-news.com","89.40.181.124"
|
||||
"nightevents.info","185.225.68.206"
|
||||
"noextramoney.com","192.161.48.122"
|
||||
"noloveforyou.com","38.132.114.168"
|
||||
"nomorewarnow.com","185.198.58.143"
|
||||
"noonstore.sale","130.185.250.201"
|
||||
"noor-alhedaya.com","89.249.65.149"
|
||||
"normal-brain.com","103.199.16.12"
|
||||
"nosalternatives.com","185.141.27.123"
|
||||
"nothernkivu.com","89.40.181.125"
|
||||
"noti-global.com","38.84.132.168"
|
||||
"noti-hot.com","8.28.175.78"
|
||||
"notresante-infos.com","5.102.145.169"
|
||||
"nouveau-president.com","185.106.120.246"
|
||||
"nouvelles247.com","200.7.97.213"
|
||||
"novosti247.com","109.200.24.32"
|
||||
"nuevaidea.co","173.254.248.115"
|
||||
"odnoklass-profile.com","185.225.68.132"
|
||||
"offresimmobilier.com","5.102.145.12"
|
||||
"ok-group.org","185.225.68.134"
|
||||
"one-isnot-enough.com","5.102.147.13"
|
||||
"onetreeinheaven.com","37.220.31.107"
|
||||
"online-dailynews.com","88.150.227.125"
|
||||
"onlinefreework.com","200.7.105.39"
|
||||
"onlineshopzm.com","185.225.68.60"
|
||||
"onlygossip.info","185.117.89.198"
|
||||
"only-news.net","5.102.147.162"
|
||||
"onlytoday.biz","109.200.24.104"
|
||||
"onthegoodtime.com","185.225.68.69"
|
||||
"operatingnews.com","46.21.147.173"
|
||||
"orange-updates.com","5.104.105.200"
|
||||
"ourorder.info","185.225.68.127"
|
||||
"outletsaroundme.com","78.142.25.37"
|
||||
"outletstore.tech","87.121.98.38"
|
||||
"papers2go.co","176.223.111.206"
|
||||
"park4free.info","185.144.83.116"
|
||||
"passwd.privo7799add.net","188.40.155.240"
|
||||
"pastesbin.com","185.195.200.56"
|
||||
"pathtogo.net","5.149.255.3"
|
||||
"pay-city.com","154.16.37.105"
|
||||
"paynfly.info","185.144.83.114"
|
||||
"paywithcrytpo.com","200.7.111.154"
|
||||
"phonering4you.com","5.149.250.19"
|
||||
"photo-my.net","5.149.255.16"
|
||||
"pickcard.info","5.102.147.138"
|
||||
"picture4us.com","46.183.221.149"
|
||||
"pi.license-updater.com","91.219.28.21"
|
||||
"pine-sales.com","92.222.208.251"
|
||||
"pizzatoyourplace.com","5.149.249.19"
|
||||
"playwithusonline.com","200.7.111.102"
|
||||
"pochta-info.com","185.29.11.203"
|
||||
"politica504.com","149.255.36.132"
|
||||
"politicalpress.org","5.102.145.99"
|
||||
"politiques-infos.info","5.102.145.17"
|
||||
"postainf.net","200.7.98.117"
|
||||
"posta.news","185.29.11.200"
|
||||
"ppcisdead.com","88.150.189.121"
|
||||
"prikol-girls.com","5.149.249.189"
|
||||
"promosdereve.com","88.119.179.105"
|
||||
"promotionlove.co","185.117.75.165"
|
||||
"promotionlove.co","185.94.192.101"
|
||||
"puffyteddybear.com","84.38.130.107"
|
||||
"purple-enveloppe.com","66.85.157.71"
|
||||
"quitmyjob.xyz","103.199.16.47"
|
||||
"quran-quote.com","84.200.32.211"
|
||||
"rainingcats.net","38.132.118.110"
|
||||
"readingbooksnow.com","109.200.24.7"
|
||||
"regionews.net","5.102.145.90"
|
||||
"reklamas.info","5.149.254.2"
|
||||
"rentmotors.net","88.150.138.99"
|
||||
"research-archive.com","5.102.146.59"
|
||||
"reseausocialsolutions.co","185.82.200.143"
|
||||
"reservationszone.com","88.150.138.85"
|
||||
"reseufun.com","188.215.229.215"
|
||||
"resolutionsbox.com","38.132.118.107"
|
||||
"restaurantsstar.com","185.225.68.75"
|
||||
"rewards-club.info","176.223.111.137"
|
||||
"rockmusic4u.com","185.82.200.164"
|
||||
"rockstarpony.com","94.177.234.8"
|
||||
"rosegoldjewerly.com","185.195.200.44"
|
||||
"rosesforus.com","88.150.189.111"
|
||||
"russian4u.net","95.213.193.40"
|
||||
"saladsaroundme.com","89.33.246.119"
|
||||
"same-old.net","37.220.31.46"
|
||||
"savemoretime.co","185.225.68.64"
|
||||
"saveurday.net","37.72.175.179"
|
||||
"securesmsing.com","109.200.24.14"
|
||||
"sergek.info","185.195.200.46"
|
||||
"services-sync.com","46.21.147.237"
|
||||
"service-update.online","185.94.191.59"
|
||||
"shia-voice.com","52.54.37.95"
|
||||
"shia-voice.com","89.249.65.148"
|
||||
"shoppingdailydeals.net","109.200.24.18"
|
||||
"shortfb.com","37.220.31.108"
|
||||
"shuturl.com","185.117.72.117"
|
||||
"signpetition.co","200.7.111.125"
|
||||
"site-redirecting.com","109.200.24.20"
|
||||
"smarttarfi.com","45.76.42.111"
|
||||
"snoweverywhere.com","46.21.147.21"
|
||||
"soccerstreamingstars.com","185.183.96.131"
|
||||
"social-life.info","185.183.96.131"
|
||||
"somuchrain.com","5.102.145.39"
|
||||
"so-this-is.com","159.89.193.231"
|
||||
"specialgifts4all.com","200.7.97.225"
|
||||
"sportupdates.info","185.225.68.86"
|
||||
"sportupdates.online","89.33.246.118"
|
||||
"sputnik-news.info","185.198.58.182"
|
||||
"starbuckscoffeeweb.com","217.112.131.109"
|
||||
"stars4sale.co","185.225.68.65"
|
||||
"start2playnow.com","5.102.145.248"
|
||||
"starting-from0.com","185.94.189.219"
|
||||
"statisticsdb.net","185.93.183.231"
|
||||
"stopmysms.com","191.101.31.222"
|
||||
"stopsms.biz","185.198.58.154"
|
||||
"sunday-deals.com","88.119.179.169"
|
||||
"supportonline4me.com","185.80.53.199"
|
||||
"surprising-sites.com","217.112.131.67"
|
||||
"sync-cdn.com","185.183.96.150"
|
||||
"syncmap.org","185.117.89.145"
|
||||
"tablereservation.info","109.200.24.66"
|
||||
"takethat.co","209.250.247.96"
|
||||
"tastyteaflavors.com","5.149.248.27"
|
||||
"telecom-info.com","185.225.68.61"
|
||||
"tengrinews.co","81.95.5.168"
|
||||
"theastafrican.com","185.156.173.104"
|
||||
"thebestclassicalmusic.net","217.64.113.250"
|
||||
"thecoffeeilove.com","185.225.68.199"
|
||||
"thehighesttemple.com","185.183.107.49"
|
||||
"thehoteloffers.com","185.225.68.203"
|
||||
"the-only-way-out.com","185.230.124.228"
|
||||
"theshopclub.org","185.225.68.160"
|
||||
"thespaclub.net","88.150.138.83"
|
||||
"theway2get.com","88.119.179.156"
|
||||
"ticket-aviata.info","185.94.191.14"
|
||||
"tiketon.info","185.94.191.120"
|
||||
"tlgr-me.org","185.225.68.130"
|
||||
"tobepure.com","88.119.179.205"
|
||||
"tommyfame.com","77.245.76.110"
|
||||
"top100vidz.com","62.113.232.207"
|
||||
"top10gifts4men.com","5.102.145.180"
|
||||
"top10leadsgen.com","200.7.97.230"
|
||||
"topbraingames4u.com","185.183.96.169"
|
||||
"topten-news.info","185.94.191.67"
|
||||
"touristvaca.com","185.198.57.200"
|
||||
"tradeexchanging.com","81.95.5.164"
|
||||
"traffic-pay.com","88.150.227.119"
|
||||
"traffic-updates.info","217.112.131.156"
|
||||
"travel-foryou.online","5.102.145.113"
|
||||
"travelight.online","81.95.5.147"
|
||||
"traveltogether.link","5.102.147.114"
|
||||
"tricksinswiss.com","89.238.138.136"
|
||||
"trililihihi.com","5.102.145.14"
|
||||
"t-support.net","109.200.24.15"
|
||||
"turismo-aqui.com","38.84.132.172"
|
||||
"tvshowcusting.com","31.184.198.150"
|
||||
"un-limitededitions.com","185.225.68.97"
|
||||
"unsubscribed.co","191.101.31.213"
|
||||
"untoldinfo.net","5.102.147.41"
|
||||
"updateapps.net","80.255.3.107"
|
||||
"upgrade-sim-card.com","217.112.131.150"
|
||||
"upload-now.net","88.150.227.116"
|
||||
"uptownfun.co","46.246.1.12"
|
||||
"urbestfriends.com","77.73.65.199"
|
||||
"url-redirect.com","66.172.10.189"
|
||||
"urlsync.com","185.141.25.210"
|
||||
"urspanishteacher.net","95.213.188.35"
|
||||
"vanillaandcream.com","77.245.76.113"
|
||||
"vastdealsnow.com","191.101.31.214"
|
||||
"verify-app.online","185.82.202.42"
|
||||
"videosdownload.co","5.102.146.66"
|
||||
"vider-image.com","185.225.68.123"
|
||||
"viedechretien.org","5.102.145.122"
|
||||
"vie-en-islam.com","5.102.147.234"
|
||||
"viewhdvideos.com","200.7.111.118"
|
||||
"vipmasajes.com","38.84.132.174"
|
||||
"viva-droid.com","5.102.146.64"
|
||||
"vivrechezsoi.info","5.102.147.236"
|
||||
"vkan-profile.com","185.225.68.129"
|
||||
"volcanosregion.com","5.102.146.85"
|
||||
"waffleswithnutella.com","66.85.157.83"
|
||||
"watersport4u.net","77.73.68.160"
|
||||
"weather4free.com","88.119.179.134"
|
||||
"weatherapi.co","206.189.51.151"
|
||||
"web-config.org","109.200.24.121"
|
||||
"websites4yourhost.com","185.234.73.10"
|
||||
"web-viewer.online","217.112.131.189"
|
||||
"welovebigcakes.com","185.117.75.82"
|
||||
"welovelollipops.com","185.45.192.144"
|
||||
"welovemorningcoffees.com","179.43.169.36"
|
||||
"wewantflowersnow.com","185.225.68.3"
|
||||
"whatcanidowithbirds.com","88.150.189.106"
|
||||
"whats-new.org","46.22.223.252"
|
||||
"whereismybonus.com","5.149.252.241"
|
||||
"whereismyhand.com","38.132.114.167"
|
||||
"whereisthehat.com","8.28.175.71"
|
||||
"windyone.net","200.7.105.24"
|
||||
"wintertimes.co","46.246.1.14"
|
||||
"wonderfulinsights.com","217.112.131.207"
|
||||
"woodhome4u.com","77.73.65.48"
|
||||
"xchange4u.net","185.183.107.44"
|
||||
"xchangerates247.net","185.183.96.139"
|
||||
"xn--nissn-3jc.com","89.238.132.249"
|
||||
"xn--noki-t5b.com","86.105.18.11"
|
||||
"xn--telegrm-qbd.com","185.225.68.136"
|
||||
"xtremelivesupport.com","5.102.146.237"
|
||||
"youcantpass.com","37.220.31.28"
|
||||
"yourbestclothes.com","46.21.147.197"
|
||||
"yourbestefforts.com","46.21.147.196"
|
||||
"yourbestvaca.com","104.216.8.38"
|
||||
"yourgreatestsmartphone.com","88.150.227.83"
|
||||
"yourhotelreservation.info","185.225.68.204"
|
||||
"yummyfoodallover.com","37.72.175.143"
|
||||
"zednewszm.com","217.64.113.251"
|
||||
"zm-banks.com","217.64.113.252"
|
||||
"zm-banks.com","89.43.60.103"
|
||||
"zm-weather.com","89.43.60.103"
|
||||
"zsports-info.com","89.43.60.104"
|
||||
|
@@ -1,216 +0,0 @@
|
||||
account-facebook.com
|
||||
account-mysecure.com
|
||||
account-privacy.com
|
||||
account-privcay.com
|
||||
account-servics.com
|
||||
account-servicse.com
|
||||
accounts-mysecure.com
|
||||
accounts-mysecures.com
|
||||
accounts-secuirty.com
|
||||
accounts-securtiy.com
|
||||
accounts-servicse.com
|
||||
accounts-settings.com
|
||||
alert-newmail02.pro
|
||||
application-secure.com
|
||||
applications-secure.com
|
||||
applications-security.com
|
||||
authorize-myaccount.com
|
||||
blu142-live.com
|
||||
blu160-live.com
|
||||
blu162-live.com
|
||||
blu165-live.com
|
||||
blu167-live.com
|
||||
blu175-live.com
|
||||
blu176-live.com
|
||||
blu178-live.com
|
||||
blu179-live.com
|
||||
blu187-live.com
|
||||
browser-checked.com
|
||||
browsering-check.com
|
||||
browsering-checked.com
|
||||
browsers-checked.com
|
||||
browser-secures.com
|
||||
browsers-secure.com
|
||||
browsers-secures.com
|
||||
bul174-live.com
|
||||
check-activities.com
|
||||
check-browser.com
|
||||
check-browsering.com
|
||||
check-browsers.com
|
||||
checking-browser.com
|
||||
connected-myaccount.com
|
||||
connect-myaccount.com
|
||||
data-center17.website
|
||||
documents-view.com
|
||||
documents-viewer.com
|
||||
document-viewer.com
|
||||
go2myprofile.info
|
||||
go2profiles.info
|
||||
googledriveservice.com
|
||||
gotolinks.top
|
||||
goto-newmail01.pro
|
||||
idmsa-login.com
|
||||
inbox01-email.pro
|
||||
inbox01-gomail.com
|
||||
inbox01-mails.icu
|
||||
inbox01-mails.pro
|
||||
inbox02-accounts.pro
|
||||
inbox02-mails.icu
|
||||
inbox02-mails.pro
|
||||
inbox03-accounts.pro
|
||||
inbox03-mails.icu
|
||||
inbox03-mails.pro
|
||||
inbox04-accounts.pro
|
||||
inbox04-mails.icu
|
||||
inbox04-mails.pro
|
||||
inbox05-accounts.pro
|
||||
inbox05-mails.icu
|
||||
inbox05-mails.pro
|
||||
inbox06-accounts.pro
|
||||
inbox06-mails.pro
|
||||
inbox07-accounts.pro
|
||||
inbox101-account.com
|
||||
inbox101-accounts.com
|
||||
inbox101-accounts.info
|
||||
inbox101-accounts.pro
|
||||
inbox101-live.com
|
||||
inbox102-account.com
|
||||
inbox102-live.com
|
||||
inbox102-mail.pro
|
||||
inbox103-account.com
|
||||
inbox103-mail.pro
|
||||
inbox104-accounts.pro
|
||||
inbox105-accounts.pro
|
||||
inbox106-accounts.pro
|
||||
inbox107-accounts.pro
|
||||
inbox108-accounts.pro
|
||||
inbox109-accounts.pro
|
||||
inbox169-live.com
|
||||
inbox171-live.com
|
||||
inbox171-live.pro
|
||||
inbox172-live.com
|
||||
inbox173-live.com
|
||||
inbox174-live.com
|
||||
inbox-live.com
|
||||
inbox-mail01.pro
|
||||
inbox-mail02.pro
|
||||
inbox-myaccount.com
|
||||
mail01-inbox.pro
|
||||
mail02-inbox.com
|
||||
mail02-inbox.pro
|
||||
mail03-inbox.com
|
||||
mail03-inbox.pro
|
||||
mail04-inbox.com
|
||||
mail04-inbox.pro
|
||||
mail05-inbox.pro
|
||||
mail06-inbox.pro
|
||||
mail07-inbox.pro
|
||||
mail08-inbox.pro
|
||||
mail09-inbox.pro
|
||||
mail101-inbox.com
|
||||
mail101-inbox.pro
|
||||
mail103-inbox.com
|
||||
mail103-inbox.pro
|
||||
mail104-inbox.com
|
||||
mail104-inbox.pro
|
||||
mail105-inbox.com
|
||||
mail105-inbox.pro
|
||||
mail106-inbox.pro
|
||||
mail107-inbox.pro
|
||||
mail108-inbox.pro
|
||||
mail109-inbox.pro
|
||||
mail10-inbox.pro
|
||||
mail110-inbox.pro
|
||||
mail12-inbox.pro
|
||||
mail13-inbox.pro
|
||||
mail14-inbox.pro
|
||||
mail15-inbox.pro
|
||||
mail16-inbox.pro
|
||||
mail17-inbox.pro
|
||||
mail18-inbox.pro
|
||||
mail19-inbox.pro
|
||||
mail201-inbox.pro
|
||||
mail20-inbox.pro
|
||||
mail21-inbox.pro
|
||||
mail-inbox.pro
|
||||
mailings-noreply.pro
|
||||
myaccountes-setting.com
|
||||
myaccountes-settings.com
|
||||
myaccount-inbox.pro
|
||||
myaccount-logins.com
|
||||
myaccount-redirects.com
|
||||
myaccount-setting.com
|
||||
myaccount-settinges.com
|
||||
myaccount-setup1.com
|
||||
myaccount-setup.com
|
||||
myaccount-setups.com
|
||||
myaccounts-login.com
|
||||
myaccounts-profile.com
|
||||
myaccounts-secuirty.com
|
||||
myaccounts-secures.com
|
||||
myaccounts-settings.com
|
||||
myaccounts-settinq.com
|
||||
myaccounts-settinqes.com
|
||||
myaccounts-transfer.com
|
||||
myaccount-transfer.com
|
||||
myaccount.verification-approve.com
|
||||
myaccount.verification-approves.com
|
||||
myaccuont-settings.com
|
||||
mysecure-account.com
|
||||
mysecure-accounts.com
|
||||
mysecures-accounts.com
|
||||
newinbox01-accounts.pro
|
||||
newinbox01-mails.pro
|
||||
newinbox02-accounts.pro
|
||||
newinbox03-accounts.pro
|
||||
newinbox05-accounts.pro
|
||||
newinbox06-accounts.pro
|
||||
newinbox07-accounts.pro
|
||||
newinbox08-accounts.pro
|
||||
newinbox-account.info
|
||||
newinbox-accounts.pro
|
||||
noreply.ac
|
||||
noreply-accounts.site
|
||||
noreply-mailer.pro
|
||||
noreply-mailers.com
|
||||
noreply-mailers.pro
|
||||
noreply-myaccount.com
|
||||
privacy-myaccount.com
|
||||
privcay-setting.com
|
||||
profile-settings.com
|
||||
protonemail.ch
|
||||
recovery-settings.info
|
||||
redirection-login.com
|
||||
redirection-logins.com
|
||||
redirections-login.com
|
||||
redirections-login.info
|
||||
redirects-myaccount.com
|
||||
royalk-uae.com
|
||||
secure-browsre.com
|
||||
secures-applications.com
|
||||
secures-browser.com
|
||||
secure-settinqes.com
|
||||
secures-inbox.com
|
||||
secures-inbox.info
|
||||
securesmails-alerts.pro
|
||||
secures-settinqes.com
|
||||
secures-transfer.com
|
||||
secures-transfers.com
|
||||
security-settinges.com
|
||||
securtiy-settings.com
|
||||
services-securtiy.com
|
||||
setting-privcay.com
|
||||
settings-secuity.com
|
||||
settinq-myaccounts.com
|
||||
settinqs-myaccount.com
|
||||
thx-me.website
|
||||
transfer-click.com
|
||||
transfer-clicks.com
|
||||
truecaller.services
|
||||
tutanota.org
|
||||
urllink.xyz
|
||||
verification-approve.com
|
||||
verification-approves.com
|
||||
verifications-approve.com
|
||||
xn--mxamya0a.ccn
|
||||
yahoo.llc
|
||||
@@ -1,34 +0,0 @@
|
||||
account-login.site
|
||||
adminmail.online
|
||||
email-secure.online
|
||||
login-acc.email
|
||||
login-network.space
|
||||
login-service.email
|
||||
login-service.online
|
||||
m4r3zb2ci0-noreply.pw
|
||||
mail-log.pw
|
||||
mail-secure.online
|
||||
mail-secure.tech
|
||||
mail-verify.live
|
||||
maillogin.pw
|
||||
mailverify.live
|
||||
my-mail-inbox.com
|
||||
redirect-secure.pw
|
||||
safebrowsing.website
|
||||
secure-accounts.online
|
||||
secure-conn.pw
|
||||
secure-email.site
|
||||
secure-emails.online
|
||||
secure-login.services
|
||||
service-login.online
|
||||
signin-aouth2.pw
|
||||
signin-verify.pw
|
||||
user-members.pro
|
||||
verify-mail.pro
|
||||
verifymail.live
|
||||
vers.pw
|
||||
weblive.pw
|
||||
whatsuppweb.me
|
||||
wi-fi.email
|
||||
www.secure-email.site
|
||||
xbz.pw
|
||||
@@ -1,5 +0,0 @@
|
||||
accounts@m4r3zb2ci0-noreply.pw
|
||||
noreply-team.googelsupport@verify-mail.pro
|
||||
secuirty.center.google.accounts@m4r3zb2ci0-noreply.pw
|
||||
support-team@m4r3zb2ci0-noreply.pw
|
||||
mails@m4r3zb2ci0-noreply.pw
|
||||
@@ -1,3 +0,0 @@
|
||||
srf-goolge.site
|
||||
gmailusercontent.site
|
||||
protect-outlook.com
|
||||
@@ -1,15 +0,0 @@
|
||||
admin@microsoftstore.com
|
||||
google.com@localhost
|
||||
google@script
|
||||
noreply750@mailgoogle.ccm
|
||||
noreply@gmailusercontent.site
|
||||
noreply@mailgoogle.ccm
|
||||
googlecommunityteam-noreply@srf-goolge.site
|
||||
noreply-accounts@goolge.cm
|
||||
noreply@accounts-goolge.com
|
||||
noreply@accounts-goolgeemail.site
|
||||
accounts-noreply@google.ccm
|
||||
noreply-accounts@google.ccm
|
||||
alerts@valabs.info
|
||||
google@noreply-accounts.com
|
||||
no-reply@goolge.email
|
||||
@@ -1,9 +0,0 @@
|
||||
stopsms.biz
|
||||
revolution-news.co
|
||||
videosdownload.co
|
||||
infospress.com
|
||||
business-today.info
|
||||
hmizat.co
|
||||
free247downloads.com
|
||||
bun54l2b67.get1tn0w.free247downloads.com
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
acccountsgoog1e.com
|
||||
account-mail.info
|
||||
accountapp.xyz
|
||||
accountsgoog1e.com
|
||||
alexandr01299.xyz
|
||||
auth-google.site
|
||||
auth-mail.email
|
||||
badoo-account-security.com
|
||||
chrome-redirect.top
|
||||
com-auth.site
|
||||
com-enter.site
|
||||
com-gm.site
|
||||
com-google.site
|
||||
check-activity.com.ru
|
||||
comericac.com
|
||||
desktest1.xyz
|
||||
desktest5.xyz
|
||||
desktest9.xyz
|
||||
dokerest.xyz
|
||||
dokertest.xyz
|
||||
droinjoin.xyz
|
||||
emails-support.site
|
||||
fedortest.xyz
|
||||
freekremlin.com
|
||||
frosdank.com
|
||||
frostdank.com
|
||||
garant-help.com
|
||||
gmail-warning.top
|
||||
google-activity.pw
|
||||
gvoice8765.online
|
||||
hpphhpph.com
|
||||
id-support-email.com
|
||||
joindroin.xyz
|
||||
lamatrest.xyz
|
||||
mail-auth.email
|
||||
mail-auth.online
|
||||
mail-google.email
|
||||
my-short.com
|
||||
myaccount-support.top
|
||||
mycabinet.xyz
|
||||
mynavvfedera1.org
|
||||
mynavyfedera1.org
|
||||
mynavyfedral.org
|
||||
mynevyfedera1.org
|
||||
navyfedara1.org
|
||||
navyfedera1.com
|
||||
navyfedera1.org
|
||||
navyfederai.org
|
||||
nayfedera1.org
|
||||
nevyfedera1.org
|
||||
nitroqensports.eu
|
||||
nsdns.xyz
|
||||
poxypoxy.xyz
|
||||
rc-room.com
|
||||
support-emails.host
|
||||
t1bank.xyz
|
||||
testdhome1.xyz
|
||||
testdhome4.xyz
|
||||
testdom1.xyz
|
||||
testdom3.xyz
|
||||
testfor7.xyz
|
||||
vkontak1e.com
|
||||
voice98765.online
|
||||
xn--avyfedera-yubm.org
|
||||
xn--bckchain-v3a30f.com
|
||||
xn--blckchain-17c.com
|
||||
xn--blockcain-lmb.com
|
||||
xn--mynavyfedera-occ.org
|
||||
xn--navyfderal-36a.com
|
||||
xn--navyfedera-j0b.org
|
||||
yandex-account-security.com
|
||||
@@ -1,22 +0,0 @@
|
||||
51.15.100.189
|
||||
51.15.114.133
|
||||
51.15.134.115
|
||||
51.15.253.174
|
||||
51.15.116.52
|
||||
212.47.244.155
|
||||
167.99.208.115
|
||||
142.93.219.124
|
||||
51.158.108.37
|
||||
51.158.168.110
|
||||
51.83.97.40
|
||||
134.209.86.7
|
||||
68.183.66.192
|
||||
167.71.93.148
|
||||
134.209.193.198
|
||||
217.61.0.148
|
||||
165.227.153.226
|
||||
68.183.49.14
|
||||
45.86.65.167
|
||||
208.68.39.124
|
||||
51.254.221.192
|
||||
217.61.17.175
|
||||
@@ -1,3 +0,0 @@
|
||||
279c70f2da2c361b62353bdaa388372adc14929b3be83571b1347d890fd6279c
|
||||
902c5f46ac101b6f30032d4c5c86ecec115add3605fb0d66057130b6e11c57e6
|
||||
ba1990b5e38191512718180d0de1ad2123e18330449b8c12877c4db60aeb05e4
|
||||
@@ -1,3 +0,0 @@
|
||||
# India: Human Rights Defenders Targeted by a Coordinated Spyware Operation
|
||||
|
||||
Indicators of the report [India: Human Rights Defenders Targeted by a Coordinated Spyware Operation](https://www.amnesty.org/en/latest/research/2020/06/india-human-rights-defenders-targeted-by-a-coordinated-spyware-operation/)
|
||||
@@ -1,3 +0,0 @@
|
||||
researchplanet.zapto.org
|
||||
socialstatistics.zapto.org
|
||||
duniaenewsportal.ddns.net
|
||||
@@ -1,5 +0,0 @@
|
||||
jagdish.meshraam@gmail.com
|
||||
drsnehapatil64@gmail.com
|
||||
sinhamuskaan04@gmail.com
|
||||
jennifergonzales789@gmail.com
|
||||
payalshastri79@gmail.com
|
||||
@@ -1,5 +0,0 @@
|
||||
185.82.202.155
|
||||
185.117.66.188
|
||||
185.117.74.47
|
||||
185.117.74.28
|
||||
185.45.193.14
|
||||
@@ -1,12 +0,0 @@
|
||||
e3dea449bf74434ee1c9cdc04ca68b8f3c9bac357768e07df303433f257d3b9a
|
||||
21d24e08889f75461a7ce6f21fc612a701bca35da1a218cf3cdd6e23f613bb4d
|
||||
16b5c74fb55f52ae0ae4328f65b2bf3bbe3e5ee34268c1d32a247a0a1dfa3186
|
||||
5a4aca57541954195953066a4be96dfb19776ba099d72f8f1d3677581594606e
|
||||
11cef331557eb693e718d27b6a7211a98d3982117a03ec1491db8098ea3cec00
|
||||
88b92d985b7d616c93c391731c1e4a6d3c8323fdcbf31cfc4d340e27253913a7
|
||||
b1b6e133aa320669c772ec7e5fd6fbe4cb3edca13ad5351f14df3c1f13939d09
|
||||
ea5f37e1feab670171963aa83b235c772202b2d4bb7289dd45302c3851dbd6f9
|
||||
de302a61e5f07b0e65753355d44d22181a2742ac3a92aa058bdcd00cc4dab788
|
||||
b09ca9d48a0455ed5e02a56aabeb397c41fb63320244719749e0741da72e79c4
|
||||
095ec879f323a0a3eceb97013125880d49ac701eef568e3b010fdddb1333941f
|
||||
ac4d5d938009fd44b2f7587986862ab2278887a17d32f748278445b625b3efd9
|
||||
@@ -1,25 +0,0 @@
|
||||
# Technical Report
|
||||
|
||||
This repository contains indicators of compromise and scripts related to the report [German-made FinSpy spyware found in Egypt, and Mac and Linux versions revealed ](https://www.amnesty.org/en/latest/research/2020/09/german-made-finspy-spyware-found-in-egypt-and-mac-and-linux-versions-revealed/) published by Amnesty Tech in September 2020.
|
||||
|
||||
Indicators:
|
||||
|
||||
* `domains.txt` : domains identified
|
||||
* `ips.txt` : IPv4 addresses identified
|
||||
* `sha256.csv` : sha256 of samples identified
|
||||
* `rules.yar` : Yara rules
|
||||
|
||||
Tools in the script folder:
|
||||
|
||||
* `decode_modules.py` : decode encrypted modules of Linux and MacOs
|
||||
* `read_config.py` : read FinSpy configuration
|
||||
* `android/extract_config.py` : extract configuration from FinSpy Android samples
|
||||
* `android/java_parser.py` : extract obfuscated strings from decompiled java code
|
||||
* `android/string_decoder.py` : decode obfuscated strings
|
||||
* `linux/extract_config.py` : extract configuration files from a Linux FinSpy installer
|
||||
* `cobaltstrike/cobaltstrike_config.py`: extract the configuration of a Cobalt Strike payload
|
||||
* `cobaltstrike/cobaltstrike_decode.py`: decode an obfuscated Cobalt Strike payload
|
||||
|
||||
Additional files:
|
||||
|
||||
* `android_tlv_list.csv` : list of TLV values extracted from the Android sample
|
||||
@@ -1,813 +0,0 @@
|
||||
Group ID,Group name,TLV value,Known TLV,TLV name,Function
|
||||
64,drives all get,131488,✔,TlvTypeGetAllDrivesRequest,
|
||||
64,drives all get,131744,✔,TlvTypeGetAllDrivesReply,
|
||||
66,contents folder get,135328,✔,TlvTypeGetFolderContentsRequest,
|
||||
66,contents folder get,135584,✔,TlvTypeGetFolderContentsReply,
|
||||
66,contents folder get,135840,✔,TlvTypeGetFolderContentsNext,
|
||||
66,contents folder get,136096,✔,TlvTypeGetFolderContentsEnd,
|
||||
68,download file,139424,✔,TlvTypeDownloadFileRequest,
|
||||
68,download file,139680,✔,TlvTypeCancelDownloadFileRequest,
|
||||
68,download file,139936,✔,TlvTypeDownloadFileReply,
|
||||
68,download file,140192,✔,TlvTypeDownloadFileNext,
|
||||
68,download file,140448,✔,TlvTypeDownloadFileEnd,
|
||||
68,download file,140704,✔,TlvTypeCancelDownloadFileReply,
|
||||
70,upload file,143520,✔,TlvTypeUploadFileRequest,
|
||||
70,upload file,143776,✔,TlvTypeCancelUploadFileRequest,
|
||||
70,upload file,144032,✔,TlvTypeUploadFileReply,
|
||||
70,upload file,144288,✔,TlvTypeUploadFileNext,
|
||||
70,upload file,144544,✔,TlvTypeUploadFileEnd,
|
||||
70,upload file,144800,✔,TlvTypeUploadFileCompleted,
|
||||
70,upload file,145056,✔,TlvTypeCancelUploadFileReply,
|
||||
72,delete file,147616,✔,TlvTypeDeleteFileRequest,
|
||||
72,delete file,147872,✔,TlvTypeDeleteFileReply,
|
||||
74,search file,151968,✔,TlvTypeSearchFileRequest,
|
||||
74,search file,152224,✔,TlvTypeSearchFileReply,
|
||||
74,search file,152480,✔,TlvTypeSearchFileNext,
|
||||
74,search file,152736,✔,TlvTypeSearchFileEnd,
|
||||
74,search file,152992,✔,TlvTypeCancelSearchFileRequest,
|
||||
74,search file,153248,✔,TlvTypeCancelSearchFileReply,
|
||||
78,fs,159888,✔,TlvTypeFSFileDataChunk,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/d, L/org/xmlpush/v3/o/h, L/org/xmlpush/v3/h/c"
|
||||
78,fs,160128,✔,TlvTypeFSDiskDrive,Lorg/xmlpush/v3/o/e
|
||||
78,fs,160384,✔,TlvTypeFSFullPath,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/f/b, L/org/xmlpush/v3/o/h, L/org/xmlpush/v3/h/c"
|
||||
78,fs,160640,✔,TlvTypeFSFilename,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, L/org/xmlpush/v3/h/c"
|
||||
78,fs,160896,✔,TlvTypeFSFileExtension,
|
||||
78,fs,161088,✔,TlvTypeFSDiskDriveType,Lorg/xmlpush/v3/o/e
|
||||
78,fs,161408,✔,TlvTypeFSFileSize,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
78,fs,161584,✔,TlvTypeFSIsFolder,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,161840,✔,TlvTypeFSReadOnly,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,162096,✔,TlvTypeFSHidden,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,162352,✔,TlvTypeFSSystem,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,162688,✔,TlvTypeFSFileCreationTime,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,162944,✔,TlvTypeFSFileLastAccessTime,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,163200,✔,TlvTypeFSFileLastWriteTime,"Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e"
|
||||
79,fs,163472,✔,TlvTypeFSFullPathM,"Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, L/org/xmlpush/v3/h/c"
|
||||
79,fs,163632,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
82,system config file,168096,✔,TlvTypeGetFileSystemConfigRequest,
|
||||
82,system config file,168352,✔,TlvTypeFileSystemConfigReply,
|
||||
82,system config file,168608,✔,TlvTypeSetFileSystemConfigRequest,
|
||||
128,line cmd,262560,✔,TlvTypeStartCmdLineSessionRequest,
|
||||
128,line cmd,262816,✔,TlvTypeStartCmdLineSessionReply,
|
||||
128,line cmd,263072,✔,TlvTypeStopCmdLineSessionRequest,
|
||||
128,line cmd,263328,✔,TlvTypeCmdLineSessionStoppedReply,
|
||||
128,line cmd,263584,✔,TlvTypeCmdLineExecute,
|
||||
128,line cmd,263840,✔,TlvTypeCmdLineExecutionResult,
|
||||
130,line cmd execute,266352,✔,TlvTypeCmdLineExecuteCommand,
|
||||
130,line cmd execute,266560,✔,TlvTypeCmdLineExecuteAnswerID,
|
||||
130,line cmd execute,266864,✔,TlvTypeCmdLineExecuteAnswerData,
|
||||
146,line config cmd,299168,✔,TlvTypeGetCmdLineConfigRequest,
|
||||
146,line config cmd,299424,✔,TlvTypeCmdLineConfigReply,
|
||||
146,line config cmd,299680,✔,TlvTypeSetCmdLineConfigRequest,
|
||||
160,config scheduler,328096,✔,TlvTypeGetSchedulerConfigRequest,
|
||||
160,config scheduler,328352,✔,TlvTypeSchedulerConfigReply,
|
||||
160,config scheduler,328608,✔,TlvTypeSetSchedulerConfigRequest,
|
||||
162,task scheduler,331920,✔,TlvTypeSchedulerTask,
|
||||
162,task scheduler,332192,✔,TlvTypeSchedulerTaskRecordByTime,
|
||||
162,task scheduler,332448,✔,TlvTypeSchedulerTaskRecordScreenWhenAppRuns,
|
||||
162,task scheduler,332704,✔,TlvTypeSchedulerTaskRecordMicWhenAppUsesIt,
|
||||
162,task scheduler,332960,✔,TlvTypeSchedulerTaskRecordWebCamWhenAppUsesIt,
|
||||
176,sch,360592,✔,TlvTypeSCHTaskConfiguration,L/org/xmlpush/v3/h/c
|
||||
176,sch,360752,✔,TlvTypeSCHTaskEnabled,L/org/xmlpush/v3/h/c
|
||||
176,sch,361344,✔,TlvTypeSCHTaskStartDateTime,L/org/xmlpush/v3/h/c
|
||||
176,sch,361600,✔,TlvTypeSCHTaskStopDateTime,L/org/xmlpush/v3/h/c
|
||||
176,sch,362112,✔,TlvTypeSCHApplicationName,
|
||||
176,sch,362288,✔,TlvTypeSCHApplicationWindowOnly,
|
||||
512,microphone,1048992,✔,TlvTypeStartMicrophoneRequest,
|
||||
512,microphone,1049248,✔,TlvTypeStartMicrophoneReply,
|
||||
512,microphone,1049504,✔,TlvTypeMicrophoneFrame,
|
||||
512,microphone,1049760,✔,TlvTypeStopMicrophoneRequest,
|
||||
512,microphone,1050016,✔,TlvTypeMicrophoneStoppedReply,
|
||||
512,microphone,1050272,✔,TlvTypeStartMicrophoneRecording,
|
||||
514,,1052736,✔,TlvTypeMICFrameID,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n"
|
||||
514,,1053072,✔,TlvTypeMICFrameData,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n"
|
||||
514,,1053312,✔,TlvTypeAudioSessionType,
|
||||
514,,1053568,✔,TlvTypeAudioEncodingType,
|
||||
518,audio config,1061024,✔,TlvTypeGetAudioConfigRequest,
|
||||
518,audio config,1061280,✔,TlvTypeAudioConfigReply,
|
||||
518,audio config,1061536,✔,TlvTypeSetAudioConfigRequest,
|
||||
520,type video,1066112,✔,TlvTypeVideoSessionType,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b"
|
||||
520,type video,1066368,✔,TlvTypeVideoEncodingType,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b"
|
||||
544,screen,1114528,✔,TlvTypeStartScreenRequest,
|
||||
544,screen,1114784,✔,TlvTypeStartScreenReply,
|
||||
544,screen,1115040,✔,TlvTypeScreenFrame,
|
||||
544,screen,1115296,✔,TlvTypeStopScreenRequest,
|
||||
544,screen,1115552,✔,TlvTypeScreenStoppedReply,
|
||||
544,screen,1115808,✔,TlvTypeStartScreenRecording,
|
||||
548,cam web,1122720,✔,TlvTypeStartWebCamRequest,
|
||||
548,cam web,1122976,✔,TlvTypeStartWebCamReply,
|
||||
548,cam web,1123232,✔,TlvTypeWebCamFrame,
|
||||
548,cam web,1123488,✔,TlvTypeStopWebCamRequest,
|
||||
548,cam web,1123744,✔,TlvTypeWebCamStoppedReply,
|
||||
548,cam web,1124000,✔,TlvTypeStartWebCamRecording,
|
||||
550,config video,1126560,✔,TlvTypeGetVideoConfigRequest,
|
||||
550,config video,1126816,✔,TlvTypeVideoConfigReply,
|
||||
550,config video,1127072,✔,TlvTypeSetVideoConfigRequest,
|
||||
552,,1130560,✔,TlvTypeVDFrameID,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b"
|
||||
552,,1130896,✔,TlvTypeVDFrameData,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b"
|
||||
552,,1131136,✔,TlvTypeOriginalVideoResolution,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b"
|
||||
552,,1131392,✔,TlvTypeVideoResolution,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b"
|
||||
552,,1132160,✔,TlvTypeAutomaticRecordingUID,
|
||||
576,key logging,1180064,✔,TlvTypeStartKeyLoggingRequest,
|
||||
576,key logging,1180320,✔,TlvTypeStartKeyLoggingReply,
|
||||
576,key logging,1180576,✔,TlvTypeKeyLoggingFrame,
|
||||
576,key logging,1180832,✔,TlvTypeStopKeyLoggingRequest,
|
||||
576,key logging,1181088,✔,TlvTypeKeyLoggingStoppedReply,
|
||||
582,config keylogger,1192096,✔,TlvTypeGetKeyloggerConfigRequest,
|
||||
582,config keylogger,1192352,✔,TlvTypeKeyloggerConfigReply,
|
||||
582,config keylogger,1192608,✔,TlvTypeSetKeyloggerConfigRequest,
|
||||
584,kl frame data,1196416,✔,TlvTypeKLFrameData,Lorg/xmlpush/v3/o/i
|
||||
640,skype,1311136,✔,TlvTypeSkypeAudioMetaInfo,
|
||||
640,skype,1311376,✔,TlvTypeSkypeAudioRecording,
|
||||
640,skype,1311648,✔,TlvTypeSkypeTextRecording,
|
||||
640,skype,1311904,✔,TlvTypeSkypeFileMetaInfo,
|
||||
640,skype,1312144,✔,TlvTypeSkypeFileRecording,
|
||||
640,skype,1312416,✔,TlvTypeSkypeContactsRecording,
|
||||
640,skype,1312640,✔,TlvTypeSkypeContactsUserData,
|
||||
646,config skype,1323168,✔,TlvTypeGetSkypeConfigRequest,
|
||||
646,config skype,1323424,✔,TlvTypeSkypeConfigReply,
|
||||
646,config skype,1323680,✔,TlvTypeSetSkypeConfigRequest,
|
||||
646,config skype,1324336,✔,TlvTypeConfigSkypeAudioEnable,
|
||||
646,config skype,1324592,✔,TlvTypeConfigSkypeTextEnable,
|
||||
646,config skype,1324848,✔,TlvTypeConfigSkypeFileEnable,
|
||||
647,config contacts enable list skype,1325104,✔,TlvTypeConfigSkypeContactsListEnable,
|
||||
648,skype,1327232,✔,TlvTypeSkypeAudioEncodingType,
|
||||
648,skype,1327488,✔,TlvTypeSkypeLoggedInUserAccountName,
|
||||
648,skype,1327744,✔,TlvTypeSkypeConversationPartnerAccountName,
|
||||
648,skype,1328000,✔,TlvTypeSkypeConversationPartnerDisplayName,
|
||||
648,skype,1328256,✔,TlvTypeSkypeChatMembers,
|
||||
648,skype,1328512,✔,TlvTypeSkypeTextMessage,
|
||||
648,skype,1328768,✔,TlvTypeSkypeChatID,
|
||||
648,skype,1329024,✔,TlvTypeSkypeSenderAccountName,
|
||||
649,skype,1329280,✔,TlvTypeSkypeSenderDisplayName,
|
||||
649,skype,1329536,✔,TlvTypeSkypeIncoming,
|
||||
649,skype,1329792,✔,TlvTypeSkypeSessionType,
|
||||
704,changed file,1442208,✔,TlvTypeChangedFileMetaInfo,
|
||||
704,changed file,1442432,✔,TlvTypeChangedFileChangeTime,
|
||||
704,changed file,1442688,✔,TlvTypeChangedFileChangeEvent,
|
||||
704,changed file,1442960,✔,TlvTypeChangedFileRecording,
|
||||
710,config changed,1454240,✔,TlvTypeGetChangedConfigRequest,
|
||||
710,config changed,1454496,✔,TlvTypeChangedConfigReply,
|
||||
710,config changed,1454752,✔,TlvTypeSetChangedConfigRequest,
|
||||
710,config changed,1454912,✔,TlvTypeConfigChangedEvents,
|
||||
736,,1507744,✔,TlvTypeAccessedFileMetaInfo,
|
||||
736,,1507968,✔,TlvTypeAccessedFileAccessTime,
|
||||
736,,1508224,✔,TlvTypeAccessedFileAccessEvent,
|
||||
736,,1508496,✔,TlvTypeAccessedFileRecording,
|
||||
736,,1508736,✔,TlvTypeAccessedApplicationName,
|
||||
736,,1508912,✔,TlvTypeConfigRecordImagesFromExplorer,
|
||||
742,accessed config,1519776,✔,TlvTypeGetAccessedConfigRequest,
|
||||
742,accessed config,1520032,✔,TlvTypeAccessedConfigReply,
|
||||
742,accessed config,1520288,✔,TlvTypeSetAccessedConfigRequest,
|
||||
742,accessed config,1520448,✔,TlvTypeConfigAccessedEvents,
|
||||
768,print,1573280,✔,TlvTypePrintFileMetaInfo,
|
||||
768,print,1573520,✔,TlvTypePrintFrame,
|
||||
772,print,1581184,✔,TlvTypePrintApplicationName,
|
||||
772,print,1581440,✔,TlvTypePrintFilename,
|
||||
772,print,1581696,✔,TlvTypePrintEncodingType,
|
||||
774,print config,1585312,✔,TlvTypeGetPrintConfigRequest,
|
||||
774,print config,1585568,✔,TlvTypePrintConfigReply,
|
||||
774,print config,1585824,✔,TlvTypeSetPrintConfigRequest,
|
||||
800,deleted,1638816,✔,TlvTypeDeletedFileMetaInfo,
|
||||
800,deleted,1639296,✔,TlvTypeDeletedFileDeletionTime,
|
||||
800,deleted,1639552,✔,TlvTypeDeletedFileRecycleBin,
|
||||
800,deleted,1639808,✔,TlvTypeDeletedMethod,
|
||||
800,deleted,1640064,✔,TlvTypeDeletedApplicationName,
|
||||
800,deleted,1640336,✔,TlvTypeDeletedFileRecording,
|
||||
806,config deleted,1650848,✔,TlvTypeGetDeletedConfigRequest,
|
||||
806,config deleted,1651104,✔,TlvTypeDeletedConfigReply,
|
||||
806,config deleted,1651360,✔,TlvTypeSetDeletedConfigRequest,
|
||||
1024,application upload forensics,2097568,✔,TlvTypeUploadForensicsApplicationRequest,
|
||||
1024,application upload forensics,2097824,✔,TlvTypeUploadForensicsApplicationReply,
|
||||
1024,application upload forensics,2098080,✔,TlvTypeUploadForensicsApplicationChunk,
|
||||
1024,application upload forensics,2098336,✔,TlvTypeUploadForensicsApplicationDoneRequest,
|
||||
1024,application upload forensics,2098592,✔,TlvTypeUploadForensicsApplicationDoneReply,
|
||||
1026,application remove forensics,2101664,✔,TlvTypeRemoveForensicsApplicationRequest,
|
||||
1026,application remove forensics,2101920,✔,TlvTypeRemoveForensicsApplicationReply,
|
||||
1028,app forensics execute,2105760,✔,TlvTypeForensicsAppExecuteRequest,
|
||||
1028,app forensics execute,2106016,✔,TlvTypeForensicsAppExecuteReply,
|
||||
1028,app forensics execute,2106272,✔,TlvTypeForensicsAppExecuteResult,
|
||||
1028,app forensics execute,2106528,✔,TlvTypeForensicsAppExecuteResultChunk,
|
||||
1028,app forensics execute,2106784,✔,TlvTypeForensicsAppExecuteResultDone,
|
||||
1028,app forensics execute,2107040,✔,TlvTypeForensicsCancelAppExecuteRequest,
|
||||
1028,app forensics execute,2107296,✔,TlvTypeForensicsCancelAppExecuteReply,
|
||||
1030,config forensics,2109600,✔,TlvTypeGetForensicsConfigRequest,
|
||||
1030,config forensics,2109856,✔,TlvTypeForensicsConfigReply,
|
||||
1030,config forensics,2110112,✔,TlvTypeSetForensicsConfigRequest,
|
||||
1032,application config info forensics,2113680,✔,TlvTypeConfigForensicsApplicationInfoGeneric,
|
||||
1032,application config info forensics,2113952,✔,TlvTypeConfigForensicsApplicationInfo,
|
||||
1034,forensics,2117760,✔,TlvTypeConfigForensicsApplicationName,
|
||||
1034,forensics,2117952,✔,TlvTypeConfigForensicsApplicationSize,
|
||||
1034,forensics,2118208,✔,TlvTypeConfigForensicsApplicationID,
|
||||
1034,forensics,2118528,✔,TlvTypeConfigForensicsApplicationCmdline,
|
||||
1034,forensics,2118784,✔,TlvTypeConfigForensicsApplicationOutput,
|
||||
1034,forensics,2118976,✔,TlvTypeConfigForensicsApplicationTimeout,
|
||||
1034,forensics,2119232,✔,TlvTypeConfigForensicsApplicationVersion,
|
||||
1034,forensics,2119552,✔,TlvTypeForensicsFriendlyName,
|
||||
1035,output application config forensics,2119808,✔,TlvTypeConfigForensicsApplicationOutputPrepend,
|
||||
1035,output application config forensics,2120064,✔,TlvTypeConfigForensicsApplicationOutputContentType,
|
||||
1056,vo meta info ip,2163104,✔,TlvTypeVoIPMetaInfo,
|
||||
1058,vo ip,2166912,✔,TlvTypeVoIPEncodingType,
|
||||
1058,vo ip,2167168,✔,TlvTypeVoIPSessionType,
|
||||
1058,vo ip,2167424,✔,TlvTypeVoIPApplicationName,Lorg/xmlpush/v3/o/n
|
||||
1058,vo ip,2167696,✔,TlvTypeVoIPAppScreenshot,
|
||||
1058,vo ip,2167952,✔,TlvTypeVoIPAudioRecording,
|
||||
1058,vo ip,2168112,✔,TlvTypeConfigVoIPScreenshotEnabled,
|
||||
1062,vo config ip,2175136,✔,TlvTypeGetVoIPConfigRequest,
|
||||
1062,vo config ip,2175392,✔,TlvTypeVoIPConfigReply,
|
||||
1062,vo config ip,2175648,✔,TlvTypeSetVoIPConfigRequest,
|
||||
1088,clicks mouse,2228640,✔,TlvTypeMouseClicksMetaInfo,
|
||||
1088,clicks mouse,2228896,✔,TlvTypeMouseClicksFrame,
|
||||
1090,clicks mouse,2232448,✔,TlvTypeMouseClicksEncodingType,
|
||||
1090,clicks mouse,2232896,✔,TlvTypeConfigMouseClicksRectangle,
|
||||
1090,clicks mouse,2233152,✔,TlvTypeConfigMouseClicksSensitivity,
|
||||
1090,clicks mouse,2233408,✔,TlvTypeConfigMouseClicksType,
|
||||
1094,clicks config mouse,2240672,✔,TlvTypeGetMouseClicksConfigRequest,
|
||||
1094,clicks config mouse,2240928,✔,TlvTypeMouseClicksConfigReply,
|
||||
1094,clicks config mouse,2241184,✔,TlvTypeSetMouseClicksConfigRequest,
|
||||
2112,sms,4325792,✔,TlvTypeMobileSMSMetaInfo,Lorg/xmlpush/v3/f/b
|
||||
2112,sms,4326016,✔,TlvTypeMobileSMSData,Lorg/xmlpush/v3/f/b
|
||||
2112,sms,4326256,✔,TlvTypeSMSSenderNumber,Lorg/xmlpush/v3/f/b
|
||||
2112,sms,4326512,✔,TlvTypeSMSRecipientNumber,Lorg/xmlpush/v3/f/b
|
||||
2112,sms,4326528,✔,TlvTypeSMSInformation,
|
||||
2112,sms,4326768,✔,TlvTypeSMSDirection,Lorg/xmlpush/v3/f/b
|
||||
2112,sms,4327040,×,unknown,Lorg/xmlpush/v3/f/b
|
||||
2144,address book mobile,4391328,✔,TlvTypeMobileAddressBookMetaInfo,Lorg/xmlpush/v3/i/a
|
||||
2144,address book mobile,4391552,✔,TlvTypeMobileAddressBookData,Lorg/xmlpush/v3/i/a
|
||||
2152,address book checksum mobile,4407360,✔,TlvTypeMobileAddressBookChecksum,
|
||||
2176,mobile blackberry,4456864,✔,TlvTypeMobileBlackberryMessengerMetaInfo,
|
||||
2176,mobile blackberry,4457088,✔,TlvTypeMobileBlackberryMessengerData,
|
||||
2176,mobile blackberry,4457328,✔,TlvTypeMobileBlackberryMsChatID,
|
||||
2176,mobile blackberry,4457600,✔,TlvTypeMobileBlackberryMsConversationPartners,
|
||||
2208,mobile tracking,4522400,✔,TlvTypeMobileTrackingStartRequest,
|
||||
2208,mobile tracking,4522656,✔,TlvTypeMobileTrackingStopRequest,
|
||||
2208,mobile tracking,4523376,✔,TlvTypeMobileTrackingDataV10,"Lorg/xmlpush/v3/t/e, Lorg/xmlpush/v3/t/e, Lorg/xmlpush/v3/t/e, Lorg/xmlpush/v3/t/e"
|
||||
2214,mobile config tracking,4535200,✔,TlvTypeMobileTrackingConfig,Lorg/xmlpush/v3/h/c
|
||||
2214,mobile config tracking,4535440,✔,TlvTypeMobileTrackingConfigRaw,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2216,mobile tracking,4538432,✔,TlvTypeMobileTrackingTimeInterval,L/org/xmlpush/v3/h/c
|
||||
2216,mobile tracking,4538688,✔,TlvTypeMobileTrackingDistance,L/org/xmlpush/v3/h/c
|
||||
2216,mobile tracking,4538928,✔,TlvTypeMobileTrackingSendOnAnyChannel,L/org/xmlpush/v3/h/c
|
||||
2240,mobile call phone,4587936,✔,TlvTypeMobilePhoneCallLogsMetaInfo,Lorg/xmlpush/v3/f/a
|
||||
2240,mobile call phone,4588192,✔,TlvTypeMobilePhoneCallLogsData,Lorg/xmlpush/v3/f/b
|
||||
2240,mobile call phone,4588400,✔,TlvTypeMobilePhoneCallLogsType,Lorg/xmlpush/v3/f/b
|
||||
2240,mobile call phone,4588672,✔,TlvTypeMobilePhoneCallAdditionalInformation,Lorg/xmlpush/v3/f/b
|
||||
2240,mobile call phone,4588912,✔,TlvTypeMobilePhoneCallLogsCallerNumber,Lorg/xmlpush/v3/f/b
|
||||
2240,mobile call phone,4589168,✔,TlvTypeMobilePhoneCallLogsCalleeNumber,Lorg/xmlpush/v3/f/b
|
||||
2240,mobile call phone,4589440,✔,TlvTypeMobilePhoneCallLogsCallerName,Lorg/xmlpush/v3/f/b
|
||||
2241,name call phone logs mobile callee,4589696,✔,TlvTypeMobilePhoneCallLogsCalleeName,Lorg/xmlpush/v3/f/b
|
||||
2242,last call phone entry mobile endtime log,4591680,✔,TlvTypeMobilePhoneCallLogLastEntryEndtime,
|
||||
3072,mobile logging,6291872,✔,TlvTypeMobileLoggingMetaInfo,
|
||||
3072,mobile logging,6292096,✔,TlvTypeMobileLoggingData,
|
||||
3616,master agent,7405984,✔,TlvTypeMasterAgentLogin,
|
||||
3616,master agent,7406240,✔,TlvTypeMasterAgentLoginAnswer,
|
||||
3616,master agent,7406752,✔,TlvTypeMasterAgentTargetList,
|
||||
3616,master agent,7407008,✔,TlvTypeMasterAgentTargetOnlineList,
|
||||
3616,master agent,7407264,✔,TlvTypeMasterAgentTargetInfoReply,
|
||||
3616,master agent,7407520,✔,TlvTypeMasterAgentUserList,
|
||||
3617,master agent list,7407776,✔,TlvTypeMasterAgentUserListReply,
|
||||
3617,master agent list,7408032,✔,TlvTypeMasterAgentTargetArchivedList,
|
||||
3617,master agent list,7408288,✔,TlvTypeMasterAgentTargetListEx,
|
||||
3617,master agent list,7408544,✔,TlvTypeMasterAgentTargetOnlineListEx,
|
||||
3617,master agent list,7408800,✔,TlvTypeMasterAgentMobileTargetArchivedList,
|
||||
3617,master agent list,7409056,✔,TlvTypeMasterAgentMobileTargetList,
|
||||
3617,master agent list,7409312,✔,TlvTypeMasterAgentMobileTargetOnlineList,
|
||||
3618,,7409824,✔,TlvTypeMasterAgentQueryFirst,
|
||||
3618,,7410080,✔,TlvTypeMasterAgentQueryNext,
|
||||
3618,,7410336,✔,TlvTypeMasterAgentQueryLast,
|
||||
3618,,7410592,✔,TlvTypeMasterAgentQueryAnswer,
|
||||
3618,,7410848,✔,TlvTypeMasterAgentRemoveRecord,
|
||||
3618,,7411104,✔,TlvTypeMasterAgentTargetInfoExReply,
|
||||
3618,,7411344,✔,TlvTypeTargetInfoExProperty,
|
||||
3618,,7411616,✔,TlvTypeTargetInfoExPropertyValue,
|
||||
3619,,7411840,✔,TlvTypeTargetInfoExPropertyValueName,
|
||||
3619,,7411968,✔,TlvTypeTargetInfoExPropertyValueData,
|
||||
3619,,7412384,✔,TlvTypeMasterAgentAlarm,
|
||||
3620,master agent,7413920,✔,TlvTypeMasterAgentRetrieveData,
|
||||
3620,master agent,7414176,✔,TlvTypeMasterAgentRetrieveDataAnswer,
|
||||
3620,master agent,7414432,✔,TlvTypeMasterAgentRemoveUser,
|
||||
3620,master agent,7414688,✔,TlvTypeMasterAgentRemoveTarget,
|
||||
3620,master agent,7414944,✔,TlvTypeMasterAgentRetrieveDataComments,
|
||||
3620,master agent,7415200,✔,TlvTypeMasterAgentUpdateDataComments,
|
||||
3620,master agent,7415712,✔,TlvTypeMasterAgentRetrieveActivityLogging,
|
||||
3621,master agent,7415968,✔,TlvTypeMasterAgentRetrieveMasterLogging,
|
||||
3621,master agent,7416224,✔,TlvTypeMasterAgentRetrieveAgentActivityLogging,
|
||||
3621,master agent,7417248,✔,TlvTypeMasterAgentSendUserGUIConfig,
|
||||
3621,master agent,7417504,✔,TlvTypeMasterAgentGetUserGUIConfigRequest,
|
||||
3621,master agent,7417760,✔,TlvTypeMasterAgentGetUserGUIConfigReply,
|
||||
3622,master agent,7418016,✔,TlvTypeMasterAgentProxyList,
|
||||
3622,master agent,7418272,✔,TlvTypeMasterAgentProxyInfoReply,
|
||||
3622,master agent,7419040,✔,TlvTypeMasterAgentNameValuePacket,
|
||||
3622,master agent,7419248,✔,TlvTypeMasterAgentValueName,
|
||||
3622,master agent,7419392,✔,TlvTypeMasterAgentValueData,
|
||||
3622,master agent,7419808,✔,TlvTypeMasterAgentRetrieveTargetHistory,
|
||||
3623,install master agent,7421088,✔,TlvTypeMasterAgentInstallMasterLicense,
|
||||
3623,install master agent,7421344,✔,TlvTypeMasterAgentInstallSoftwareUpdate,
|
||||
3623,install master agent,7421600,✔,TlvTypeMasterAgentInstallSoftwareUpdateChunk,
|
||||
3623,install master agent,7421856,✔,TlvTypeMasterAgentInstallSoftwareUpdateDone,
|
||||
3624,master agent,7422112,✔,TlvTypeMasterAgentSoftwareUpdateInfo,
|
||||
3624,master agent,7422368,✔,TlvTypeMasterAgentSoftwareUpdateInfoReply,
|
||||
3624,master agent,7422624,✔,TlvTypeMasterAgentSoftwareUpdate,
|
||||
3624,master agent,7422880,✔,TlvTypeMasterAgentSoftwareUpdateReply,
|
||||
3624,master agent,7423136,✔,TlvTypeMasterAgentSoftwareUpdateNext,
|
||||
3624,master agent,7423392,✔,TlvTypeMasterAgentAddTimeSchedule,
|
||||
3624,master agent,7423648,✔,TlvTypeMasterAgentAddScreenSchedule,
|
||||
3624,master agent,7423904,✔,TlvTypeMasterAgentAddLockedSchedule,
|
||||
3625,master agent,7424160,✔,TlvTypeMasterAgentRemoveSchedule,
|
||||
3625,master agent,7424416,✔,TlvTypeMasterAgentGetSchedulerList,
|
||||
3625,master agent,7424672,✔,TlvTypeMasterAgentSchedulerTimeAction,
|
||||
3625,master agent,7424928,✔,TlvTypeMasterAgentSchedulerScreenAction,
|
||||
3625,master agent,7425184,✔,TlvTypeMasterAgentSchedulerLockedAction,
|
||||
3625,master agent,7425440,✔,TlvTypeMasterAgentProjectSoftwareUpdateInfo,
|
||||
3625,master agent,7425696,✔,TlvTypeMasterAgentProjectSoftwareUpdateInfoReply,
|
||||
3625,master agent,7425952,✔,TlvTypeMasterAgentProjectSoftwareUpdate,
|
||||
3626,master agent,7426112,✔,TlvTypeMasterAgentSchedulerID,
|
||||
3626,master agent,7426368,✔,TlvTypeMasterAgentSchedulerStartTime,L/org/xmlpush/v3/h/c
|
||||
3626,master agent,7426624,✔,TlvTypeMasterAgentSchedulerStopTime,L/org/xmlpush/v3/h/c
|
||||
3626,master agent,7427488,✔,TlvTypeMasterAgentAddRecordedDataAvailableSchedule,
|
||||
3626,master agent,7427744,✔,TlvTypeMasterAgentSchedulerRecordedDataAvailableAction,
|
||||
3627,master agent data,7428256,✔,TlvTypeMasterAgentRetrieveRemoteMasterData,
|
||||
3627,master agent data,7428512,✔,TlvTypeMasterAgentRetrieveRemoteMasterDataReply,
|
||||
3627,master agent data,7428768,✔,TlvTypeMasterAgentDeleteRemoteMasterData,
|
||||
3627,master agent data,7429024,✔,TlvTypeMasterAgentRetrieveOfflineMasterData,
|
||||
3627,master agent data,7429280,✔,TlvTypeMasterAgentRetrieveOfflineMasterDataReply,
|
||||
3627,master agent data,7429536,✔,TlvTypeMasterAgentDeleteOfflineMasterData,
|
||||
3628,master agent,7430304,✔,TlvTypeMasterAgentQueryFirstEx,
|
||||
3628,master agent,7430560,✔,TlvTypeMasterAgentQueryNextEx,
|
||||
3628,master agent,7430816,✔,TlvTypeMasterAgentQueryLastEx,
|
||||
3628,master agent,7431072,✔,TlvTypeMasterAgentQueryAnswerEx,
|
||||
3628,master agent,7431328,✔,TlvTypeMasterAgentSendUserPreferences,
|
||||
3628,master agent,7431584,✔,TlvTypeMasterAgentGetUserPreferencesRequest,
|
||||
3628,master agent,7431840,✔,TlvTypeMasterAgentGetUserPreferencesReply,
|
||||
3628,master agent,7432096,✔,TlvTypeMasterAgentListMCFilesRequest,
|
||||
3629,master agent mc,7432608,✔,TlvTypeMasterAgentDeleteMCFiles,
|
||||
3629,master agent mc,7432864,✔,TlvTypeMasterAgentSendMCFiles,
|
||||
3629,master agent mc,7433120,✔,TlvTypeMasterAgentMCStatisticsRequest,
|
||||
3629,master agent mc,7433376,✔,TlvTypeMasterAgentMCStatisticsReply,
|
||||
3629,master agent mc,7433616,✔,TlvTypeMasterAgentMCStatisticsValues,
|
||||
3630,master agent,7434400,✔,TlvTypeMasterAgentTrojanKeyRequest,
|
||||
3630,master agent,7434656,✔,TlvTypeMasterAgentTrojanKeyReply,
|
||||
3630,master agent,7434912,✔,TlvTypeMasterAgentEvProtectionX509Request,
|
||||
3630,master agent,7435168,✔,TlvTypeMasterAgentEvProtectionX509Reply,
|
||||
3630,master agent,7435424,✔,TlvTypeMasterAgentEvProtectionImportCert,
|
||||
3630,master agent,7435680,✔,TlvTypeMasterAgentEvProtectionImportCertCompleted,
|
||||
3630,master agent,7435936,✔,TlvTypeMasterAgentConfigurationRequest,
|
||||
3630,master agent,7436192,✔,TlvTypeMasterAgentConfigurationReply,
|
||||
3631,master agent configuration,7436448,✔,TlvTypeMasterAgentConfigurationUpdateRequest,
|
||||
3631,master agent configuration,7436704,✔,TlvTypeMasterAgentConfigurationUpdateRequestCompleted,
|
||||
3631,master agent configuration,7436944,✔,TlvTypeMasterAgentConfiguration,
|
||||
3631,master agent configuration,7437216,✔,TlvTypeMasterAgentConfigurationValue,
|
||||
3631,master agent configuration,7437424,✔,TlvTypeMasterAgentConfigurationValueName,
|
||||
3631,master agent configuration,7437568,✔,TlvTypeMasterAgentConfigurationValueData,
|
||||
3631,master agent configuration,7437984,✔,TlvTypeMasterAgentConfigurationTransferDone,
|
||||
3632,master agent,7438496,✔,TlvTypeMasterAgentRetrieveTargetFile,
|
||||
3632,master agent,7438752,✔,TlvTypeMasterAgentRetrieveTargetFileAnswer,
|
||||
3632,master agent,7438912,✔,TlvTypeMasterAgentAlarmEntryID,
|
||||
3632,master agent,7439168,✔,TlvTypeMasterAgentAlarmEntryVersion,
|
||||
3632,master agent,7439424,✔,TlvTypeMasterAgentAlarmTriggerFlags,
|
||||
3632,master agent,7439776,✔,TlvTypeMasterAgentGetAlarmList,
|
||||
3632,master agent,7440032,✔,TlvTypeMasterAgentAddAlarmEntry,
|
||||
3632,master agent,7440288,✔,TlvTypeMasterAgentRemoveAlarmEntry,
|
||||
3633,master agent,7440544,✔,TlvTypeMasterAgentAlarmEntry,
|
||||
3633,master agent,7440800,✔,TlvTypeMasterAgentSystemStatus,
|
||||
3633,master agent,7441056,✔,TlvTypeMasterAgentSystemStatusRequest,
|
||||
3633,master agent,7441312,✔,TlvTypeMasterAgentSystemStatusReply,
|
||||
3633,master agent,7441552,✔,TlvTypeMasterAgentLicenseValues,
|
||||
3633,master agent,7441824,✔,TlvTypeMasterAgentLicenseValuesRequest,
|
||||
3633,master agent,7442080,✔,TlvTypeMasterAgentLicenseValuesReply,
|
||||
3634,master agent,7442592,✔,TlvTypeMasterAgentGetNetworkConfigurationRequest,
|
||||
3634,master agent,7442848,✔,TlvTypeMasterAgentSetNetworkConfigurationRequest,
|
||||
3634,master agent,7443104,✔,TlvTypeMasterAgentSetNetworkConfigurationReply,
|
||||
3634,master agent,7443360,✔,TlvTypeMasterAgentRetrieveAllowedModulesList,
|
||||
3634,master agent,7443616,✔,TlvTypeMasterAgentRetrieveAllowedModulesListAnswer,
|
||||
3636,master agent,7446688,✔,TlvTypeMasterAgentRemoveAllTargetData,
|
||||
3636,master agent,7446944,✔,TlvTypeMasterAgentForceDownloadRecordedData,
|
||||
3636,master agent,7447200,✔,TlvTypeMasterAgentTargetCreateNotification,
|
||||
3636,master agent,7447456,✔,TlvTypeMasterAgentMobileTargetInfoReply,
|
||||
3636,master agent,7447696,✔,TlvTypeMasterAgentMobileTargetInfoValues,
|
||||
3638,master agent alert,7450784,✔,TlvTypeMasterAgentAlert,
|
||||
3640,master agent,7454880,✔,TlvTypeMasterAgentAddUser,
|
||||
3640,master agent,7455392,✔,TlvTypeMasterAgentAddUserReply,
|
||||
3640,master agent,7455648,✔,TlvTypeMasterAgentModifyUser,
|
||||
3640,master agent,7455904,✔,TlvTypeMasterAgentSetUserPermission,
|
||||
3640,master agent,7456160,✔,TlvTypeMasterAgentSetTargetPermission,
|
||||
3640,master agent,7456400,✔,TlvTypeMasterAgentUserPermission,
|
||||
3640,master agent,7456656,✔,TlvTypeMasterAgentTargetPermission,
|
||||
3641,master agent,7456928,✔,TlvTypeMasterAgentUserPermissionValuePacket,
|
||||
3641,master agent,7457184,✔,TlvTypeMasterAgentTargetPermissionValuePacket,
|
||||
3641,master agent,7457344,✔,TlvTypeMasterAgentUserPermissionValueName,
|
||||
3641,master agent,7457600,✔,TlvTypeMasterAgentTargetPermissionValueName,
|
||||
3641,master agent,7457856,✔,TlvTypeMasterAgentUserPermissionValueData,
|
||||
3641,master agent,7458112,✔,TlvTypeMasterAgentTargetPermissionValueData,
|
||||
3641,master agent,7458464,✔,TlvTypeMasterAgentModifyPassword,
|
||||
3641,master agent,7458656,✔,TlvTypeMasterAgentMobileTargetPermissionValueName,
|
||||
3642,master agent,7458976,✔,TlvTypeMasterAgentUploadFile,
|
||||
3642,master agent,7459232,✔,TlvTypeMasterAgentUploadFileChunk,
|
||||
3642,master agent,7459488,✔,TlvTypeMasterAgentUploadFileDone,
|
||||
3642,master agent,7459744,✔,TlvTypeMasterAgentUploadFilesTransferDone,
|
||||
3642,master agent,7460000,✔,TlvTypeMasterAgentGetTargetModuleConfigRequest,
|
||||
3642,master agent,7460256,✔,TlvTypeMasterAgentRemoveFile,
|
||||
3642,master agent,7460512,✔,TlvTypeMasterAgentMobileProxyList,
|
||||
3642,master agent,7460768,✔,TlvTypeMasterAgentSMSProxyList,
|
||||
3643,master agent,7461024,✔,TlvTypeMasterAgentSMSProxyInfoReply,
|
||||
3643,master agent,7461280,✔,TlvTypeMasterAgentCallPhoneNumberList,
|
||||
3643,master agent,7461536,✔,TlvTypeMasterAgentCallPhoneNumberInfoReply,
|
||||
3643,master agent,7461792,✔,TlvTypeMasterAgentGetMobileTargetModuleConfigRequest,
|
||||
3643,master agent,7462048,✔,TlvTypeMasterAgentSendSMS,
|
||||
3647,master agent,7469984,✔,TlvTypeMasterAgentEncryptionRequired,
|
||||
3647,master agent,7470240,✔,TlvTypeMasterAgentFileCompleted,
|
||||
3647,master agent,7470496,✔,TlvTypeMasterAgentRequestCompleted,
|
||||
3647,master agent,7470752,✔,TlvTypeAgentMasterComm,
|
||||
3647,master agent,7471008,✔,TlvTypeMasterAgentRequestStatus,
|
||||
3648,master,7471424,✔,TlvTypeProxyMasterCommSig,
|
||||
3648,master,7471520,✔,TlvTypeMasterTargetConn,
|
||||
3648,master,7471776,✔,TlvTypeProxyMasterComm,
|
||||
3648,master,7472032,✔,TlvTypeMasterProxyComm,
|
||||
3648,master,7472288,✔,TlvTypeProxyMasterHeartBeatAnswer,
|
||||
3648,master,7472544,✔,TlvTypeProxyMasterDisconnect,
|
||||
3648,master,7472704,✔,TlvTypeProxyMasterNotification,
|
||||
3648,master,7473056,✔,TlvTypeProxyMasterRequest,
|
||||
3649,master,7473312,✔,TlvTypeMasterProxyCommNotification,
|
||||
3649,master,7473568,✔,TlvTypeMasterCheckTargetDisconnect,
|
||||
3680,target proxy,7536960,✔,TlvTypeProxyTargetCommSig,
|
||||
3680,target proxy,7537312,✔,TlvTypeProxyTargetComm,
|
||||
3680,target proxy,7537568,✔,TlvTypeProxyMasterTargetComm,
|
||||
3680,target proxy,7537728,✔,TlvTypeProxyTargetRequestCrypto,
|
||||
3680,target proxy,7538064,✔,TlvTypeProxyTargetAnswerCrypto,
|
||||
3744,target,7668128,✔,TlvTypeMasterTargetComm,
|
||||
3744,target,7668384,✔,TlvTypeTargetCloseAllLiveStreaming,
|
||||
3776,relay,7733664,✔,TlvTypeRelayProxyComm,
|
||||
3776,relay,7734176,✔,TlvTypeRelayDummyHeartbeat,
|
||||
4032,test type meta,8257792,✔,TlvTypeTestMetaTypeInvalid,
|
||||
4032,test type meta,8258608,✔,TlvTypeTestMetaTypeBool,
|
||||
4032,test type meta,8258880,✔,TlvTypeTestMetaTypeUInt,
|
||||
4032,test type meta,8259152,✔,TlvTypeTestMetaTypeInt,
|
||||
4032,test type meta,8259440,✔,TlvTypeTestMetaTypeString,
|
||||
4033,test,8259712,✔,TlvTypeTestMetaTypeUnicode,
|
||||
4033,test,8259984,✔,TlvTypeTestMetaTypeRaw,
|
||||
4033,test,8260256,✔,TlvTypeTestMetaTypeGroup,
|
||||
4033,test,8260416,✔,TlvTypeTestMemberIdentifier,
|
||||
4033,test,8260736,✔,TlvTypeTestMemberName,
|
||||
4096,target,8389008,✔,TlvTypeTargetData,
|
||||
4096,target,8389280,✔,TlvTypeTargetHeartBeat,
|
||||
4096,target,8389680,✔,TlvTypeTargetKeepSessionAlive,
|
||||
4096,target,8390000,✔,TlvTypeTargetLocalIP,
|
||||
4096,target,8390256,✔,TlvTypeTargetGlobalIP,
|
||||
4096,target,8390448,✔,TlvTypeTargetState,
|
||||
4097,agent master,8390784,✔,TlvTypeTargetID,
|
||||
4097,agent master,8391072,✔,TlvTypeGetInstalledModulesRequest,
|
||||
4097,agent master,8391328,✔,TlvTypeInstalledModulesReply,
|
||||
4097,agent master,8391488,✔,TlvTypeTrojanUID,
|
||||
4097,agent master,8391808,✔,TlvTypeTrojanID,
|
||||
4097,agent master,8392000,✔,TlvTypeTrojanMaxInfections,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4097,agent master,8392240,✔,TlvTypeScreenSaverOn,
|
||||
4097,agent master,8392496,✔,TlvTypeScreenLocked,
|
||||
4098,agent master,8392752,✔,TlvTypeRecordedDataAvailable,
|
||||
4098,agent master,8393024,✔,TlvTypeDownloadedRecordedDataTimeStamp,
|
||||
4098,agent master,8393280,✔,TlvTypeInstallationMode,
|
||||
4098,agent master,8393552,✔,TlvTypeTargetRemoveNotification,
|
||||
4098,agent master,8393792,✔,TlvTypeTargetPlatformBits,
|
||||
4098,agent master,8394032,✔,TlvTypeRemoveItselfMaxInfectionReached,
|
||||
4098,agent master,8394288,✔,TlvTypeRemoveItselfAtMasterRequest,
|
||||
4098,agent master,8394544,✔,TlvTypeRemoveItselfAtAgentRequest,
|
||||
4099,agent master,8394912,✔,TlvTypeRemoveItselfAtAgentReqRequest,
|
||||
4099,agent master,8395072,✔,TlvTypeRecordedFilesDownloadTotal,
|
||||
4099,agent master,8395328,✔,TlvTypeRecordedFilesDownloadProgress,
|
||||
4099,agent master,8395632,✔,TlvTypeTargetLicenseInfo,
|
||||
4099,agent master,8395840,✔,TlvTypeRemoveTargetLicenseInfo,
|
||||
4099,agent master,8396176,✔,TlvTypeTargetAllConfigurations,
|
||||
4100,target error,8396960,✔,TlvTypeTargetError,
|
||||
4102,target config,8401056,✔,TlvTypeGetTargetConfigRequest,
|
||||
4102,target config,8401312,✔,TlvTypeTargetConfigReply,
|
||||
4102,target config,8401568,✔,TlvTypeSetTargetConfigRequest,
|
||||
4102,target config,8402304,✔,TlvTypeConfigTargetID,
|
||||
4102,target config,8402496,✔,TlvTypeConfigTargetHeartbeatInterval,
|
||||
4102,target config,8402800,✔,TlvTypeConfigTargetProxy,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4103,agent master,8403008,✔,TlvTypeConfigTargetPort,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4103,agent master,8403584,✔,TlvTypeConfigAutoRemovalDateTime,
|
||||
4103,agent master,8403776,✔,TlvTypeConfigAutoRemovalIfNoProxy,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4103,agent master,8404032,✔,TlvTypeInternalAutoRemovalElapsedTime,
|
||||
4104,active hiding config,8405040,✔,TlvTypeConfigActiveHiding,
|
||||
4106,target module,8409248,✔,TlvTypeTargetLoadModuleRequest,
|
||||
4106,target module,8409504,✔,TlvTypeTargetLoadModuleReply,
|
||||
4106,target module,8409760,✔,TlvTypeTargetUnLoadModuleRequest,
|
||||
4106,target module,8410016,✔,TlvTypeTargetUnLoadModuleReply,
|
||||
4106,target module,8410272,✔,TlvTypeTargetUploadModuleRequest,
|
||||
4106,target module,8410528,✔,TlvTypeTargetUploadModuleReply,
|
||||
4106,target module,8410784,✔,TlvTypeTargetUploadModuleChunk,
|
||||
4106,target module,8411040,✔,TlvTypeTargetUploadModuleDoneRequest,
|
||||
4107,target module,8411296,✔,TlvTypeTargetUploadModuleDoneReply,
|
||||
4107,target module,8411552,✔,TlvTypeTargetRemoveModuleRequest,
|
||||
4107,target module,8411808,✔,TlvTypeTargetRemoveModuleReply,
|
||||
4107,target module,8412064,✔,TlvTypeTargetOfflineUploadModuleRequest,
|
||||
4107,target module,8412320,✔,TlvTypeTargetOfflineUploadModuleReply,
|
||||
4107,target module,8412576,✔,TlvTypeTargetOfflineUploadModuleChunk,
|
||||
4107,target module,8412832,✔,TlvTypeTargetOfflineUploadModuleDoneRequest,
|
||||
4107,target module,8413088,✔,TlvTypeTargetOfflineUploadModuleDoneReply,
|
||||
4108,target error,8413344,✔,TlvTypeTargetOfflineError,
|
||||
4108,target error,8413600,✔,TlvTypeTargetUploadError,
|
||||
4109,files reply master list agent mc,8415392,✔,TlvTypeMasterAgentListMCFilesReply,
|
||||
4110,target recorded,8417440,✔,TlvTypeTargetGetRecordedFilesRequest,
|
||||
4110,target recorded,8417696,✔,TlvTypeTargetRecordedFilesReply,
|
||||
4110,target recorded,8417952,✔,TlvTypeTargetRecordedFileDownloadRequest,
|
||||
4110,target recorded,8418208,✔,TlvTypeTargetRecordedFileDownloadReply,
|
||||
4110,target recorded,8418464,✔,TlvTypeTargetRecordedFileDownloadChunk,
|
||||
4110,target recorded,8418720,✔,TlvTypeTargetRecordedFileDownloadCompleted,
|
||||
4110,target recorded,8418976,✔,TlvTypeTargetRecordedFileDeleteRequest,
|
||||
4110,target recorded,8419232,✔,TlvTypeTargetRecordedFileDeleteReply,
|
||||
4111,target recorded ex,8419488,✔,TlvTypeTargetGetRecordedFilesRequestEx,
|
||||
4111,target recorded ex,8419744,✔,TlvTypeTargetRecordedFilesReplyEx,
|
||||
4111,target recorded ex,8420000,✔,TlvTypeTargetRecordedFileDeleteRequestEx,
|
||||
4111,target recorded ex,8420256,✔,TlvTypeTargetRecordedFilesDownloadRequestEx,
|
||||
4128,data,8454544,✔,TlvTypeProxyData,
|
||||
4128,data,8454800,✔,TlvTypeRelayData,
|
||||
4130,proxy,8458400,✔,TlvTypeProxyTargetDisconnect,
|
||||
4130,proxy,8458656,✔,TlvTypeProxyMobileTargetDisconnect,
|
||||
4130,proxy,8458912,✔,TlvTypeProxyDummyHeartbeat,
|
||||
4130,proxy,8459168,✔,TlvTypeProxyMobileDummyHeartbeat,
|
||||
4160,master,8520080,✔,TlvTypeMasterData,
|
||||
4160,master,8520768,✔,TlvTypeMasterMode,
|
||||
4160,master,8521024,✔,TlvTypeMasterToken,
|
||||
4160,master,8521344,✔,TlvTypeMasterQueryResult,
|
||||
4161,string master alarm,8522368,✔,TlvTypeMasterAlarmString,
|
||||
4192,agent,8585616,✔,TlvTypeAgentData,
|
||||
4192,agent,8585808,✔,TlvTypeAgentQueryID,
|
||||
4192,agent,8586048,✔,TlvTypeAgentQueryModSubmodID,
|
||||
4192,agent,8586304,✔,TlvTypeAgentQueryFromDate,
|
||||
4192,agent,8586560,✔,TlvTypeAgentQueryToDate,
|
||||
4192,agent,8586816,✔,TlvTypeAgentQuerySortOrder,
|
||||
4192,agent,8587136,✔,TlvTypeAgentQueryValueFilter,
|
||||
4193,uid agent,8587328,✔,TlvTypeAgentUID,
|
||||
4224,mobile,8651152,✔,TlvTypeMobileTargetData,
|
||||
4224,mobile,8651376,✔,TlvTypeMobileTargetHeartBeatV10,"Lorg/xmlpush/v3/o/g, Lorg/xmlpush/v3/o/g"
|
||||
4224,mobile,8651632,✔,TlvTypeMobileTargetExtendedHeartBeatV10,"Lorg/xmlpush/v3/o/g, Lorg/xmlpush/v3/q/b"
|
||||
4224,mobile,8651888,✔,TlvTypeMobileHeartBeatReplyV10,"Lorg/xmlpush/v3/o/h$b, Lorg/xmlpush/v3/o/l$2, L/org/xmlpush/v3/q/a, L/org/xmlpush/v3/q/c"
|
||||
4225,installed reply modules mobile,8653472,✔,TlvTypeMobileInstalledModulesReply,
|
||||
4225,installed reply modules mobile,8652912,×,unknown,Lorg/xmlpush/v3/o/l$2
|
||||
4226,module upload mobile target,8655008,✔,TlvTypeMobileTargetOfflineUploadModuleRequest,L/org/xmlpush/v3/o/h
|
||||
4226,module upload mobile target,8656032,✔,TlvTypeMobileTargetUploadModuleRequest,
|
||||
4226,module upload mobile target,8656288,✔,TlvTypeMobileTargetUploadModuleReply,
|
||||
4226,module upload mobile target,8656544,✔,TlvTypeMobileTargetUploadModuleChunk,
|
||||
4226,module upload mobile target,8656800,✔,TlvTypeMobileTargetUploadModuleDoneRequest,
|
||||
4227,target mobile,8657056,✔,TlvTypeMobileTargetUploadModuleDoneReply,
|
||||
4227,target mobile,8657312,✔,TlvTypeMobileTargetRemoveModuleRequest,
|
||||
4227,target mobile,8657568,✔,TlvTypeMobileTargetRemoveModuleReply,
|
||||
4227,target mobile,8657824,✔,TlvTypeMobileTargetOfflineUploadModuleReply,Lorg/xmlpush/v3/o/j
|
||||
4227,target mobile,8658080,✔,TlvTypeMobileTargetOfflineUploadModuleChunk,L/org/xmlpush/v3/o/h
|
||||
4227,target mobile,8658336,✔,TlvTypeMobileTargetOfflineUploadModuleDoneRequest,L/org/xmlpush/v3/o/h
|
||||
4227,target mobile,8658592,✔,TlvTypeMobileTargetOfflineUploadModuleDoneReply,Lorg/xmlpush/v3/o/j
|
||||
4227,target mobile,8658848,✔,TlvTypeMobileTargetOfflineError,
|
||||
4228,mobile target,8659104,✔,TlvTypeMobileTargetError,
|
||||
4228,mobile target,8659360,✔,TlvTypeMobileTargetGetRecordedFilesRequest,L/org/xmlpush/v3/o/h
|
||||
4228,mobile target,8659616,✔,TlvTypeMobileTargetRecordedFilesReply,Lorg/xmlpush/v3/o/d
|
||||
4228,mobile target,8659872,✔,TlvTypeMobileTargetRecordedFileDownloadRequest,L/org/xmlpush/v3/o/h
|
||||
4228,mobile target,8660128,✔,TlvTypeMobileTargetRecordedFileDownloadReply,Lorg/xmlpush/v3/o/d
|
||||
4228,mobile target,8660384,✔,TlvTypeMobileTargetRecordedFileDownloadChunk,Lorg/xmlpush/v3/o/d
|
||||
4228,mobile target,8660640,✔,TlvTypeMobileTargetRecordedFileDownloadCompleted,Lorg/xmlpush/v3/o/d
|
||||
4228,mobile target,8660896,✔,TlvTypeMobileTargetRecordedFileDeleteRequest,L/org/xmlpush/v3/o/h
|
||||
4229,target reply delete mobile recorded file,8661152,✔,TlvTypeMobileTargetRecordedFileDeleteReply,
|
||||
4230,mobile config target,8663968,✔,TlvTypeMobileTargetOfflineConfig,Lorg/xmlpush/v3/q/c
|
||||
4230,mobile config target,8664224,✔,TlvTypeMobileTargetEmergencyConfigAsTLV,
|
||||
4230,mobile config target,8664432,✔,TlvTypeMobileTargetEmergencyConfig,"L/org/xmlpush/v3/q/a, L/org/xmlpush/v3/q/c"
|
||||
4234,load module mobile target,8671392,✔,TlvTypeMobileTargetLoadModuleRequest,
|
||||
4234,load module mobile target,8671648,✔,TlvTypeMobileTargetLoadModuleReply,
|
||||
4234,load module mobile target,8671904,✔,TlvTypeMobileTargetUnLoadModuleRequest,
|
||||
4234,load module mobile target,8672160,✔,TlvTypeMobileTargetUnLoadModuleReply,
|
||||
4236,target error,8675472,✔,TlvTypeMobileTargetHeartbeatEvents,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4236,agent master files mc reply list,8675648,✔,TlvTypeMobileTargetHeartbeatInterval,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8675984,✔,TlvTypeMobileTargetHeartbeatRestrictions,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8676208,✔,TlvTypeConfigSMSPhoneNumber,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8676496,✔,TlvTypeMobileTargetPositioning,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8676672,✔,TlvTypeMobileTrojanUID,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/t/d, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/n, Lorg/xmlpush/v3/a/a, Lorg/xmlpush/v3/q/c, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/h/c, Lorg/xmlpush/v3/i/a, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8676976,✔,TlvTypeMobileTrojanID,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4236,recorded target,8677296,✔,TlvTypeMobileTargetLocationChangedRange,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4237,config,8677440,✔,TlvTypeConfigMobileAutoRemovalDateTime,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4237,config,8677808,✔,TlvTypeConfigOverwriteProxyAndPhones,
|
||||
4237,config,8678000,✔,TlvTypeConfigCallPhoneNumber,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4238,ex recorded target,8679488,✔,TlvTypeLocationAreaCode,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
4238,ex recorded target,8679744,✔,TlvTypeCellID,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
4238,ex recorded target,8680048,✔,TlvTypeMobileCountryCode,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
4238,data,8680304,✔,TlvTypeMobileNetworkCode,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
4238,data,8680560,✔,TlvTypeIMSI,
|
||||
4238,proxy,8680816,✔,TlvTypeIMEI,
|
||||
4238,proxy,8681072,✔,TlvTypeGPSLatitude,
|
||||
4238,proxy,8681328,✔,TlvTypeGPSLongitude,
|
||||
4239,proxy,8681520,✔,TlvTypeFirstHeartbeat,
|
||||
4239,master,8681872,✔,TlvTypeInstalledModules,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4240,gps valid values,8683568,✔,TlvTypeValidGPSValues,
|
||||
4288,mobile proxy comm target,8782176,✔,TlvTypeProxyMobileTargetCommSig,
|
||||
4288,mobile proxy comm target,8782496,✔,TlvTypeProxyMobileTargetComm,
|
||||
4288,mobile proxy comm target,8782752,✔,TlvTypeProxyMasterMobileTargetComm,
|
||||
4384,master mobile,8978752,✔,TlvTypeMobileProxyMasterCommSig,
|
||||
4384,master mobile,8978848,✔,TlvTypeMasterMobileTargetConn,
|
||||
4384,master mobile,8979104,✔,TlvTypeMobileProxyMasterComm,
|
||||
4384,master mobile,8979360,✔,TlvTypeMobileMasterProxyComm,
|
||||
4384,master mobile,8979616,✔,TlvTypeProxyMasterMobileHeartBeatAnswer,"Lorg/xmlpush/v3/o/l$2, L/org/xmlpush/v3/o/h"
|
||||
4384,master mobile,8979872,✔,TlvTypeMobileMasterProxyCommNotification,
|
||||
8128,agent,16646544,✔,TlvTypePlaintext,
|
||||
8128,agent uid,16646800,✔,TlvTypeCompression,
|
||||
8128,mobile,16647056,✔,TlvTypeEncryption,"Lorg/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8128,mobile,16647232,✔,TlvTypeTargetUID,
|
||||
8128,mobile,16647536,✔,TlvTypeIPAddress,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/n"
|
||||
8128,mobile,16647808,✔,TlvTypeUserName,
|
||||
8128,installed reply modules mobile,16648064,✔,TlvTypeComputerName,
|
||||
8129,installed reply modules mobile,16648304,✔,TlvTypeLoginName,
|
||||
8129,module upload mobile target,16648560,✔,TlvTypePassphrase,
|
||||
8129,module upload mobile target,16648832,✔,TlvTypeRecordID,
|
||||
8129,module upload mobile target,16649088,✔,TlvTypeOwner,
|
||||
8129,module upload mobile target,16649344,✔,TlvTypeMetaData,
|
||||
8129,module upload mobile target,16649536,✔,TlvTypeModuleID,"Lorg/xmlpush/v3/o/d, L/org/xmlpush/v3/o/h, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8129,mobile target,16649856,✔,TlvTypeOSName,
|
||||
8129,mobile target,16650048,✔,TlvTypeModuleSubID,"Lorg/xmlpush/v3/o/d, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8130,mobile target,16650320,✔,TlvTypeErrorCode,
|
||||
8130,mobile target,16650560,✔,TlvTypeOffset,
|
||||
8130,mobile target,16650816,✔,TlvTypeLength,
|
||||
8130,mobile target,16651088,✔,TlvTypeRequestID,"Lorg/xmlpush/v3/w, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/j, Lorg/xmlpush/v3/o/j, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/n, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/o/d, Lorg/xmlpush/v3/q/c, Lorg/xmlpush/v3/f/b, L/org/xmlpush/v3/o/h, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8130,mobile target,16651328,✔,TlvTypeRequestType,
|
||||
8130,mobile target,16651584,✔,TlvTypeVersion,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8130,mobile target,16651840,✔,TlvTypeMachineID,
|
||||
8130,mobile target,16652096,✔,TlvTypeMajorNumber,
|
||||
8131,mobile target,16652352,✔,TlvTypeMinorNumber,
|
||||
8131,mobile target,16652656,✔,TlvTypeGlobalIPAddress,
|
||||
8131,mobile target,16652912,✔,TlvTypeASCII_Filename,
|
||||
8131,mobile target,16653120,✔,TlvTypeFilesize,
|
||||
8131,mobile target,16653392,✔,TlvTypeFilecount,
|
||||
8131,mobile target,16653712,✔,TlvTypeFiledata,
|
||||
8131,target reply recorded delete file mobile,16653968,✔,TlvTypeMD5Sum,
|
||||
8131,mobile target config,16654144,✔,TlvTypeProxyPort,
|
||||
8132,mobile target config,16654400,✔,TlvTypeStatus,
|
||||
8132,mobile target config,16654656,✔,TlvTypeUserID,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
8132,module load mobile target,16654912,✔,TlvTypeGroupID,
|
||||
8132,module load mobile target,16655168,✔,TlvTypePermissions,
|
||||
8132,module load mobile target,16655424,✔,TlvTypeRequestCode,
|
||||
8132,module load mobile target,16655680,✔,TlvTypeDataSize,
|
||||
8132,,16655936,✔,TlvTypeKeyType,
|
||||
8132,,16656240,✔,TlvTypeEmail,
|
||||
8133,,16656432,✔,TlvTypeEnabled,
|
||||
8133,,16656688,✔,TlvTypeLicensed,
|
||||
8133,,16656960,✔,TlvTypeAudioFrequency,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n"
|
||||
8133,,16657216,✔,TlvTypeAudioBitsPerSample,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n"
|
||||
8133,,16657472,✔,TlvTypeAudioChannels,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n"
|
||||
8133,,16657728,✔,TlvTypeStartTime,
|
||||
8133,config,16657984,✔,TlvTypeStopTime,
|
||||
8133,config,16658240,✔,TlvTypeBitMask,
|
||||
8134,config,16658560,✔,TlvTypeTimeZone,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/t/d, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/o/n, Lorg/xmlpush/v3/a/a, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
8134,,16658816,✔,TlvTypeDateTime,"Lorg/xmlpush/v3/t/d, Lorg/xmlpush/v3/o/e, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b"
|
||||
8134,,16659072,✔,TlvTypeStartSessionDateTime,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/i, Lorg/xmlpush/v3/o/n, Lorg/xmlpush/v3/a/a, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
8134,,16659328,✔,TlvTypeStopSessionDateTime,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/n"
|
||||
8134,,16659520,✔,TlvTypeDateTimeRef,"L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8134,,16659776,✔,TlvTypeScheduleRepeat,"L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8134,,16660032,✔,TlvTypeUnixMasterDateTime,
|
||||
8134,,16660288,✔,TlvTypeUnixUTCDateTime,
|
||||
8135,,16660544,✔,TlvTypeDurationInSeconds,Lorg/xmlpush/v3/f/b
|
||||
8135,,16660864,✔,TlvTypeMasterRefTime,
|
||||
8135,,16661120,✔,TlvTypeMasterRefTimeStart,
|
||||
8135,values gps valid,16661376,✔,TlvTypeMasterRefTimeEnd,
|
||||
8135,,16661568,✔,TlvTypeCounter,"Lorg/xmlpush/v3/q/c, Lorg/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8135,,16661888,✔,TlvTypeWhiteListEntry,type: byte array
|
||||
8135,,16662144,✔,TlvTypeBlackListEntry,type: array
|
||||
8135,,16662336,✔,TlvTypeBlackWhiteListingMode,
|
||||
8136,config,16662576,✔,TlvTypeConfigEnabled,
|
||||
8136,config,16662848,✔,TlvTypeConfigMaxRecordingSize,
|
||||
8136,config,16663104,✔,TlvTypeConfigAudioQuality,"Lorg/xmlpush/v3/o/a, Lorg/xmlpush/v3/o/n, L/org/xmlpush/v3/h/c"
|
||||
8136,config,16663344,✔,TlvTypeConfigVideoBlackAndWhite,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, L/org/xmlpush/v3/h/c"
|
||||
8136,config,16663616,✔,TlvTypeConfigVideoResolution,L/org/xmlpush/v3/h/c
|
||||
8136,config,16663872,✔,TlvTypeConfigCaptureFrequency,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, L/org/xmlpush/v3/h/c"
|
||||
8136,config,16664128,✔,TlvTypeConfigVideoQuality,"Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/k, Lorg/xmlpush/v3/o/b, Lorg/xmlpush/v3/o/b, L/org/xmlpush/v3/h/c"
|
||||
8136,config,16664384,✔,TlvTypeConfigFilesStandardFilter,
|
||||
8137,config,16664704,✔,TlvTypeConfigFilesCustomFilter,
|
||||
8137,config,16664896,✔,TlvTypeConfigStandardLocation,
|
||||
8137,config,16665216,✔,TlvTypeConfigCustomLocation,
|
||||
8137,config,16665408,✔,TlvTypeConfigFileChunkSize,
|
||||
8137,config,16665664,✔,TlvTypeConfigFileTransferSpeed,
|
||||
8137,config,16665904,✔,TlvTypeConfigUploadFileOverwrite,
|
||||
8137,config,16666160,✔,TlvTypeConfigDeleteOverReboot,
|
||||
8137,config,16666496,✔,TlvTypeConfigCustomLocationException,
|
||||
8138,master mobile,16666752,✔,TlvTypeExtraData,
|
||||
8138,master mobile,16667008,✔,TlvTypeSignature,
|
||||
8138,,16667264,✔,TlvTypeComments,
|
||||
8138,,16667520,✔,TlvTypeDescription,
|
||||
8138,,16667776,✔,TlvTypeFilenameExtension,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/f/b"
|
||||
8138,,16668032,✔,TlvTypeSessionType,
|
||||
8138,,16668224,✔,TlvTypePeriod,
|
||||
8138,,16668512,✔,TlvTypeMobileTargetUID,"Lorg/xmlpush/v3/w, Lorg/xmlpush/v3/o/g, Lorg/xmlpush/v3/o/c, Lorg/xmlpush/v3/a/a, Lorg/xmlpush/v3/q/c, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/h/c, Lorg/xmlpush/v3/h/c, L/org/xmlpush/v3/o/h, L/org/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
8139,,16668784,✔,TlvTypeMobileTargetID,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
8139,,16669072,✔,TlvTypeMobilePlaintext,
|
||||
8139,,16669328,✔,TlvTypeMobileCompression,Lorg/xmlpush/v3/k
|
||||
8139,,16669584,✔,TlvTypeMobileEncryption,"Lorg/xmlpush/v3/o/m, Lorg/xmlpush/v3/h/c"
|
||||
8139,,16669824,✔,TlvTypeEncodingType,
|
||||
8139,,16670576,✔,TlvTypePhoneNumber,"Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/n/m, Lorg/xmlpush/v3/t/d, Lorg/xmlpush/v3/a/a, Lorg/xmlpush/v3/f/a, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/f/b, Lorg/xmlpush/v3/d/a, Lorg/xmlpush/v3/i/a"
|
||||
8140,custom config location mode,16670784,✔,TlvTypeConfigCustomLocationMode,
|
||||
8140,custom config location mode,16672080,×,unknown,Lorg/xmlpush/v3/n/k
|
||||
8140,custom config location mode,16671792,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
8142,network interface,16674928,✔,TlvTypeNetworkInterface,
|
||||
8142,network interface,16675136,✔,TlvTypeNetworkInterfaceMode,
|
||||
8142,network interface,16675440,✔,TlvTypeNetworkInterfaceAddress,
|
||||
8142,network interface,16675696,✔,TlvTypeNetworkInterfaceNetmask,
|
||||
8142,network interface,16675952,✔,TlvTypeNetworkInterfaceGateway,
|
||||
8142,network interface,16676208,✔,TlvTypeNetworkInterfaceDNS_1,
|
||||
8142,network interface,16676464,✔,TlvTypeNetworkInterfaceDNS_2,
|
||||
8143,,16677440,✔,TlvTypeLoginTime,
|
||||
8143,,16677696,✔,TlvTypeLogoffTime,
|
||||
8143,,16678720,✔,TlvTypeGeneric_Type,
|
||||
8144,,16678976,✔,TlvTypeChecksum,
|
||||
8144,,16679280,✔,TlvTypeCity,
|
||||
8144,,16679536,✔,TlvTypeCountry,
|
||||
8144,,16679792,✔,TlvTypeCountryCode,
|
||||
8146,,16683072,✔,TlvTypeTargetType,
|
||||
8146,,16683392,✔,TlvTypeDurationString,Lorg/xmlpush/v3/o/a
|
||||
8146,,16683904,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
8146,,16684848,×,unknown,"Lorg/xmlpush/v3/o/k, L/org/xmlpush/v3/h/c"
|
||||
8160,,16712000,✔,TlvTypeTargetConnectionBroken,
|
||||
8160,,16712256,✔,TlvTypeAgentConnectionBroken,
|
||||
8160,,16712512,✔,TlvTypeTargetOffline,
|
||||
8176,,16744768,✔,TlvTypeProxyConnectionBroken,
|
||||
4242,,8688960,×,unknown,Lorg/xmlpush/v3/w
|
||||
4242,,8689296,×,unknown,Lorg/xmlpush/v3/w
|
||||
4242,,8689568,×,unknown,Lorg/xmlpush/v3/w
|
||||
2752,,5636992,×,unknown,Lorg/xmlpush/v3/n/k
|
||||
2752,,5637504,×,unknown,Lorg/xmlpush/v3/n/k
|
||||
2752,,5637760,×,unknown,Lorg/xmlpush/v3/n/k
|
||||
2752,,5636464,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2752,,5636736,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2752,,5637248,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2753,,5638256,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2753,,5638768,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2754,,5641600,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2754,,5640608,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2754,,5641120,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2754,,5640864,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2754,,5640352,×,unknown,Lorg/xmlpush/v3/n/m
|
||||
2218,,4542832,×,unknown,Lorg/xmlpush/v3/t/d
|
||||
2218,,4542624,×,unknown,Lorg/xmlpush/v3/t/d
|
||||
8147,,16685104,×,unknown,"Lorg/xmlpush/v3/o/k, L/org/xmlpush/v3/h/c"
|
||||
8147,,16685392,×,unknown,"Lorg/xmlpush/v3/o/k, L/org/xmlpush/v3/h/c"
|
||||
2658,,5444000,×,unknown,Lorg/xmlpush/v3/o/k
|
||||
2658,,5444512,×,unknown,Lorg/xmlpush/v3/o/k
|
||||
2656,,5440320,×,unknown,Lorg/xmlpush/v3/o/k
|
||||
2656,,5439904,×,unknown,Lorg/xmlpush/v3/o/k
|
||||
2660,,5447840,×,unknown,Lorg/xmlpush/v3/o/k
|
||||
2722,,5575072,×,unknown,Lorg/xmlpush/v3/o/a
|
||||
2722,,5575328,×,unknown,Lorg/xmlpush/v3/o/a
|
||||
2722,config,5575840,×,unknown,Lorg/xmlpush/v3/o/a
|
||||
2560,config,5243552,×,unknown,Lorg/xmlpush/v3/o/i
|
||||
2560,config,5243296,×,unknown,Lorg/xmlpush/v3/o/i
|
||||
4244,config,8693104,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8692080,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8692336,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8692592,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8692848,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8693360,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
4244,config,8691872,×,unknown,Lorg/xmlpush/v3/o/g
|
||||
2690,config,5509536,×,unknown,Lorg/xmlpush/v3/o/b
|
||||
2690,config,5510048,×,unknown,Lorg/xmlpush/v3/o/b
|
||||
2692,config,5513376,×,unknown,Lorg/xmlpush/v3/o/b
|
||||
2688,config,5505856,×,unknown,Lorg/xmlpush/v3/o/b
|
||||
2688,config,5505440,×,unknown,Lorg/xmlpush/v3/o/b
|
||||
2592,config,5309088,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2602,,5329824,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2602,,5330592,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2602,,5329568,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2602,,5330080,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2596,,5317536,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2596,,5317792,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2596,,5318048,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2596,,5317280,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2594,,5313440,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2594,,5312928,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2594,,5313184,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2600,,5325216,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2598,,5321376,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2598,,5322144,×,unknown,Lorg/xmlpush/v3/o/e
|
||||
2784,mode location custom config,5703584,×,unknown,Lorg/xmlpush/v3/o/n
|
||||
2784,mode location custom config,5703328,×,unknown,Lorg/xmlpush/v3/o/n
|
||||
2784,mode location custom config,5702816,×,unknown,Lorg/xmlpush/v3/o/n
|
||||
2784,interface network,5702032,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2784,interface network,5702304,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
2785,interface network,5703808,×,unknown,Lorg/xmlpush/v3/o/n
|
||||
2785,interface network,5704064,×,unknown,Lorg/xmlpush/v3/o/n
|
||||
1757,interface network,3600000,×,unknown,Lorg/xmlpush/v3/b/f
|
||||
2696,interface network,5521552,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2696,interface network,5521568,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
2720,,5570960,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2720,,5571232,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
2756,,5644432,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2756,,5644704,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
2848,,5833104,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2848,,5833376,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
3104,,6357392,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
3104,,6357664,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
2664,,5456016,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
2664,,5456288,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
4243,,8690064,×,unknown,"Lorg/xmlpush/v3/q/c, L/org/xmlpush/v3/h/c"
|
||||
4243,,8690336,×,unknown,Lorg/xmlpush/v3/h/c
|
||||
4243,,8689712,×,unknown,"Lorg/xmlpush/v3/h/c, L/org/xmlpush/v3/h/c"
|
||||
2304,,4719008,×,unknown,Lorg/xmlpush/v3/d/a
|
||||
2304,,4719232,×,unknown,Lorg/xmlpush/v3/d/a
|
||||
3106,,6361200,×,unknown,Lorg/xmlpush/v3/k/c
|
||||
16425,,33639248,×,unknown,Lorg/xmlpush/v3/h/a
|
||||
48781,,99903492,×,unknown,"Lorg/b/b/e$gs, L/org/b/b/e$r"
|
||||
41609,,85215461,×,unknown,"Lorg/b/b/e$df, L/org/b/b/e$j"
|
||||
4494,,9203775,×,unknown,"Lorg/b/b/e$ol, L/org/b/b/e$pi"
|
||||
25586,,52401552,×,unknown,"Lorg/b/b/e$js, L/org/b/b/e$x"
|
||||
21214,,43446532,×,unknown,"Lorg/b/b/e$ec, L/org/b/b/e$m"
|
||||
27793,,56920439,×,unknown,"Lorg/b/b/e$az, L/org/b/b/e$d"
|
||||
26992,,55281185,×,unknown,"Lorg/b/b/e$nj, L/org/b/b/e$ag"
|
||||
44308,,90744648,×,unknown,"Lorg/b/b/e$ew, L/org/b/b/e$ev"
|
||||
|
@@ -1,4 +0,0 @@
|
||||
flash.browserupdate.download
|
||||
current.browserupdate.download
|
||||
files.browserupdate.download
|
||||
browserupdate.download
|
||||
@@ -1,6 +0,0 @@
|
||||
172.241.27.171
|
||||
5.135.174.213
|
||||
158.69.105.207
|
||||
207.244.95.223
|
||||
45.11.19.235
|
||||
185.125.230.203
|
||||
@@ -1,174 +0,0 @@
|
||||
rule finspy_linux_installer1 {
|
||||
meta:
|
||||
description = "Rule for FinSpy Linux installer x86 or x64"
|
||||
author = "Etienne Maynier, Amnesty Tech"
|
||||
sample = "8aaf886a2a2cd459e65277343bc951a2d23555980eddd73218a5c608e6d2a29c"
|
||||
strings:
|
||||
$a = "%s/.kde/Autostart" ascii wide nocase
|
||||
$b = "%s/.kde4/Autostart" ascii wide nocase
|
||||
$c = "dmesg --notime 2>/dev/null | grep -i \"hypervisor detected\" | cut -d ':' -f2" ascii wide nocase
|
||||
$d = "g_plauncher" ascii wide nocase
|
||||
$e = "g_pinstall_host_location" ascii wide nocase
|
||||
$f = "g_pinstall_folder" ascii wide nocase
|
||||
$g = "%s/.bash_profile" ascii wide nocase
|
||||
$h = "lspci 2>/dev/null | grep -i \"system peripheral\" | grep -i \"virtual\"" ascii wide nocase
|
||||
$i = "lspci | grep -i \"system peripheral\" | grep -i \"virtual\"" ascii nocase
|
||||
|
||||
condition:
|
||||
7 of them
|
||||
}
|
||||
|
||||
rule finppy_linux_coremodule {
|
||||
meta:
|
||||
description = "Rule for FinSpy Linux core module x86 or x64"
|
||||
author = "Etienne Maynier, Amnesty Tech"
|
||||
strings:
|
||||
$s1 = "ps auxww | grep -iEe 'bt-scan' | grep -v -e grep" ascii
|
||||
$s2 = "ls /sys/class/net/ 2>/dev/null | awk '{printf (\"%s\n\", $1)}' 2>/dev/null" ascii
|
||||
$s3 = "cat /sys/class/net/eth?/address 2>/dev/null" ascii
|
||||
$s4 = "dmesg --notime 2>/dev/null | grep -i \"cpu\" | grep -i \"virtual\"" ascii
|
||||
$s5 = "/etc/hostname-merlin" ascii
|
||||
$s6 = "@%02X%X%c%08X.dat" ascii
|
||||
$s7 = "%s/.bash_profile1" ascii
|
||||
$s8 = "%s/.kde4/share/config" ascii
|
||||
$s9 = "ls /dev/disk/by-id/ 2>/dev/null" ascii
|
||||
$s10 = "/index.php HTTP/1.1" ascii
|
||||
|
||||
condition:
|
||||
uint16(0) == 0x457F and 8 of them
|
||||
}
|
||||
|
||||
rule finspy_linux_installer2 {
|
||||
meta:
|
||||
description = "Rule for FinSpy Linux installer"
|
||||
author = "Etienne Maynier, Amnesty Tech"
|
||||
|
||||
strings:
|
||||
$encrypted_conf = { 5? a5 aa ca a6 54 5a ?? a? 5a a5 0a } /* header of configuration files */
|
||||
$encrypted_bin_32 = { 7f 0d 45 4c 46 01 02 c2 14 68 03 05 0e } /* header of encrypted bin */
|
||||
$encrypted_bin_64 = { 7f 07 45 4c 46 02 01 1e 15 01 8e 03 0e } /* header of encrypted bin */
|
||||
|
||||
condition:
|
||||
(uint16(0) == 0x457F or uint16(0) == 0x2123) and (#encrypted_conf > 5 or #encrypted_bin_32 > 5 or #encrypted_bin_64 > 5)
|
||||
}
|
||||
|
||||
rule finspy_macos_installer {
|
||||
meta:
|
||||
description = "Rule for FinSpy OSX installer"
|
||||
author = "Etienne Maynier, Amnesty Tech"
|
||||
|
||||
strings:
|
||||
$s1 = "80.bundle.zip" ascii
|
||||
$s2 = "AAC.dat" ascii
|
||||
$s3 = "arch.zip" ascii
|
||||
$s4 = "/Library/LaunchAgents" ascii
|
||||
$s5 = "7FC.dat" ascii
|
||||
$s6 = "logind.plist" ascii
|
||||
$s7 = "org.logind.ctp.archive" ascii
|
||||
$s8 = "helper" ascii
|
||||
$s9 = "Contents/Resources/7f.bundle/Contents/Resources" ascii
|
||||
|
||||
condition:
|
||||
uint16(0) == 0xFACF and 8 of them
|
||||
}
|
||||
|
||||
rule finspy_macos_datapkg {
|
||||
meta:
|
||||
description = "Rule for FinSpy OSX core module"
|
||||
author = "Etienne Maynier, Amnesty Tech"
|
||||
|
||||
strings:
|
||||
$s1 = "vlacwjwcefforoxisdryuvbqlxvxt" ascii
|
||||
$s2 = "vquyqefxqpwytfuherfvzwaqqyanaddmvquyqefxqpwytfu" ascii
|
||||
$s3 = "vsczabsutfuhajffslhlkulomhivwligvscza:" ascii
|
||||
$s4 = "ijfrkptshbsurggfqxshpiolwupesxewijfrkptxnj" ascii
|
||||
$s5 = "wwsodegezqrtafprejkrytzablizbddgwwsodegezqrtafprejxnj" ascii
|
||||
$s6 = "clfggqtyflyspjewoxpodxesnpavcpofclfggqtyflyspjewoxpodxesnpavcpofclfggqtyflyspjewoxpodx" ascii
|
||||
$s7 = "mhqxzxdbxsfblsxmidzcribjewzkezujmhqxzxdbxsfblsxmidzcribjewzkezujmh" ascii
|
||||
$s8 = "sqpviurrqssxwzrzdwldcanprnsuadyhsqpvixnj" ascii
|
||||
$s9 = "zfocytolmylaejykmwphsbchfkfzyadbzfocytolmylaejykmwphsbchfkfzyadbz" ascii
|
||||
$s10 = "fehbsdjwmqrdndkskegllpixxabegjrdfehbsdjwmqrdndkske" ascii
|
||||
$s11 = "exmycityouezjfdczebdfhqdgt:" ascii
|
||||
$s12 = "denueozlbzhqzzdjhxjnjhoadjdsmashdenueozlbzhqzzd" ascii
|
||||
|
||||
|
||||
condition:
|
||||
uint16(0) == 0xFACF and 8 of them
|
||||
}
|
||||
|
||||
rule finspy_android_configinapk : android apkhideconfig finspy {
|
||||
meta:
|
||||
description = "Detect FinFisher FinSpy configuration in APK file. Probably the original FinSpy version."
|
||||
date = "2020/08/05"
|
||||
reference = "https://github.com/devio/FinSpy-Tools"
|
||||
author = "Esther Onfroy a.k.a U+039b - *@0x39b.fr (https://twitter.com/u039b)"
|
||||
warning = "May have some False Positive"
|
||||
|
||||
strings:
|
||||
$re = /\x50\x4B\x01\x02[\x00-\xff]{32}[A-Za-z0-9+\/]{6}/
|
||||
|
||||
condition:
|
||||
uint32(0) == 0x04034b50 and $re and (#re > 50)
|
||||
}
|
||||
|
||||
rule finspy_android_dexden : android dexhideconfig finspy
|
||||
{
|
||||
meta:
|
||||
description = "Detect FinFisher FinSpy configuration in DEX file. Probably a newer FinSpy variant."
|
||||
date = "2020/08/05"
|
||||
author = "Esther Onfroy a.k.a U+039b - *@0x39b.fr (https://twitter.com/u039b)"
|
||||
|
||||
strings:
|
||||
$config_1 = { 90 5b fe 00 }
|
||||
$config_2 = { 70 37 80 00 }
|
||||
$config_3 = { 40 38 80 00 }
|
||||
$config_4 = { a0 33 84 }
|
||||
$config_5 = { 90 79 84 00 }
|
||||
|
||||
condition:
|
||||
uint16(0) == 0x6564 and
|
||||
#config_1 >= 2 and
|
||||
#config_2 >= 2 and
|
||||
#config_3 >= 2 and
|
||||
#config_4 >= 2 and
|
||||
#config_5 >= 2
|
||||
}
|
||||
|
||||
rule FinSpy_TippyTime: finspyTT {
|
||||
meta:
|
||||
description = "Detect FinFisher FinSpy 'TippyTime' variant."
|
||||
date = "2020/08/05"
|
||||
author = "Esther Onfroy a.k.a U+039b - *@0x39b.fr (https://twitter.com/u039b)"
|
||||
strings:
|
||||
$config_1 = { 90 5b fe 00 }
|
||||
$config_2 = { 70 37 80 00 }
|
||||
$config_3 = { 40 38 80 00 }
|
||||
$config_4 = { a0 33 84 }
|
||||
$config_5 = { 90 79 84 00 }
|
||||
$timestamp = { 95 E9 D1 5B }
|
||||
|
||||
condition:
|
||||
uint16(0) == 0x6564 and
|
||||
$timestamp and
|
||||
$config_1 and
|
||||
$config_2 and
|
||||
$config_3 and
|
||||
$config_4 and
|
||||
$config_5
|
||||
}
|
||||
|
||||
rule FinSpy_TippyPad: finspyTP
|
||||
{
|
||||
meta:
|
||||
description = "Detect FinFisher FinSpy 'TippyPad' variant."
|
||||
date = "2020/08/05"
|
||||
author = "Esther Onfroy a.k.a U+039b - *@0x39b.fr (https://twitter.com/u039b)"
|
||||
strings:
|
||||
$pad_1 = "0123456789abcdef"
|
||||
$pad_2 = "fedcba9876543210"
|
||||
|
||||
condition:
|
||||
uint16(0) == 0x6564 and
|
||||
#pad_1 > 50 and
|
||||
#pad_2 > 50
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
import argparse
|
||||
import struct
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
|
||||
"""
|
||||
Extract configuration from a Cobalt Strike decrypted beacon
|
||||
|
||||
Author : Etienne Maynier, Amnesty Tech
|
||||
Date : March 2020
|
||||
"""
|
||||
|
||||
CONFIG_STRUCT = {
|
||||
1: "dns_ssl",
|
||||
2: "port",
|
||||
3: ".sleeptime",
|
||||
4: ".http-get.server.output",
|
||||
5: ".jitter",
|
||||
6: ".maxdns",
|
||||
7: "publickey",
|
||||
8: ".http-get.uri",
|
||||
9: ".user-agent",
|
||||
10: ".http-post.uri",
|
||||
11: ".http-get.server.output",
|
||||
12: ".http-get.client",
|
||||
13: ".http-post.client",
|
||||
14: ".spawnto",
|
||||
15: "unknown",
|
||||
19: ".dns_idle",
|
||||
20: ".dns_sleep ",
|
||||
26: ".http-get.verb",
|
||||
27: ".http-post.verb",
|
||||
28: "shouldChunkPosts",
|
||||
29: ".post-ex.spawnto_x86",
|
||||
30: ".post-ex.spawnto_x64",
|
||||
31: "cryptoscheme",
|
||||
37: "watermark",
|
||||
38: ".stage.cleanup",
|
||||
39: "CFGCaution",
|
||||
50: "cookieBeacon"
|
||||
}
|
||||
CONFIG_SIZE = 1978
|
||||
|
||||
class JsonEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, bytearray):
|
||||
return obj.hex()
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
|
||||
|
||||
def search_config(data):
|
||||
r = re.search(b"ihihik.{2}ikihik", data)
|
||||
if r:
|
||||
return r.span()[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def decode_config(data):
|
||||
config = {}
|
||||
i = 0
|
||||
while i < len(data) - 8:
|
||||
dec = struct.unpack(">HHH", data[i:i+6])
|
||||
if dec[0] == 1:
|
||||
v = struct.unpack(">H", data[i+6:i+8])[0]
|
||||
config["dns"] = ((v & 1) == 1)
|
||||
config["ssl"] = ((v & 8) == 8)
|
||||
elif dec[0] in CONFIG_STRUCT.keys():
|
||||
if dec[1] == 1 and dec[2] == 2:
|
||||
# Short
|
||||
config[CONFIG_STRUCT[dec[0]]] = struct.unpack(">H", data[i+6:i+8])[0]
|
||||
elif dec[1] == 2 and dec[2] == 4:
|
||||
# Int
|
||||
config[CONFIG_STRUCT[dec[0]]] = struct.unpack(">I", data[i+6:i+10])[0]
|
||||
elif dec[1] == 3:
|
||||
# Byte or string
|
||||
v = data[i+6:i+6+dec[2]]
|
||||
try:
|
||||
config[CONFIG_STRUCT[dec[0]]] = v.decode('utf-8').strip('\x00')
|
||||
except UnicodeDecodeError:
|
||||
config[CONFIG_STRUCT[dec[0]]] = v
|
||||
else:
|
||||
print("Unknown config command {}".format(dec[0]))
|
||||
# Add size +
|
||||
i += dec[2] + 6
|
||||
return config
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Extract Cobalt Strike configuration')
|
||||
parser.add_argument('PAYLOAD', help='A Cobalt Strike beacon')
|
||||
parser.add_argument('--json', '-j', action="store_true", help='Print json')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.PAYLOAD, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
START = search_config(data)
|
||||
if not START:
|
||||
print("Start position of the config struct not found")
|
||||
sys.exit(-1)
|
||||
|
||||
# Configuration is xored with 105
|
||||
conf = bytearray([c ^ 105 for c in data[START:START+CONFIG_SIZE]])
|
||||
|
||||
config = decode_config(conf)
|
||||
if args.json:
|
||||
print(json.dumps(config, indent=4, sort_keys=True, cls=JsonEncoder))
|
||||
else:
|
||||
for d in config:
|
||||
if isinstance(config[d], bytearray):
|
||||
print("{} : {}".format(d, config[d].hex()))
|
||||
else:
|
||||
print("{} : {}".format(d, config[d]))
|
||||
@@ -1,51 +0,0 @@
|
||||
import argparse
|
||||
import struct
|
||||
import sys
|
||||
|
||||
"""
|
||||
Decrypt a Cobalt Strike encrypted beacon
|
||||
|
||||
Author: Etienne Maynier, Amnesty Tech
|
||||
Date: March 2020
|
||||
"""
|
||||
|
||||
def xor(a, b):
|
||||
return bytearray([a[0]^b[0], a[1]^b[1], a[2]^b[2], a[3]^b[3]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Decode an encoded Cobalt Strike beacon')
|
||||
parser.add_argument('PAYLOAD', help='an integer for the accumulator')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.PAYLOAD, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
# The base address of the sample change depending on the code
|
||||
ba = data.find(b"\xe8\xd4\xff\xff\xff")
|
||||
if ba == -1:
|
||||
ba = data.find(b"\xe8\xd0\xff\xff\xff")
|
||||
if ba == -1:
|
||||
print("Base Address not found")
|
||||
sys.exit(1)
|
||||
ba += 5
|
||||
|
||||
key = data[ba:ba+4]
|
||||
print("Key : {}".format(key))
|
||||
size = struct.unpack("I", xor(key, data[ba+4:ba+8]))[0]
|
||||
print("Size : {}".format(size))
|
||||
|
||||
res = bytearray()
|
||||
i = ba+8
|
||||
while i < (len(data) - ba - 8):
|
||||
d = data[i:i+4]
|
||||
res += xor(d, key)
|
||||
key = d
|
||||
i += 4
|
||||
|
||||
if not res.startswith(b"MZ"):
|
||||
print("Invalid decoding, no PE header")
|
||||
|
||||
with open("a.out", "wb+") as f:
|
||||
f.write(res)
|
||||
print("PE file extracted in a.out")
|
||||
@@ -1,56 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
import struct
|
||||
import hashlib
|
||||
import ctypes
|
||||
import binascii
|
||||
import argparse
|
||||
from Crypto.Cipher import AES
|
||||
"""
|
||||
Decode FinSpy modules for Linux and MacOS
|
||||
|
||||
Author : Maciek mak@malwarelab.pl
|
||||
Date: August 2020
|
||||
"""
|
||||
|
||||
|
||||
def unpack(data, s=0):
|
||||
"""
|
||||
Decode the binary with aplib
|
||||
"""
|
||||
cin = ctypes.c_buffer(data)
|
||||
cout = ctypes.c_buffer(s if s else len(data) * 20)
|
||||
aplib_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
"_aplib.so")
|
||||
aPLIB = ctypes.cdll.LoadLibrary(aplib_path)
|
||||
n = aPLIB.aP_depack(cin, cout)
|
||||
return cout.raw[:n]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Unpack FinSpy modules')
|
||||
parser.add_argument('MODULE', help='Finspy module')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.MODULE,'rb') as f:
|
||||
hmd5 = f.read(0x10)
|
||||
IV = f.read(0x10)
|
||||
data = f.read()
|
||||
|
||||
hash_iv_data = hashlib.md5(IV + data)
|
||||
if hmd5 == hash_iv_data.digest():
|
||||
data = IV + data
|
||||
IV = b'\xd9!V\xee\xbe\x0c\xf9\x18*\xfaR;%&\xb7\x08'
|
||||
|
||||
if hmd5 == hashlib.md5(data).digest():
|
||||
print('[+] DATA HASH match {}'.format(binascii.hexlify(hmd5)))
|
||||
|
||||
key = b'YO\xf4\xa6\xd6\x1d\xd7!\xdc\x01A\xbfg\x83"m'
|
||||
xdata = AES.new(key,mode=AES.MODE_CBC,IV=bytes(IV)).decrypt(data)
|
||||
size = struct.unpack('I',xdata[:4])[0]
|
||||
print('[+] Unpacked size: {:x}'.format(size))
|
||||
depack = unpack(xdata[4:], size)
|
||||
with open(args.MODULE + '.unpacked.bin','wb') as f:
|
||||
f.write(depack)
|
||||
print('[*] saved to {}.unpacked.bin'.format(sys.argv[1]))
|
||||
@@ -1,38 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
import struct
|
||||
|
||||
"""
|
||||
Extract configuration of Linux FinSpy from an installer
|
||||
author: Etienne Maynier, Amnesty Tech
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Extract configuration Linux Finspy sample')
|
||||
parser.add_argument('FILE', help='FinSpy sample for Linux')
|
||||
args = parser.parse_args()
|
||||
|
||||
regex_cfg = re.compile(b'.[\x50-\x5f]\xa5\xaa\xca\xa6\x54\x5a.[\xa0-\xaf]\x5a\xa5\x0a')
|
||||
|
||||
with open(args.FILE, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
if len(regex_cfg.findall(data)) < 5:
|
||||
print("This does not look like a FinSpy sample")
|
||||
sys.exit(-1)
|
||||
|
||||
if not os.path.isdir('extracted'):
|
||||
os.mkdir('extracted')
|
||||
|
||||
i = 1
|
||||
for cfg in regex_cfg.finditer(data):
|
||||
pos = cfg.span()[0]
|
||||
# Decrypt the first 4 bytes to get the length
|
||||
length = struct.unpack('I', bytearray([data[pos]^0xaa, data[pos+1]^0x5a, data[pos+2]^0xa5, data[pos+3]^0xaa]))[0]
|
||||
with open('extracted/{0:02d}.dat'.format(i), 'wb+') as f:
|
||||
f.write(data[pos:pos+length])
|
||||
print("Configuration file extracted {0:02d}.dat ({} bytes)".format(i, length))
|
||||
i += 1
|
||||
@@ -1,872 +0,0 @@
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
#import simplejson as json
|
||||
from json import JSONEncoder
|
||||
import json
|
||||
from io import BytesIO
|
||||
"""
|
||||
Decode configuration from FinSpy Linux, MacOS and Android samples
|
||||
Python3 only
|
||||
"""
|
||||
|
||||
__author__ = "Maciek mak@malwarelab.pl"
|
||||
|
||||
|
||||
# From https://github.com/devio/FinSpy-Tools/blob/master/Android/finspyCfgParse.py
|
||||
tlv_types = {
|
||||
4522400: "TlvTypeMobileTrackingStartRequest",
|
||||
4522656: "TlvTypeMobileTrackingStopRequest",
|
||||
4523376: "TlvTypeMobileTrackingDataV10",
|
||||
4535200: "TlvTypeMobileTrackingConfig",
|
||||
4535440: "TlvTypeMobileTrackingConfigRaw",
|
||||
4538432: "TlvTypeMobileTrackingTimeInterval",
|
||||
4538688: "TlvTypeMobileTrackingDistance",
|
||||
4538928: "TlvTypeMobileTrackingSendOnAnyChannel",
|
||||
6291872: "TlvTypeMobileLoggingMetaInfo",
|
||||
6292096: "TlvTypeMobileLoggingData",
|
||||
4456864: "TlvTypeMobileBlackberryMessengerMetaInfo",
|
||||
4457088: "TlvTypeMobileBlackberryMessengerData",
|
||||
4457328: "TlvTypeMobileBlackberryMsChatID",
|
||||
4457600: "TlvTypeMobileBlackberryMsConversationPartners",
|
||||
4587936: "TlvTypeMobilePhoneCallLogsMetaInfo",
|
||||
4588192: "TlvTypeMobilePhoneCallLogsData",
|
||||
4588400: "TlvTypeMobilePhoneCallLogsType",
|
||||
4588672: "TlvTypeMobilePhoneCallAdditionalInformation",
|
||||
4588912: "TlvTypeMobilePhoneCallLogsCallerNumber",
|
||||
4589168: "TlvTypeMobilePhoneCallLogsCalleeNumber",
|
||||
4589440: "TlvTypeMobilePhoneCallLogsCallerName",
|
||||
4589696: "TlvTypeMobilePhoneCallLogsCalleeName",
|
||||
4591680: "TlvTypeMobilePhoneCallLogLastEntryEndtime",
|
||||
4325792: "TlvTypeMobileSMSMetaInfo",
|
||||
4326016: "TlvTypeMobileSMSData",
|
||||
4326256: "TlvTypeSMSSenderNumber",
|
||||
4326512: "TlvTypeSMSRecipientNumber",
|
||||
4326768: "TlvTypeSMSDirection",
|
||||
4326528: "TlvTypeSMSInformation",
|
||||
4391328: "TlvTypeMobileAddressBookMetaInfo",
|
||||
4391552: "TlvTypeMobileAddressBookData",
|
||||
4407360: "TlvTypeMobileAddressBookChecksum",
|
||||
8978752: "TlvTypeMobileProxyMasterCommSig",
|
||||
8979104: "TlvTypeMobileProxyMasterComm",
|
||||
8979360: "TlvTypeMobileMasterProxyComm",
|
||||
8979616: "TlvTypeProxyMasterMobileHeartBeatAnswer",
|
||||
8979872: "TlvTypeMobileMasterProxyCommNotification",
|
||||
8782176: "TlvTypeProxyMobileTargetCommSig",
|
||||
8782496: "TlvTypeProxyMobileTargetComm",
|
||||
8782752: "TlvTypeProxyMasterMobileTargetComm",
|
||||
1507744: "TlvTypeAccessedFileMetaInfo",
|
||||
1507968: "TlvTypeAccessedFileAccessTime",
|
||||
1508224: "TlvTypeAccessedFileAccessEvent",
|
||||
1508496: "TlvTypeAccessedFileRecording",
|
||||
1508736: "TlvTypeAccessedApplicationName",
|
||||
1508912: "TlvTypeConfigRecordImagesFromExplorer",
|
||||
1519776: "TlvTypeGetAccessedConfigRequest",
|
||||
1520032: "TlvTypeAccessedConfigReply",
|
||||
1520288: "TlvTypeSetAccessedConfigRequest",
|
||||
1520448: "TlvTypeConfigAccessedEvents",
|
||||
2240672: "TlvTypeGetMouseClicksConfigRequest",
|
||||
2240928: "TlvTypeMouseClicksConfigReply",
|
||||
2241184: "TlvTypeSetMouseClicksConfigRequest",
|
||||
2228640: "TlvTypeMouseClicksMetaInfo",
|
||||
2228896: "TlvTypeMouseClicksFrame",
|
||||
2232448: "TlvTypeMouseClicksEncodingType",
|
||||
2232896: "TlvTypeConfigMouseClicksRectangle",
|
||||
2233152: "TlvTypeConfigMouseClicksSensitivity",
|
||||
2233408: "TlvTypeConfigMouseClicksType",
|
||||
2175136: "TlvTypeGetVoIPConfigRequest",
|
||||
2175392: "TlvTypeVoIPConfigReply",
|
||||
2175648: "TlvTypeSetVoIPConfigRequest",
|
||||
2163104: "TlvTypeVoIPMetaInfo",
|
||||
2166912: "TlvTypeVoIPEncodingType",
|
||||
2167168: "TlvTypeVoIPSessionType",
|
||||
2167424: "TlvTypeVoIPApplicationName",
|
||||
2167696: "TlvTypeVoIPAppScreenshot",
|
||||
2167952: "TlvTypeVoIPAudioRecording",
|
||||
2168112: "TlvTypeConfigVoIPScreenshotEnabled",
|
||||
2109600: "TlvTypeGetForensicsConfigRequest",
|
||||
2109856: "TlvTypeForensicsConfigReply",
|
||||
2110112: "TlvTypeSetForensicsConfigRequest",
|
||||
2097568: "TlvTypeUploadForensicsApplicationRequest",
|
||||
2097824: "TlvTypeUploadForensicsApplicationReply",
|
||||
2098080: "TlvTypeUploadForensicsApplicationChunk",
|
||||
2098336: "TlvTypeUploadForensicsApplicationDoneRequest",
|
||||
2098592: "TlvTypeUploadForensicsApplicationDoneReply",
|
||||
2101664: "TlvTypeRemoveForensicsApplicationRequest",
|
||||
2101920: "TlvTypeRemoveForensicsApplicationReply",
|
||||
2105760: "TlvTypeForensicsAppExecuteRequest",
|
||||
2106016: "TlvTypeForensicsAppExecuteReply",
|
||||
2106272: "TlvTypeForensicsAppExecuteResult",
|
||||
2106528: "TlvTypeForensicsAppExecuteResultChunk",
|
||||
2106784: "TlvTypeForensicsAppExecuteResultDone",
|
||||
2107040: "TlvTypeForensicsCancelAppExecuteRequest",
|
||||
2107296: "TlvTypeForensicsCancelAppExecuteReply",
|
||||
2113680: "TlvTypeConfigForensicsApplicationInfoGeneric",
|
||||
2113952: "TlvTypeConfigForensicsApplicationInfo",
|
||||
2117760: "TlvTypeConfigForensicsApplicationName",
|
||||
2117952: "TlvTypeConfigForensicsApplicationSize",
|
||||
2118208: "TlvTypeConfigForensicsApplicationID",
|
||||
2118528: "TlvTypeConfigForensicsApplicationCmdline",
|
||||
2118784: "TlvTypeConfigForensicsApplicationOutput",
|
||||
2118976: "TlvTypeConfigForensicsApplicationTimeout",
|
||||
2119232: "TlvTypeConfigForensicsApplicationVersion",
|
||||
2119552: "TlvTypeForensicsFriendlyName",
|
||||
2119808: "TlvTypeConfigForensicsApplicationOutputPrepend",
|
||||
2120064: "TlvTypeConfigForensicsApplicationOutputContentType",
|
||||
1638816: "TlvTypeDeletedFileMetaInfo",
|
||||
1639296: "TlvTypeDeletedFileDeletionTime",
|
||||
1639552: "TlvTypeDeletedFileRecycleBin",
|
||||
1639808: "TlvTypeDeletedMethod",
|
||||
1640064: "TlvTypeDeletedApplicationName",
|
||||
1640336: "TlvTypeDeletedFileRecording",
|
||||
1650848: "TlvTypeGetDeletedConfigRequest",
|
||||
1651104: "TlvTypeDeletedConfigReply",
|
||||
1651360: "TlvTypeSetDeletedConfigRequest",
|
||||
1573280: "TlvTypePrintFileMetaInfo",
|
||||
1573520: "TlvTypePrintFrame",
|
||||
1581184: "TlvTypePrintApplicationName",
|
||||
1581440: "TlvTypePrintFilename",
|
||||
1581696: "TlvTypePrintEncodingType",
|
||||
1585312: "TlvTypeGetPrintConfigRequest",
|
||||
1585568: "TlvTypePrintConfigReply",
|
||||
1585824: "TlvTypeSetPrintConfigRequest",
|
||||
1442208: "TlvTypeChangedFileMetaInfo",
|
||||
1442432: "TlvTypeChangedFileChangeTime",
|
||||
1442688: "TlvTypeChangedFileChangeEvent",
|
||||
1442960: "TlvTypeChangedFileRecording",
|
||||
1454240: "TlvTypeGetChangedConfigRequest",
|
||||
1454496: "TlvTypeChangedConfigReply",
|
||||
1454752: "TlvTypeSetChangedConfigRequest",
|
||||
1454912: "TlvTypeConfigChangedEvents",
|
||||
1311136: "TlvTypeSkypeAudioMetaInfo",
|
||||
1311376: "TlvTypeSkypeAudioRecording",
|
||||
1311648: "TlvTypeSkypeTextRecording",
|
||||
1311904: "TlvTypeSkypeFileMetaInfo",
|
||||
1312144: "TlvTypeSkypeFileRecording",
|
||||
1312416: "TlvTypeSkypeContactsRecording",
|
||||
1312640: "TlvTypeSkypeContactsUserData",
|
||||
1323168: "TlvTypeGetSkypeConfigRequest",
|
||||
1323424: "TlvTypeSkypeConfigReply",
|
||||
1323680: "TlvTypeSetSkypeConfigRequest",
|
||||
1324336: "TlvTypeConfigSkypeAudioEnable",
|
||||
1324592: "TlvTypeConfigSkypeTextEnable",
|
||||
1324848: "TlvTypeConfigSkypeFileEnable",
|
||||
1325104: "TlvTypeConfigSkypeContactsListEnable",
|
||||
1327232: "TlvTypeSkypeAudioEncodingType",
|
||||
1327488: "TlvTypeSkypeLoggedInUserAccountName",
|
||||
1327744: "TlvTypeSkypeConversationPartnerAccountName",
|
||||
1328000: "TlvTypeSkypeConversationPartnerDisplayName",
|
||||
1328256: "TlvTypeSkypeChatMembers",
|
||||
1328512: "TlvTypeSkypeTextMessage",
|
||||
1328768: "TlvTypeSkypeChatID",
|
||||
1329024: "TlvTypeSkypeSenderAccountName",
|
||||
1329280: "TlvTypeSkypeSenderDisplayName",
|
||||
1329536: "TlvTypeSkypeIncoming",
|
||||
1329792: "TlvTypeSkypeSessionType",
|
||||
1192096: "TlvTypeGetKeyloggerConfigRequest",
|
||||
1192352: "TlvTypeKeyloggerConfigReply",
|
||||
1192608: "TlvTypeSetKeyloggerConfigRequest",
|
||||
1180064: "TlvTypeStartKeyLoggingRequest",
|
||||
1180320: "TlvTypeStartKeyLoggingReply",
|
||||
1180576: "TlvTypeKeyLoggingFrame",
|
||||
1180832: "TlvTypeStopKeyLoggingRequest",
|
||||
1181088: "TlvTypeKeyLoggingStoppedReply",
|
||||
1196416: "TlvTypeKLFrameData",
|
||||
1126560: "TlvTypeGetVideoConfigRequest",
|
||||
1126816: "TlvTypeVideoConfigReply",
|
||||
1127072: "TlvTypeSetVideoConfigRequest",
|
||||
1114528: "TlvTypeStartScreenRequest",
|
||||
1114784: "TlvTypeStartScreenReply",
|
||||
1115040: "TlvTypeScreenFrame",
|
||||
1115296: "TlvTypeStopScreenRequest",
|
||||
1115552: "TlvTypeScreenStoppedReply",
|
||||
1115808: "TlvTypeStartScreenRecording",
|
||||
1122720: "TlvTypeStartWebCamRequest",
|
||||
1122976: "TlvTypeStartWebCamReply",
|
||||
1123232: "TlvTypeWebCamFrame",
|
||||
1123488: "TlvTypeStopWebCamRequest",
|
||||
1123744: "TlvTypeWebCamStoppedReply",
|
||||
1124000: "TlvTypeStartWebCamRecording",
|
||||
1130560: "TlvTypeVDFrameID",
|
||||
1130896: "TlvTypeVDFrameData",
|
||||
1131136: "TlvTypeOriginalVideoResolution",
|
||||
1131392: "TlvTypeVideoResolution",
|
||||
1066112: "TlvTypeVideoSessionType",
|
||||
1066368: "TlvTypeVideoEncodingType",
|
||||
1132160: "TlvTypeAutomaticRecordingUID",
|
||||
1061024: "TlvTypeGetAudioConfigRequest",
|
||||
1061280: "TlvTypeAudioConfigReply",
|
||||
1061536: "TlvTypeSetAudioConfigRequest",
|
||||
1048992: "TlvTypeStartMicrophoneRequest",
|
||||
1049248: "TlvTypeStartMicrophoneReply",
|
||||
1049504: "TlvTypeMicrophoneFrame",
|
||||
1049760: "TlvTypeStopMicrophoneRequest",
|
||||
1050016: "TlvTypeMicrophoneStoppedReply",
|
||||
1050272: "TlvTypeStartMicrophoneRecording",
|
||||
1052736: "TlvTypeMICFrameID",
|
||||
1053072: "TlvTypeMICFrameData",
|
||||
1053312: "TlvTypeAudioSessionType",
|
||||
1053568: "TlvTypeAudioEncodingType",
|
||||
328096: "TlvTypeGetSchedulerConfigRequest",
|
||||
328352: "TlvTypeSchedulerConfigReply",
|
||||
328608: "TlvTypeSetSchedulerConfigRequest",
|
||||
331920: "TlvTypeSchedulerTask",
|
||||
332192: "TlvTypeSchedulerTaskRecordByTime",
|
||||
332448: "TlvTypeSchedulerTaskRecordScreenWhenAppRuns",
|
||||
332704: "TlvTypeSchedulerTaskRecordMicWhenAppUsesIt",
|
||||
332960: "TlvTypeSchedulerTaskRecordWebCamWhenAppUsesIt",
|
||||
360592: "TlvTypeSCHTaskConfiguration",
|
||||
360752: "TlvTypeSCHTaskEnabled",
|
||||
361344: "TlvTypeSCHTaskStartDateTime",
|
||||
361600: "TlvTypeSCHTaskStopDateTime",
|
||||
362112: "TlvTypeSCHApplicationName",
|
||||
362288: "TlvTypeSCHApplicationWindowOnly",
|
||||
299168: "TlvTypeGetCmdLineConfigRequest",
|
||||
299424: "TlvTypeCmdLineConfigReply",
|
||||
299680: "TlvTypeSetCmdLineConfigRequest",
|
||||
262560: "TlvTypeStartCmdLineSessionRequest",
|
||||
262816: "TlvTypeStartCmdLineSessionReply",
|
||||
263072: "TlvTypeStopCmdLineSessionRequest",
|
||||
263328: "TlvTypeCmdLineSessionStoppedReply",
|
||||
263584: "TlvTypeCmdLineExecute",
|
||||
263840: "TlvTypeCmdLineExecutionResult",
|
||||
266352: "TlvTypeCmdLineExecuteCommand",
|
||||
266560: "TlvTypeCmdLineExecuteAnswerID",
|
||||
266864: "TlvTypeCmdLineExecuteAnswerData",
|
||||
168096: "TlvTypeGetFileSystemConfigRequest",
|
||||
168352: "TlvTypeFileSystemConfigReply",
|
||||
168608: "TlvTypeSetFileSystemConfigRequest",
|
||||
131488: "TlvTypeGetAllDrivesRequest",
|
||||
131744: "TlvTypeGetAllDrivesReply",
|
||||
135328: "TlvTypeGetFolderContentsRequest",
|
||||
135584: "TlvTypeGetFolderContentsReply",
|
||||
135840: "TlvTypeGetFolderContentsNext",
|
||||
136096: "TlvTypeGetFolderContentsEnd",
|
||||
139424: "TlvTypeDownloadFileRequest",
|
||||
139680: "TlvTypeCancelDownloadFileRequest",
|
||||
139936: "TlvTypeDownloadFileReply",
|
||||
140192: "TlvTypeDownloadFileNext",
|
||||
140448: "TlvTypeDownloadFileEnd",
|
||||
140704: "TlvTypeCancelDownloadFileReply",
|
||||
143520: "TlvTypeUploadFileRequest",
|
||||
143776: "TlvTypeCancelUploadFileRequest",
|
||||
144032: "TlvTypeUploadFileReply",
|
||||
144288: "TlvTypeUploadFileNext",
|
||||
144544: "TlvTypeUploadFileEnd",
|
||||
144800: "TlvTypeUploadFileCompleted",
|
||||
145056: "TlvTypeCancelUploadFileReply",
|
||||
147616: "TlvTypeDeleteFileRequest",
|
||||
147872: "TlvTypeDeleteFileReply",
|
||||
151968: "TlvTypeSearchFileRequest",
|
||||
152224: "TlvTypeSearchFileReply",
|
||||
152480: "TlvTypeSearchFileNext",
|
||||
152736: "TlvTypeSearchFileEnd",
|
||||
152992: "TlvTypeCancelSearchFileRequest",
|
||||
153248: "TlvTypeCancelSearchFileReply",
|
||||
159888: "TlvTypeFSFileDataChunk",
|
||||
160128: "TlvTypeFSDiskDrive",
|
||||
160384: "TlvTypeFSFullPath",
|
||||
160640: "TlvTypeFSFilename",
|
||||
160896: "TlvTypeFSFileExtension",
|
||||
161088: "TlvTypeFSDiskDriveType",
|
||||
161408: "TlvTypeFSFileSize",
|
||||
161584: "TlvTypeFSIsFolder",
|
||||
161840: "TlvTypeFSReadOnly",
|
||||
162096: "TlvTypeFSHidden",
|
||||
162352: "TlvTypeFSSystem",
|
||||
162688: "TlvTypeFSFileCreationTime",
|
||||
162944: "TlvTypeFSFileLastAccessTime",
|
||||
163200: "TlvTypeFSFileLastWriteTime",
|
||||
163472: "TlvTypeFSFullPathM",
|
||||
8978848: "TlvTypeMasterMobileTargetConn",
|
||||
7471520: "TlvTypeMasterTargetConn",
|
||||
7405984: "TlvTypeMasterAgentLogin",
|
||||
7406240: "TlvTypeMasterAgentLoginAnswer",
|
||||
7406752: "TlvTypeMasterAgentTargetList",
|
||||
7407008: "TlvTypeMasterAgentTargetOnlineList",
|
||||
7407264: "TlvTypeMasterAgentTargetInfoReply",
|
||||
7407520: "TlvTypeMasterAgentUserList",
|
||||
7407776: "TlvTypeMasterAgentUserListReply",
|
||||
7408032: "TlvTypeMasterAgentTargetArchivedList",
|
||||
7408288: "TlvTypeMasterAgentTargetListEx",
|
||||
7408544: "TlvTypeMasterAgentTargetOnlineListEx",
|
||||
7408800: "TlvTypeMasterAgentMobileTargetArchivedList",
|
||||
7409056: "TlvTypeMasterAgentMobileTargetList",
|
||||
7409312: "TlvTypeMasterAgentMobileTargetOnlineList",
|
||||
7409824: "TlvTypeMasterAgentQueryFirst",
|
||||
7410080: "TlvTypeMasterAgentQueryNext",
|
||||
7410336: "TlvTypeMasterAgentQueryLast",
|
||||
7410592: "TlvTypeMasterAgentQueryAnswer",
|
||||
7410848: "TlvTypeMasterAgentRemoveRecord",
|
||||
7411104: "TlvTypeMasterAgentTargetInfoExReply",
|
||||
7411344: "TlvTypeTargetInfoExProperty",
|
||||
7411616: "TlvTypeTargetInfoExPropertyValue",
|
||||
7411840: "TlvTypeTargetInfoExPropertyValueName",
|
||||
7411968: "TlvTypeTargetInfoExPropertyValueData",
|
||||
7412384: "TlvTypeMasterAgentAlarm",
|
||||
7413920: "TlvTypeMasterAgentRetrieveData",
|
||||
7414176: "TlvTypeMasterAgentRetrieveDataAnswer",
|
||||
7414432: "TlvTypeMasterAgentRemoveUser",
|
||||
7414688: "TlvTypeMasterAgentRemoveTarget",
|
||||
7414944: "TlvTypeMasterAgentRetrieveDataComments",
|
||||
7415200: "TlvTypeMasterAgentUpdateDataComments",
|
||||
7415712: "TlvTypeMasterAgentRetrieveActivityLogging",
|
||||
7415968: "TlvTypeMasterAgentRetrieveMasterLogging",
|
||||
7416224: "TlvTypeMasterAgentRetrieveAgentActivityLogging",
|
||||
7417248: "TlvTypeMasterAgentSendUserGUIConfig",
|
||||
7417504: "TlvTypeMasterAgentGetUserGUIConfigRequest",
|
||||
7417760: "TlvTypeMasterAgentGetUserGUIConfigReply",
|
||||
7418016: "TlvTypeMasterAgentProxyList",
|
||||
7418272: "TlvTypeMasterAgentProxyInfoReply",
|
||||
7419040: "TlvTypeMasterAgentNameValuePacket",
|
||||
7419248: "TlvTypeMasterAgentValueName",
|
||||
7419392: "TlvTypeMasterAgentValueData",
|
||||
7419808: "TlvTypeMasterAgentRetrieveTargetHistory",
|
||||
7421088: "TlvTypeMasterAgentInstallMasterLicense",
|
||||
7421344: "TlvTypeMasterAgentInstallSoftwareUpdate",
|
||||
7421600: "TlvTypeMasterAgentInstallSoftwareUpdateChunk",
|
||||
7421856: "TlvTypeMasterAgentInstallSoftwareUpdateDone",
|
||||
7422112: "TlvTypeMasterAgentSoftwareUpdateInfo",
|
||||
7422368: "TlvTypeMasterAgentSoftwareUpdateInfoReply",
|
||||
7422624: "TlvTypeMasterAgentSoftwareUpdate",
|
||||
7422880: "TlvTypeMasterAgentSoftwareUpdateReply",
|
||||
7423136: "TlvTypeMasterAgentSoftwareUpdateNext",
|
||||
7423392: "TlvTypeMasterAgentAddTimeSchedule",
|
||||
7423648: "TlvTypeMasterAgentAddScreenSchedule",
|
||||
7423904: "TlvTypeMasterAgentAddLockedSchedule",
|
||||
7424160: "TlvTypeMasterAgentRemoveSchedule",
|
||||
7424416: "TlvTypeMasterAgentGetSchedulerList",
|
||||
7424672: "TlvTypeMasterAgentSchedulerTimeAction",
|
||||
7424928: "TlvTypeMasterAgentSchedulerScreenAction",
|
||||
7425184: "TlvTypeMasterAgentSchedulerLockedAction",
|
||||
7425440: "TlvTypeMasterAgentProjectSoftwareUpdateInfo",
|
||||
7425696: "TlvTypeMasterAgentProjectSoftwareUpdateInfoReply",
|
||||
7425952: "TlvTypeMasterAgentProjectSoftwareUpdate",
|
||||
7426112: "TlvTypeMasterAgentSchedulerID",
|
||||
7426368: "TlvTypeMasterAgentSchedulerStartTime",
|
||||
7426624: "TlvTypeMasterAgentSchedulerStopTime",
|
||||
7427488: "TlvTypeMasterAgentAddRecordedDataAvailableSchedule",
|
||||
7427744: "TlvTypeMasterAgentSchedulerRecordedDataAvailableAction",
|
||||
7428256: "TlvTypeMasterAgentRetrieveRemoteMasterData",
|
||||
7428512: "TlvTypeMasterAgentRetrieveRemoteMasterDataReply",
|
||||
7428768: "TlvTypeMasterAgentDeleteRemoteMasterData",
|
||||
7429024: "TlvTypeMasterAgentRetrieveOfflineMasterData",
|
||||
7429280: "TlvTypeMasterAgentRetrieveOfflineMasterDataReply",
|
||||
7429536: "TlvTypeMasterAgentDeleteOfflineMasterData",
|
||||
7430304: "TlvTypeMasterAgentQueryFirstEx",
|
||||
7430560: "TlvTypeMasterAgentQueryNextEx",
|
||||
7430816: "TlvTypeMasterAgentQueryLastEx",
|
||||
7431072: "TlvTypeMasterAgentQueryAnswerEx",
|
||||
7431328: "TlvTypeMasterAgentSendUserPreferences",
|
||||
7431584: "TlvTypeMasterAgentGetUserPreferencesRequest",
|
||||
7431840: "TlvTypeMasterAgentGetUserPreferencesReply",
|
||||
7432096: "TlvTypeMasterAgentListMCFilesRequest",
|
||||
8415392: "TlvTypeMasterAgentListMCFilesReply",
|
||||
7432608: "TlvTypeMasterAgentDeleteMCFiles",
|
||||
7432864: "TlvTypeMasterAgentSendMCFiles",
|
||||
7433120: "TlvTypeMasterAgentMCStatisticsRequest",
|
||||
7433376: "TlvTypeMasterAgentMCStatisticsReply",
|
||||
7433616: "TlvTypeMasterAgentMCStatisticsValues",
|
||||
7434400: "TlvTypeMasterAgentTrojanKeyRequest",
|
||||
7434656: "TlvTypeMasterAgentTrojanKeyReply",
|
||||
7434912: "TlvTypeMasterAgentEvProtectionX509Request",
|
||||
7435168: "TlvTypeMasterAgentEvProtectionX509Reply",
|
||||
7435424: "TlvTypeMasterAgentEvProtectionImportCert",
|
||||
7435680: "TlvTypeMasterAgentEvProtectionImportCertCompleted",
|
||||
7435936: "TlvTypeMasterAgentConfigurationRequest",
|
||||
7436192: "TlvTypeMasterAgentConfigurationReply",
|
||||
7436448: "TlvTypeMasterAgentConfigurationUpdateRequest",
|
||||
7436704: "TlvTypeMasterAgentConfigurationUpdateRequestCompleted",
|
||||
7436944: "TlvTypeMasterAgentConfiguration",
|
||||
7437216: "TlvTypeMasterAgentConfigurationValue",
|
||||
7437424: "TlvTypeMasterAgentConfigurationValueName",
|
||||
7437568: "TlvTypeMasterAgentConfigurationValueData",
|
||||
7437984: "TlvTypeMasterAgentConfigurationTransferDone",
|
||||
7438496: "TlvTypeMasterAgentRetrieveTargetFile",
|
||||
7438752: "TlvTypeMasterAgentRetrieveTargetFileAnswer",
|
||||
7438912: "TlvTypeMasterAgentAlarmEntryID",
|
||||
7439168: "TlvTypeMasterAgentAlarmEntryVersion",
|
||||
7439424: "TlvTypeMasterAgentAlarmTriggerFlags",
|
||||
7439776: "TlvTypeMasterAgentGetAlarmList",
|
||||
7440032: "TlvTypeMasterAgentAddAlarmEntry",
|
||||
7440288: "TlvTypeMasterAgentRemoveAlarmEntry",
|
||||
7440544: "TlvTypeMasterAgentAlarmEntry",
|
||||
7440800: "TlvTypeMasterAgentSystemStatus",
|
||||
7441056: "TlvTypeMasterAgentSystemStatusRequest",
|
||||
7441312: "TlvTypeMasterAgentSystemStatusReply",
|
||||
7441552: "TlvTypeMasterAgentLicenseValues",
|
||||
7441824: "TlvTypeMasterAgentLicenseValuesRequest",
|
||||
7442080: "TlvTypeMasterAgentLicenseValuesReply",
|
||||
7442592: "TlvTypeMasterAgentGetNetworkConfigurationRequest",
|
||||
7442848: "TlvTypeMasterAgentSetNetworkConfigurationRequest",
|
||||
7443104: "TlvTypeMasterAgentSetNetworkConfigurationReply",
|
||||
7443360: "TlvTypeMasterAgentRetrieveAllowedModulesList",
|
||||
7443616: "TlvTypeMasterAgentRetrieveAllowedModulesListAnswer",
|
||||
7446688: "TlvTypeMasterAgentRemoveAllTargetData",
|
||||
7446944: "TlvTypeMasterAgentForceDownloadRecordedData",
|
||||
7447200: "TlvTypeMasterAgentTargetCreateNotification",
|
||||
7447456: "TlvTypeMasterAgentMobileTargetInfoReply",
|
||||
7447696: "TlvTypeMasterAgentMobileTargetInfoValues",
|
||||
7450784: "TlvTypeMasterAgentAlert",
|
||||
7454880: "TlvTypeMasterAgentAddUser",
|
||||
7455392: "TlvTypeMasterAgentAddUserReply",
|
||||
7455648: "TlvTypeMasterAgentModifyUser",
|
||||
7455904: "TlvTypeMasterAgentSetUserPermission",
|
||||
7456160: "TlvTypeMasterAgentSetTargetPermission",
|
||||
7456400: "TlvTypeMasterAgentUserPermission",
|
||||
7456656: "TlvTypeMasterAgentTargetPermission",
|
||||
7456928: "TlvTypeMasterAgentUserPermissionValuePacket",
|
||||
7457184: "TlvTypeMasterAgentTargetPermissionValuePacket",
|
||||
7457344: "TlvTypeMasterAgentUserPermissionValueName",
|
||||
7457600: "TlvTypeMasterAgentTargetPermissionValueName",
|
||||
7457856: "TlvTypeMasterAgentUserPermissionValueData",
|
||||
7458112: "TlvTypeMasterAgentTargetPermissionValueData",
|
||||
7458464: "TlvTypeMasterAgentModifyPassword",
|
||||
7458656: "TlvTypeMasterAgentMobileTargetPermissionValueName",
|
||||
7458976: "TlvTypeMasterAgentUploadFile",
|
||||
7459232: "TlvTypeMasterAgentUploadFileChunk",
|
||||
7459488: "TlvTypeMasterAgentUploadFileDone",
|
||||
7459744: "TlvTypeMasterAgentUploadFilesTransferDone",
|
||||
7460000: "TlvTypeMasterAgentGetTargetModuleConfigRequest",
|
||||
7460256: "TlvTypeMasterAgentRemoveFile",
|
||||
7460512: "TlvTypeMasterAgentMobileProxyList",
|
||||
7460768: "TlvTypeMasterAgentSMSProxyList",
|
||||
7461024: "TlvTypeMasterAgentSMSProxyInfoReply",
|
||||
7461280: "TlvTypeMasterAgentCallPhoneNumberList",
|
||||
7461536: "TlvTypeMasterAgentCallPhoneNumberInfoReply",
|
||||
7461792: "TlvTypeMasterAgentGetMobileTargetModuleConfigRequest",
|
||||
7462048: "TlvTypeMasterAgentSendSMS",
|
||||
7469984: "TlvTypeMasterAgentEncryptionRequired",
|
||||
7470752: "TlvTypeAgentMasterComm",
|
||||
7470240: "TlvTypeMasterAgentFileCompleted",
|
||||
7470496: "TlvTypeMasterAgentRequestCompleted",
|
||||
7471008: "TlvTypeMasterAgentRequestStatus",
|
||||
7733664: "TlvTypeRelayProxyComm",
|
||||
8454800: "TlvTypeRelayData",
|
||||
7734176: "TlvTypeRelayDummyHeartbeat",
|
||||
7668128: "TlvTypeMasterTargetComm",
|
||||
7668384: "TlvTypeTargetCloseAllLiveStreaming",
|
||||
7471424: "TlvTypeProxyMasterCommSig",
|
||||
7471776: "TlvTypeProxyMasterComm",
|
||||
7472032: "TlvTypeMasterProxyComm",
|
||||
7472288: "TlvTypeProxyMasterHeartBeatAnswer",
|
||||
7472544: "TlvTypeProxyMasterDisconnect",
|
||||
7472704: "TlvTypeProxyMasterNotification",
|
||||
7473056: "TlvTypeProxyMasterRequest",
|
||||
7473312: "TlvTypeMasterProxyCommNotification",
|
||||
7473568: "TlvTypeMasterCheckTargetDisconnect",
|
||||
7536960: "TlvTypeProxyTargetCommSig",
|
||||
7537312: "TlvTypeProxyTargetComm",
|
||||
7537568: "TlvTypeProxyMasterTargetComm",
|
||||
7537728: "TlvTypeProxyTargetRequestCrypto",
|
||||
7538064: "TlvTypeProxyTargetAnswerCrypto",
|
||||
8454544: "TlvTypeProxyData",
|
||||
8458400: "TlvTypeProxyTargetDisconnect",
|
||||
8458656: "TlvTypeProxyMobileTargetDisconnect",
|
||||
8458912: "TlvTypeProxyDummyHeartbeat",
|
||||
8459168: "TlvTypeProxyMobileDummyHeartbeat",
|
||||
8585616: "TlvTypeAgentData",
|
||||
8585808: "TlvTypeAgentQueryID",
|
||||
8586048: "TlvTypeAgentQueryModSubmodID",
|
||||
8586304: "TlvTypeAgentQueryFromDate",
|
||||
8586560: "TlvTypeAgentQueryToDate",
|
||||
8586816: "TlvTypeAgentQuerySortOrder",
|
||||
8587136: "TlvTypeAgentQueryValueFilter",
|
||||
8587328: "TlvTypeAgentUID",
|
||||
8520080: "TlvTypeMasterData",
|
||||
8520768: "TlvTypeMasterMode",
|
||||
8521024: "TlvTypeMasterToken",
|
||||
8521344: "TlvTypeMasterQueryResult",
|
||||
8522368: "TlvTypeMasterAlarmString",
|
||||
8651152: "TlvTypeMobileTargetData",
|
||||
8651376: "TlvTypeMobileTargetHeartBeatV10",
|
||||
8651632: "TlvTypeMobileTargetExtendedHeartBeatV10",
|
||||
8651888: "TlvTypeMobileHeartBeatReplyV10",
|
||||
8653472: "TlvTypeMobileInstalledModulesReply",
|
||||
8656032: "TlvTypeMobileTargetUploadModuleRequest",
|
||||
8656288: "TlvTypeMobileTargetUploadModuleReply",
|
||||
8656544: "TlvTypeMobileTargetUploadModuleChunk",
|
||||
8656800: "TlvTypeMobileTargetUploadModuleDoneRequest",
|
||||
8657056: "TlvTypeMobileTargetUploadModuleDoneReply",
|
||||
8657312: "TlvTypeMobileTargetRemoveModuleRequest",
|
||||
8657568: "TlvTypeMobileTargetRemoveModuleReply",
|
||||
8655008: "TlvTypeMobileTargetOfflineUploadModuleRequest",
|
||||
8657824: "TlvTypeMobileTargetOfflineUploadModuleReply",
|
||||
8658080: "TlvTypeMobileTargetOfflineUploadModuleChunk",
|
||||
8658336: "TlvTypeMobileTargetOfflineUploadModuleDoneRequest",
|
||||
8658592: "TlvTypeMobileTargetOfflineUploadModuleDoneReply",
|
||||
8658848: "TlvTypeMobileTargetOfflineError",
|
||||
8659104: "TlvTypeMobileTargetError",
|
||||
8659360: "TlvTypeMobileTargetGetRecordedFilesRequest",
|
||||
8659616: "TlvTypeMobileTargetRecordedFilesReply",
|
||||
8659872: "TlvTypeMobileTargetRecordedFileDownloadRequest",
|
||||
8660128: "TlvTypeMobileTargetRecordedFileDownloadReply",
|
||||
8660384: "TlvTypeMobileTargetRecordedFileDownloadChunk",
|
||||
8660640: "TlvTypeMobileTargetRecordedFileDownloadCompleted",
|
||||
8660896: "TlvTypeMobileTargetRecordedFileDeleteRequest",
|
||||
8661152: "TlvTypeMobileTargetRecordedFileDeleteReply",
|
||||
8663968: "TlvTypeMobileTargetOfflineConfig",
|
||||
8664224: "TlvTypeMobileTargetEmergencyConfigAsTLV",
|
||||
8664432: "TlvTypeMobileTargetEmergencyConfig",
|
||||
8671392: "TlvTypeMobileTargetLoadModuleRequest",
|
||||
8671648: "TlvTypeMobileTargetLoadModuleReply",
|
||||
8671904: "TlvTypeMobileTargetUnLoadModuleRequest",
|
||||
8672160: "TlvTypeMobileTargetUnLoadModuleReply",
|
||||
8675472: "TlvTypeMobileTargetHeartbeatEvents",
|
||||
8675648: "TlvTypeMobileTargetHeartbeatInterval",
|
||||
8675984: "TlvTypeMobileTargetHeartbeatRestrictions",
|
||||
8676208: "TlvTypeConfigSMSPhoneNumber",
|
||||
8676496: "TlvTypeMobileTargetPositioning",
|
||||
8676672: "TlvTypeMobileTrojanUID",
|
||||
8676976: "TlvTypeMobileTrojanID",
|
||||
8677296: "TlvTypeMobileTargetLocationChangedRange",
|
||||
8677440: "TlvTypeConfigMobileAutoRemovalDateTime",
|
||||
8677808: "TlvTypeConfigOverwriteProxyAndPhones",
|
||||
8678000: "TlvTypeConfigCallPhoneNumber",
|
||||
8679488: "TlvTypeLocationAreaCode",
|
||||
8679744: "TlvTypeCellID",
|
||||
8680048: "TlvTypeMobileCountryCode",
|
||||
8680304: "TlvTypeMobileNetworkCode",
|
||||
8680560: "TlvTypeIMSI",
|
||||
8680816: "TlvTypeIMEI",
|
||||
8681072: "TlvTypeGPSLatitude",
|
||||
8681328: "TlvTypeGPSLongitude",
|
||||
8681520: "TlvTypeFirstHeartbeat",
|
||||
8681872: "TlvTypeInstalledModules",
|
||||
8683568: "TlvTypeValidGPSValues",
|
||||
8389008: "TlvTypeTargetData",
|
||||
8389280: "TlvTypeTargetHeartBeat",
|
||||
8389680: "TlvTypeTargetKeepSessionAlive",
|
||||
8390000: "TlvTypeTargetLocalIP",
|
||||
8390256: "TlvTypeTargetGlobalIP",
|
||||
8390448: "TlvTypeTargetState",
|
||||
8390784: "TlvTypeTargetID",
|
||||
8391072: "TlvTypeGetInstalledModulesRequest",
|
||||
8391328: "TlvTypeInstalledModulesReply",
|
||||
8391488: "TlvTypeTrojanUID",
|
||||
8391808: "TlvTypeTrojanID",
|
||||
8392000: "TlvTypeTrojanMaxInfections",
|
||||
8392240: "TlvTypeScreenSaverOn",
|
||||
8392496: "TlvTypeScreenLocked",
|
||||
8392752: "TlvTypeRecordedDataAvailable",
|
||||
8393024: "TlvTypeDownloadedRecordedDataTimeStamp",
|
||||
8393280: "TlvTypeInstallationMode",
|
||||
8393552: "TlvTypeTargetRemoveNotification",
|
||||
8393792: "TlvTypeTargetPlatformBits",
|
||||
8394032: "TlvTypeRemoveItselfMaxInfectionReached",
|
||||
8394288: "TlvTypeRemoveItselfAtMasterRequest",
|
||||
8394544: "TlvTypeRemoveItselfAtAgentRequest",
|
||||
8394912: "TlvTypeRemoveItselfAtAgentReqRequest",
|
||||
8395072: "TlvTypeRecordedFilesDownloadTotal",
|
||||
8395328: "TlvTypeRecordedFilesDownloadProgress",
|
||||
8395632: "TlvTypeTargetLicenseInfo",
|
||||
8395840: "TlvTypeRemoveTargetLicenseInfo",
|
||||
8396176: "TlvTypeTargetAllConfigurations",
|
||||
8396960: "TlvTypeTargetError",
|
||||
8401056: "TlvTypeGetTargetConfigRequest",
|
||||
8401312: "TlvTypeTargetConfigReply",
|
||||
8401568: "TlvTypeSetTargetConfigRequest",
|
||||
8402304: "TlvTypeConfigTargetID",
|
||||
8402496: "TlvTypeConfigTargetHeartbeatInterval",
|
||||
8402800: "TlvTypeConfigTargetProxy",
|
||||
8403008: "TlvTypeConfigTargetPort",
|
||||
8403584: "TlvTypeConfigAutoRemovalDateTime",
|
||||
8403776: "TlvTypeConfigAutoRemovalIfNoProxy",
|
||||
8404032: "TlvTypeInternalAutoRemovalElapsedTime",
|
||||
8405040: "TlvTypeConfigActiveHiding",
|
||||
8409248: "TlvTypeTargetLoadModuleRequest",
|
||||
8409504: "TlvTypeTargetLoadModuleReply",
|
||||
8409760: "TlvTypeTargetUnLoadModuleRequest",
|
||||
8410016: "TlvTypeTargetUnLoadModuleReply",
|
||||
8410272: "TlvTypeTargetUploadModuleRequest",
|
||||
8410528: "TlvTypeTargetUploadModuleReply",
|
||||
8410784: "TlvTypeTargetUploadModuleChunk",
|
||||
8411040: "TlvTypeTargetUploadModuleDoneRequest",
|
||||
8411296: "TlvTypeTargetUploadModuleDoneReply",
|
||||
8411552: "TlvTypeTargetRemoveModuleRequest",
|
||||
8411808: "TlvTypeTargetRemoveModuleReply",
|
||||
8412064: "TlvTypeTargetOfflineUploadModuleRequest",
|
||||
8412320: "TlvTypeTargetOfflineUploadModuleReply",
|
||||
8412576: "TlvTypeTargetOfflineUploadModuleChunk",
|
||||
8412832: "TlvTypeTargetOfflineUploadModuleDoneRequest",
|
||||
8413088: "TlvTypeTargetOfflineUploadModuleDoneReply",
|
||||
8413344: "TlvTypeTargetOfflineError",
|
||||
8413600: "TlvTypeTargetUploadError",
|
||||
8417440: "TlvTypeTargetGetRecordedFilesRequest",
|
||||
8417696: "TlvTypeTargetRecordedFilesReply",
|
||||
8417952: "TlvTypeTargetRecordedFileDownloadRequest",
|
||||
8418208: "TlvTypeTargetRecordedFileDownloadReply",
|
||||
8418464: "TlvTypeTargetRecordedFileDownloadChunk",
|
||||
8418720: "TlvTypeTargetRecordedFileDownloadCompleted",
|
||||
8418976: "TlvTypeTargetRecordedFileDeleteRequest",
|
||||
8419232: "TlvTypeTargetRecordedFileDeleteReply",
|
||||
8419488: "TlvTypeTargetGetRecordedFilesRequestEx",
|
||||
8419744: "TlvTypeTargetRecordedFilesReplyEx",
|
||||
8420000: "TlvTypeTargetRecordedFileDeleteRequestEx",
|
||||
8420256: "TlvTypeTargetRecordedFilesDownloadRequestEx",
|
||||
16744768: "TlvTypeProxyConnectionBroken",
|
||||
16712000: "TlvTypeTargetConnectionBroken",
|
||||
16712256: "TlvTypeAgentConnectionBroken",
|
||||
16712512: "TlvTypeTargetOffline",
|
||||
16646544: "TlvTypePlaintext",
|
||||
16646800: "TlvTypeCompression",
|
||||
16647056: "TlvTypeEncryption",
|
||||
16647232: "TlvTypeTargetUID",
|
||||
16647536: "TlvTypeIPAddress",
|
||||
16647808: "TlvTypeUserName",
|
||||
16648064: "TlvTypeComputerName",
|
||||
16648304: "TlvTypeLoginName",
|
||||
16648560: "TlvTypePassphrase",
|
||||
16648832: "TlvTypeRecordID",
|
||||
16649088: "TlvTypeOwner",
|
||||
16649344: "TlvTypeMetaData",
|
||||
16649536: "TlvTypeModuleID",
|
||||
16649856: "TlvTypeOSName",
|
||||
16650048: "TlvTypeModuleSubID",
|
||||
16650320: "TlvTypeErrorCode",
|
||||
16650560: "TlvTypeOffset",
|
||||
16650816: "TlvTypeLength",
|
||||
16651088: "TlvTypeRequestID",
|
||||
16651328: "TlvTypeRequestType",
|
||||
16651584: "TlvTypeVersion",
|
||||
16651840: "TlvTypeMachineID",
|
||||
16652096: "TlvTypeMajorNumber",
|
||||
16652352: "TlvTypeMinorNumber",
|
||||
16652656: "TlvTypeGlobalIPAddress",
|
||||
16652912: "TlvTypeASCII_Filename",
|
||||
16653120: "TlvTypeFilesize",
|
||||
16653392: "TlvTypeFilecount",
|
||||
16653712: "TlvTypeFiledata",
|
||||
16653968: "TlvTypeMD5Sum",
|
||||
16654144: "TlvTypeProxyPort",
|
||||
16654400: "TlvTypeStatus",
|
||||
16654656: "TlvTypeUserID",
|
||||
16654912: "TlvTypeGroupID",
|
||||
16655168: "TlvTypePermissions",
|
||||
16655424: "TlvTypeRequestCode",
|
||||
16655680: "TlvTypeDataSize",
|
||||
16655936: "TlvTypeKeyType",
|
||||
16656240: "TlvTypeEmail",
|
||||
16656432: "TlvTypeEnabled",
|
||||
16656688: "TlvTypeLicensed",
|
||||
16656960: "TlvTypeAudioFrequency",
|
||||
16657216: "TlvTypeAudioBitsPerSample",
|
||||
16657472: "TlvTypeAudioChannels",
|
||||
16657728: "TlvTypeStartTime",
|
||||
16657984: "TlvTypeStopTime",
|
||||
16658240: "TlvTypeBitMask",
|
||||
16658560: "TlvTypeTimeZone",
|
||||
16658816: "TlvTypeDateTime",
|
||||
16659072: "TlvTypeStartSessionDateTime",
|
||||
16659328: "TlvTypeStopSessionDateTime",
|
||||
16659520: "TlvTypeDateTimeRef",
|
||||
16659776: "TlvTypeScheduleRepeat",
|
||||
16660032: "TlvTypeUnixMasterDateTime",
|
||||
16660288: "TlvTypeUnixUTCDateTime",
|
||||
16660544: "TlvTypeDurationInSeconds",
|
||||
16660864: "TlvTypeMasterRefTime",
|
||||
16661120: "TlvTypeMasterRefTimeStart",
|
||||
16661376: "TlvTypeMasterRefTimeEnd",
|
||||
16661568: "TlvTypeCounter",
|
||||
16661888: "TlvTypeWhiteListEntry",
|
||||
16662144: "TlvTypeBlackListEntry",
|
||||
16662336: "TlvTypeBlackWhiteListingMode",
|
||||
16662576: "TlvTypeConfigEnabled",
|
||||
16662848: "TlvTypeConfigMaxRecordingSize",
|
||||
16663104: "TlvTypeConfigAudioQuality",
|
||||
16663344: "TlvTypeConfigVideoBlackAndWhite",
|
||||
16663616: "TlvTypeConfigVideoResolution",
|
||||
16663872: "TlvTypeConfigCaptureFrequency",
|
||||
16664128: "TlvTypeConfigVideoQuality",
|
||||
16664384: "TlvTypeConfigFilesStandardFilter",
|
||||
16664704: "TlvTypeConfigFilesCustomFilter",
|
||||
16664896: "TlvTypeConfigStandardLocation",
|
||||
16665216: "TlvTypeConfigCustomLocation",
|
||||
16665408: "TlvTypeConfigFileChunkSize",
|
||||
16665664: "TlvTypeConfigFileTransferSpeed",
|
||||
16665904: "TlvTypeConfigUploadFileOverwrite",
|
||||
16666160: "TlvTypeConfigDeleteOverReboot",
|
||||
16666496: "TlvTypeConfigCustomLocationException",
|
||||
16666752: "TlvTypeExtraData",
|
||||
16667008: "TlvTypeSignature",
|
||||
16667264: "TlvTypeComments",
|
||||
16667520: "TlvTypeDescription",
|
||||
16667776: "TlvTypeFilenameExtension",
|
||||
16668032: "TlvTypeSessionType",
|
||||
16668224: "TlvTypePeriod",
|
||||
16668512: "TlvTypeMobileTargetUID",
|
||||
16668784: "TlvTypeMobileTargetID",
|
||||
16669072: "TlvTypeMobilePlaintext",
|
||||
16669328: "TlvTypeMobileCompression",
|
||||
16669584: "TlvTypeMobileEncryption",
|
||||
16669824: "TlvTypeEncodingType",
|
||||
16670576: "TlvTypePhoneNumber",
|
||||
16670784: "TlvTypeConfigCustomLocationMode",
|
||||
16674928: "TlvTypeNetworkInterface",
|
||||
16675136: "TlvTypeNetworkInterfaceMode",
|
||||
16675440: "TlvTypeNetworkInterfaceAddress",
|
||||
16675696: "TlvTypeNetworkInterfaceNetmask",
|
||||
16675952: "TlvTypeNetworkInterfaceGateway",
|
||||
16676208: "TlvTypeNetworkInterfaceDNS_1",
|
||||
16676464: "TlvTypeNetworkInterfaceDNS_2",
|
||||
16677440: "TlvTypeLoginTime",
|
||||
16677696: "TlvTypeLogoffTime",
|
||||
16678720: "TlvTypeGeneric_Type",
|
||||
16678976: "TlvTypeChecksum",
|
||||
16679280: "TlvTypeCity",
|
||||
16679536: "TlvTypeCountry",
|
||||
16679792: "TlvTypeCountryCode",
|
||||
16683072: "TlvTypeTargetType",
|
||||
16683392: "TlvTypeDurationString",
|
||||
8257792: "TlvTypeTestMetaTypeInvalid",
|
||||
8258608: "TlvTypeTestMetaTypeBool",
|
||||
8258880: "TlvTypeTestMetaTypeUInt",
|
||||
8259152: "TlvTypeTestMetaTypeInt",
|
||||
8259440: "TlvTypeTestMetaTypeString",
|
||||
8259712: "TlvTypeTestMetaTypeUnicode",
|
||||
8259984: "TlvTypeTestMetaTypeRaw",
|
||||
8260256: "TlvTypeTestMetaTypeGroup",
|
||||
8260416: "TlvTypeTestMemberIdentifier",
|
||||
8260736: "TlvTypeTestMemberName",
|
||||
0x2331a0: "TlvTypeVideoConfigReply", # Guess based on module
|
||||
0x2431a0: "TlvTypeScreenRecordingConfigReply", # Guess
|
||||
0x2731a0: "TlvTypeEmailConfigReply", # Guess
|
||||
0x2831a0: "TlvTypeWifiConfigReply", # Guess
|
||||
0x2931a0: "TlvTypeRemoteConfigReply", #Guess
|
||||
}
|
||||
|
||||
NEED_RECURSION = ["TlvTypeChangedConfigReply", "TlvTypeTargetConfigReply",
|
||||
"TlvTypeFileSystemConfigReply", "TlvTypeCmdLineConfigReply",
|
||||
"TlvTypeSchedulerConfigReply", "TlvTypeMobileTargetOfflineConfig",
|
||||
"TlvTypeMobileTrackingConfigRaw", "TlvTypeMobileTrackingConfig",
|
||||
"0x544090", "0x5440a0", "0x534090", "0x5341a0"]
|
||||
|
||||
|
||||
def decode(m):
|
||||
cfg = {}
|
||||
while m.b.tell() < m._len:
|
||||
size = m.dword()
|
||||
tag = m.dword()
|
||||
tag_type = (tag & 0xf0) >> 4
|
||||
name = tlv_types.get(tag)
|
||||
if tag_type < 4:
|
||||
data = m.byte()
|
||||
elif tag_type >= 6:
|
||||
data = m.read(size - 8)
|
||||
if tag_type == 8:
|
||||
data = data.decode('utf-16')
|
||||
if u"\u0380" in data:
|
||||
category, rest = data.split(u"\u0380")
|
||||
data = {'category': category, 'list': rest.split(u"\u0381")}
|
||||
else:
|
||||
data = m.dword()
|
||||
if not name:
|
||||
name = hex(tag)
|
||||
|
||||
if name in NEED_RECURSION or "ConfigReply" in name:
|
||||
nm = M(data)
|
||||
cfg[name] = decode(nm)
|
||||
elif name in cfg and type(cfg[name]) != list:
|
||||
olv = cfg[name]
|
||||
cfg[name] = [olv, data]
|
||||
elif name in cfg and type(cfg[name]) == list:
|
||||
cfg[name].append(data)
|
||||
elif name == "TlvTypeInstalledModules":
|
||||
# Specific decoding for Android modules
|
||||
olv = {"data": data}
|
||||
olv["logging"] = (data[68] == 1)
|
||||
olv["spycall"] = (data[64] == 1)
|
||||
olv["call_interception"] = (data[65] == 1)
|
||||
olv["sms"] = (data[66] == 1)
|
||||
olv["addressbook"] = (data[67] == 1)
|
||||
olv["tracking"] = (data[69] == 1)
|
||||
olv["phonelogs"] = (data[70] == 1)
|
||||
cfg[name] = olv
|
||||
else:
|
||||
cfg[name] = data
|
||||
|
||||
return cfg
|
||||
|
||||
class MyEncoder(JSONEncoder):
|
||||
"""
|
||||
JSON encoder to encode bytes
|
||||
"""
|
||||
def default(self, o):
|
||||
if isinstance(o, bytes):
|
||||
try:
|
||||
return o.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
return repr(o)
|
||||
return o
|
||||
|
||||
|
||||
# From https://github.com/mak/mlib
|
||||
class M(object):
|
||||
TRANSL = {'byte': ('B', 1), 'word': ('H', 2),
|
||||
'dword': ('I', 4), 'qword': ('Q', 8)}
|
||||
|
||||
def __init__(self, d, end_fmt=''):
|
||||
self._len = len(d)
|
||||
self.b = BytesIO(d)
|
||||
|
||||
def _get_bytes(self, fmt, s, off):
|
||||
return struct.unpack(fmt, self.read(off, s) if off else self.read(s))[0]
|
||||
|
||||
def skip(self, n):
|
||||
self.b.seek(n, os.SEEK_CUR)
|
||||
|
||||
def unskip(self, n):
|
||||
self.b.seek(-n, os.SEEK_CUR)
|
||||
|
||||
def read(self, a0, a1= None):
|
||||
r = None
|
||||
if a1 is None:
|
||||
r = self.b.read(a0)
|
||||
else:
|
||||
r = self.read_at(a0,a1)
|
||||
return r
|
||||
|
||||
def read_at(self, off, n):
|
||||
old_l = self.b.tell()
|
||||
self.b.seek(off, os.SEEK_SET)
|
||||
r = self.b.read(n)
|
||||
self.b.seek(old_l, os.SEEK_SET)
|
||||
return r
|
||||
|
||||
def __len__(self):
|
||||
return self._len
|
||||
|
||||
def __getattr__(self, name):
|
||||
at = False
|
||||
if name.endswith('_at'):
|
||||
name = name[:-3]
|
||||
|
||||
if name in M.TRANSL:
|
||||
f, s = M.TRANSL[name]
|
||||
return lambda off = None: self._get_bytes(f, s, off)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Decode FinSpy configuration files')
|
||||
parser.add_argument('CONFFILE', help='Configuration file')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
with open(args.CONFFILE, 'rb') as f:
|
||||
d = f.read()
|
||||
|
||||
m = M(d)
|
||||
total_size = m.dword()
|
||||
if total_size != len(d):
|
||||
print("Encrypted configuration, decrypting...")
|
||||
k = (0xaa, 0x5a, 0xa5)
|
||||
r = bytearray()
|
||||
for i, c in enumerate(bytearray(d)):
|
||||
r.append(c ^ k[i % 3])
|
||||
data = bytes(r)
|
||||
m = M(data)
|
||||
total_size = m.dword()
|
||||
|
||||
_ = m.dword() ## doesn't matter but config is wrapped into TlvTypeEncryption
|
||||
cfg = decode(m)
|
||||
print(json.dumps(cfg, cls=MyEncoder, indent=4))
|
||||
@@ -1,13 +0,0 @@
|
||||
sha256,Description
|
||||
1e9162cd0941557304a6a097dfaadf59f90bc8bbaa9879afe67b5ce0d1514be8,Linux FinSpy sample
|
||||
854774a198db490a1ae9f06d5da5fe6a1f683bf3d7186e56776516f982d41ad3,Android FinSpy sample
|
||||
bb8c0e477512adab1db26eb77fe10dadbc5dcbf8e94569061c7199ca4626a420,Backdoored rar installer
|
||||
80d6e71c54fb3d4a904637e4d56e108a8255036cbb4760493b142889e47b951f,MacOS Installer
|
||||
f960144126748b971386731d35e41288336ad72a9da0c6b942287f397d57c600,Backdoored flash installer
|
||||
fab6b3bbc14c80049f95b040680fba6d1b47f07746729d04c887a55272084648,Encoded cobalt strike beacon
|
||||
8f216d2f0be2c4a5c07abf45cf138453f72f00ec598327756c6fc9d5f4dabe0d,Decoded Cobalt Strike beacon
|
||||
4f3003dd2ed8dcb68133f95c14e28b168bd0f52e5ae9842f528d3f7866495cea,Older Mac OS sample
|
||||
bd1b8bc046dbf19f8c9bbf9398fdbc47c777e1d9e6d9ff1787ada05ed75c1b12,Older Linux sample
|
||||
9f04439bc94f2eef76b72ac2e0aeece0d4f46b6c42ef179fc860f6b5876f5f50,Android FinSpy sample
|
||||
928aefbcac9386c953b3491230a719ff65b21612eb6bd9b32501de149cacbc92,Android FinSpy sample
|
||||
14658327efaa15275fb8718956ee97ebcad5bc80312a4f3182a3b10cd3dcf257,NilePhish downloader
|
||||
|
@@ -1,157 +0,0 @@
|
||||
# Overview of Ocean Lotus Samples used to target Vietnamese Human Rights Defenders
|
||||
|
||||
From May to November 2020, we have identified malware attacks targeting Human Rights Defenders and organizations from Viet Nam. This technical blog post provides an overview of the different Ocean Lotus samples identified, technical indicators, and details on the link with earlier Ocean Lotus activities. For more information on the context of these attacks and the targets we identified, please read the report entitled [“Click and Bait: Vietnamese Human Rights Defenders Targeted with Spyware Attacks”](https://www.amnesty.org/en/latest/research/2021/02/click-and-bait-vietnamese-human-rights-defenders-targeted-with-spyware-attacks/) on the Amnesty website (also available in Vietnamese).
|
||||
|
||||
We found 9 different malware samples in this investigation: 4 for Mac OS, and 5 for Microsoft Windows.
|
||||
|
||||
## Mac OS Malware
|
||||
|
||||
### First appearance in 2018
|
||||
|
||||
The first Mac OS sample we identified targeted Bui Thanh Hieu in February 2018. Attackers delivered a malicious Mac OS application named _“PHIẾU GHI DANH THAM DỰ TĨNH HỘI HMDC 2018”_ attached to an email. This sample belongs to the same family as the Ocean Lotus samples analysed by [Trend Micro in 2018](https://www.trendmicro.com/en_us/research/18/d/new-macos-backdoor-linked-to-oceanlotus-found.html), and they even share the same string encryption algorithm and key.
|
||||
|
||||
The malicious application uses a first stage dropper to bypass Apple GateKeeper, then it installs the final payload either in `/Library/CoreMediaIO/Plug-Ins/FCP-DAL/iOSScreenCapture.plugin/Contents/Resources/screenassistantd`, if it is launched with root access, otherwise in `~/Library/Spelling/spellagentd`. The malware gains persistence with a Property List file placed in `~/Library/LaunchAgents/`.
|
||||
|
||||
The final payload communicates with the same domains mentioned in the Trend Micro report: `ssl.arkouthrie.com`, `s3.hiahornber.com` and `widget.shoreoa.com`.
|
||||
|
||||
### New variants from 2019
|
||||
|
||||
In 2019 Bui Thanh Hieu received three more malicious emails with links to or attached malicious Mac OS applications, which are more recent variants of the same malware we described above. However, these variants seem less developed than the samples analysed by [Trend Micro in November 2020](https://www.trendmicro.com/en_us/research/20/k/new-macos-backdoor-connected-to-oceanlotus-surfaces.html), making them likely intermediate versions between those discovered by Trend Micro in 2018 and in 2020.
|
||||
|
||||
When executed, these applications launch an installer either embedded in the package or decrypted by a dedicated Python script. The installer disables security protections by removing the _com.apple.quarantine_ bit, launches the final payload and configures persistence by creating a property list in the LaunchAgent user folder, or in the _/Library/LaunchDaemons/_ folder if launched as root.
|
||||
|
||||

|
||||
|
||||
The installer drops two files in the destination folder: one Mach-O binary payload and an encrypted shared Mach-O library named `[INTEGER].3gp` (such as 33.3gp or 152.3gp). To avoid their discovery during forensic analysis, these files’ creation date and time are faked with the command `touch –t`.
|
||||
|
||||
The payload first gathers information on the system, including the MacOS version, the kernel version and details on the hardware and CPU. Then it tries to decrypt all the files in the folder until it finds a shared library exporting the functions `ArchaeologistCodeine` and `PlayerAberadurtheIncomprehensible`. This shared library implements the communication with one of three configured Command & Control (C&C) domains, using libcurl to send POST HTTP requests with an encrypted body.
|
||||
|
||||
This malware uses custom base64 and AES algorithms to obfuscate all the strings, making it harder to analyse or build signatures as the encryption keys are changing regularly. In comparison, the 2018 variant used a custom base64 but standard AES, while more recent samples analysed by Trend Micro in 2020 abandoned AES in favour of a custom byte manipulation algorithm.
|
||||
|
||||
This backdoor has limited purpose. It allows to manipulate files and execute commands in a terminal. For the full list of supported commands, check [Trend Micro’s report](https://www.trendmicro.com/en_us/research/18/d/new-macos-backdoor-linked-to-oceanlotus-found.html).
|
||||
|
||||
## Windows Backdoors
|
||||
|
||||
We identified five emails in 2019 and 2020 each containing two files compressed in RAR or ISO archives. The first file is a legitimate copy of Microsoft Word 2007’s executable used for DLL side-loading, while the second is a DLL named wwlib.dll loaded at launch by the Word executable it accompanies.
|
||||
|
||||
DLL side-loading is a technique observed [several times](https://unit42.paloaltonetworks.com/tracking-oceanlotus-new-downloader-kerrdown/) used by Ocean Lotus, typically with a Microsoft Word executable. The final payload is always a variant of a downloader used exclusively by Ocean Lotus and [named Kerrdown](https://unit42.paloaltonetworks.com/tracking-oceanlotus-new-downloader-kerrdown/) by the cybersecurity company Palo Alto. All the Kerrdown samples we analysed delivered a Cobalt Strike payload.
|
||||
|
||||
### Kerrdown analysis
|
||||
|
||||
Kerrdown is a dropper that uses several layers of shellcode to obfuscate the final payload. Each one of them decrypting and redirecting to the next layer, until the final payload is reached.
|
||||
|
||||
For instance, the first Kerrdown sample we found in May 2019 used 4 distinct stages before executing the final shellcode that downloads a payload from `api.ciscofreak.com/HjRX` (the domain was down during our investigation, but [this Cobalt Strike beacon](https://www.virustotal.com/gui/file/1cc3f2296f5cd9207f6c84fa9de26dcdbff0b16e49accb0f8dd670ee8d32dd50/detection) uploaded on Virus Total in 2019 communicates with this domain)
|
||||
|
||||

|
||||
|
||||
These layers of shellcode are different for each Kerrdown sample we discovered, making it challenging to build signatures for this malware family.
|
||||
|
||||
One of the samples which targeted the Vietnamese blogger in July 2020 introduced an additional step in the execution. The _wwwlib.dll_ payload installs a binary in `C:\ProgramData\Java\UK.exe`, a self-extractable RAR archive containing a legitimate executable copy of the Opera browser, then used to sideload a malicious DLL called _opera.dll_.
|
||||
|
||||
This opera.dll is another variant of the Kerrdown family, but the file itself is exceptionally large (42MB). Expanding payloads with junk data is [a technique](https://attack.mitre.org/techniques/T1027/001/), called “binary padding”, often used by malware to avoid detection by security solutions as some do not analyse large files in depth to avoid performance issues. Binary padding is known to have been used by Ocean Lotus [in the past](https://www.welivesecurity.com/2019/03/20/fake-or-fake-keeping-up-with-oceanlotus-decoys/). This Kerrdown sample includes an obfuscated Cobalt Strike beacon communicating with the domain `delicalo.dnsalias.net`.
|
||||
|
||||

|
||||
|
||||
### Cobalt Strike
|
||||
|
||||
Cobalt Strike is an intrusion toolkit sold by the US company [Strategic Cyber LLC](Strategic Cyber LLC) for penetration testing or adversary simulation. Over the past years, cracked versions of Cobalt Strike have been regularly used by attack groups in their operations. [Cobalt Strike allows](https://www.cobaltstrike.com/features) to remotely monitor a compromised system, including accessing files but also logging keystrokes or taking screenshots.
|
||||
|
||||
Ocean Lotus has been known for using Cobalt Strike since [at least 2017](https://www.cybereason.com/blog/operation-cobalt-kitty-apt). The 4 Kerrdown samples we identified all either embedded or downloaded a Cobalt Strike beacon. They all used a Cobalt Strike profile impersonating Google Safe Browsing services URLs, similar to [this public profile](https://github.com/rsmudge/Malleable-C2-Profiles/blob/master/normal/safebrowsing.profile).
|
||||
|
||||
The configuration can be easily extracted with the [scripts we released in September 2020](https://github.com/AmnestyTech/investigations/tree/master/2020-09-25_finfisher/scripts/cobaltstrike). Here is an example of configuration for a beacon hosted on `delicalo.dnsalias.net`:
|
||||
|
||||
```
|
||||
dns False
|
||||
ssl True
|
||||
port 443
|
||||
.sleeptime 4100
|
||||
.http-get.server.output
|
||||
.jitter 12
|
||||
.maxdns 245
|
||||
publickey 30819f300d06092a864886f70d010101050003818d0030818902818100ac50b035fd1b294778b8cbd4ee33323f9b04af158cca225d099052d7987441cbb365ab0f81c4c1190cd8758324e1cb7085dac65ce264dc510c57cfa1d1c7711f26c767d574f04ac16d20a0acf91d4e5dc1cc62c764676b0c38ba50d43953df5184468efdd6b4098c12b5c94be562de22881484accf8e69473621efa95e290f19020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
.http-get.uri delicalo.dnsalias[.]net,/safebrowsing/rd/e3Iz4FnySnhy3IuXKqrWM40JnseSLDHcH-OzVVfWmVgwx
|
||||
.user-agent Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
|
||||
.http-post.uri /safebrowsing/rd/3KHLhJGZRq4iyImdpSZ5RM90vLo3Yt2hB
|
||||
.http-get.client
|
||||
GAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflaPREF=ID=Cookie
|
||||
.http-post.client
|
||||
GAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflatU=NoncmvrScxBxlwoPREF=ID=Cookie
|
||||
.post-ex.spawnto_x86 %windir%\syswow64\rundll32.exe
|
||||
.post-ex.spawnto_x64 %windir%\sysnative\rundll32.exe
|
||||
.pipename
|
||||
.cryptoscheme 1
|
||||
.dns_idle 0
|
||||
.dns_sleep 0
|
||||
.http-get.verb GET
|
||||
.http-post.verb POST
|
||||
shouldChunkPosts 0
|
||||
.watermark 0
|
||||
.stage.cleanup 0
|
||||
CFGCaution 0
|
||||
.proxy_type 2
|
||||
killdate 0
|
||||
text_section 0
|
||||
process-inject-start-rwx 64
|
||||
process-inject-use-rwx 64
|
||||
process-inject-min_alloc 0
|
||||
process-inject-transform-x86
|
||||
process-inject-transform-x64
|
||||
```
|
||||
|
||||
## Indicators of Compromise
|
||||
|
||||
### Mac OS samples
|
||||
|
||||
| Feb 2018 | |
|
||||
| ------------- |-------------|
|
||||
| Package name | PHIẾU GHI DANH THAM DỰ TĨNH HỘI HMDC 2018 |
|
||||
| Dropper | 952c16674bde3c16aa3935b3e01f3f0fb4cbac7ffa130143cbf6ccaa72733068 |
|
||||
| Payload | d3a198e18f8c5e9ed54ed4959b471a0f15fbda7d4abf92b7726bc07723e46dd5 |
|
||||
| C&C | `ssl.arkouthrie.com` `widget.shoreoa.com` `s3.hiahornber.com` |
|
||||
| **June 2019** | |
|
||||
| Package name | TaiLieu |
|
||||
| Dropper | ecb6186a5e722fa360ece37191589305858a0e176321c9339831f2884dcb0405 |
|
||||
| Payload | 1599fe6cc77764c17802cfde1ca77f091bb3ec2a49f6cab1c80ee667ea7c752b |
|
||||
| Network library | b8567ce4d0595e6466414999798bcb1dfe01cc5ca1dd058bfc55f92033f0f3d8 |
|
||||
| C&C | `tips.jasperpfeiffer.com` `land.rellecharlessper.com` and `art.guillermoespana.com` |
|
||||
| **October 2019** | |
|
||||
| Package Name | Danh sach nhan su |
|
||||
| Dropper | b252a8d2ec5c7080286fe3f0ad193062f506b5c34c4c797f97717e396c0a22d5 |
|
||||
| Payload | 9c14cffd79f863fec0a6c0ed337ea82a9044db09afda53b8ac2aef1d49f74f4f |
|
||||
| Network Library | 5ed6b7b450ead2d0e69faa3069d1e0bd3a6852909092235f75087da0ca05462f |
|
||||
| C&C | `tips.jasperpfeiffer.com` `land.rellecharlessper.com` and `art.guillermoespana.com` |
|
||||
| **December 2019** | |
|
||||
| Package Name | Don keu cuu cua gia dinh Le Nam Tra |
|
||||
| Dropper | a890c88b6c64371242b4047830b9189b4546536c6b11576d0738f0ba1840ade |
|
||||
| Payload | 0c41358adeea24d80b35bac4b4f60d93711e32e287343cb604e1fa79b5e5e465 |
|
||||
| Network Library | 5ed6b7b450ead2d0e69faa3069d1e0bd3a6852909092235f75087da0ca05462f |
|
||||
| C&C | `tips.jasperpfeiffer.com` `land.rellecharlessper.com` and `art.guillermoespana.com` |
|
||||
|
||||
### Windows Samples
|
||||
|
||||
| June 2019 | |
|
||||
|-----------|--|
|
||||
| Winword.exe (legitimate) | 6c959cfb001fbb900958441dfd8b262fb33e052342948bab338775d3e83ef7f7 |
|
||||
| wwlib.dll | 148e647885712b69258967c5f8798966fb9b8ae24847dda8aeb880cb6f56b6da |
|
||||
| C&C | `api.ciscofreak.com` |
|
||||
| **April 2020** | |
|
||||
| Winword.exe (legitimate) | 6c959cfb001fbb900958441dfd8b262fb33e052342948bab338775d3e83ef7f7 |
|
||||
| wwlib.dll | acb33adf7429424170f63fa5490ed580cf502de4a7ef00e4b8c962425cd85052 |
|
||||
| C&C | `node.podzone.org` |
|
||||
| **July 2020** | |
|
||||
| Winword.exe (legitimate) | 6c959cfb001fbb900958441dfd8b262fb33e052342948bab338775d3e83ef7f7 |
|
||||
| wwlib.dll | 5cc8d52fcabfd35042336e095f1f78c2b2884e7826358f5385729cf45ce4d860 |
|
||||
| Opera.exe (legitimate) | 71c3b9538a0f14a8ab67e579ecc4ce2b01e25507d8c07eaf46555e8f44181e37 |
|
||||
| Opera.dll | a51fb048e5a2730bffd0fd43e3bdda4e931c9358254aff960ddf43526c768120 |
|
||||
| C&C | `delicalo.dnsalias.net` |
|
||||
| **November 2020 (2 emails)** | |
|
||||
| Winword.exe (legitimate) | 6c959cfb001fbb900958441dfd8b262fb33e052342948bab338775d3e83ef7f7 |
|
||||
| wwlib.dll | a574720e7b4f420098a0ac0055089000435439eb61ec6de2077ac0f782a506e9 |
|
||||
| C&C | `coco.cechire.com` |
|
||||
|
||||
|
||||
You can find the full list of indicators of compromise [here](https://github.com/AmnestyTech/investigations/tree/master/2021-02-24_vietnam/indicators).
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB |
@@ -1,9 +0,0 @@
|
||||
# Indicators of Compromise
|
||||
|
||||
Indicators of compromise of the report [Click and Bait: Vietnamese Human Rights Defenders Targeted with Spyware Attacks ](https://www.amnesty.org/en/latest/research/2021/02/click-and-bait-vietnamese-human-rights-defenders-targeted-with-spyware-attacks/)
|
||||
|
||||
Files:
|
||||
* `domains.txt`: list of domains
|
||||
* `ips.txt`: list of IP addresses
|
||||
* `rules.yar`: YARA rules
|
||||
* `sha256.txt`: SHA256 of samples
|
||||
@@ -1,10 +0,0 @@
|
||||
ssl.arkouthrie.com
|
||||
widget.shoreoa.com
|
||||
s3.hiahornber.com
|
||||
tips.jasperpfeiffer.com
|
||||
land.rellecharlessper.com
|
||||
art.guillermoespana.com
|
||||
api.ciscofreak.com
|
||||
node.podzone.org
|
||||
delicalo.dnsalias.net
|
||||
coco.cechire.com
|
||||
@@ -1,6 +0,0 @@
|
||||
185.174.101.13
|
||||
185.157.79.134
|
||||
95.168.191.35
|
||||
45.76.106.146
|
||||
5.149.254.19
|
||||
103.114.161.122
|
||||
@@ -1,62 +0,0 @@
|
||||
rule apt32_macos_dropper {
|
||||
meta:
|
||||
author = "Amnesty Tech"
|
||||
|
||||
strings:
|
||||
$s1 = "setStartup" ascii
|
||||
$s2 = "getSizeDataLoader" ascii
|
||||
$s3 = "GET_LAUNCHNAME" ascii
|
||||
$s4 = "GET_PROCESSNAME" ascii
|
||||
$s5 = "getProcessnameRoot" ascii
|
||||
$s6 = "getProcessnameUser" ascii
|
||||
$s7 = "getProcessPathRoot" ascii
|
||||
$s8 = "getLabelnameRoot" ascii
|
||||
$s9 = "getLabelnameUser" ascii
|
||||
$s10 = "stringFromHex" ascii
|
||||
$s11 = "_b64_decode_ex" ascii
|
||||
|
||||
condition:
|
||||
(uint16(0) == 0xfacf or uint16(0) == 0xface) and 9 of them
|
||||
}
|
||||
|
||||
rule apt32_macos_backdoor_2018_encryption_key {
|
||||
strings:
|
||||
$key = { 63 49 2f 6e 22 00 10 fe 33 4f 2f c5 05 b2 11 03 ba 5b dd 02 }
|
||||
$ccc = "CCCrypt" ascii
|
||||
condition:
|
||||
(uint16(0) == 0xfacf or uint16(0) == 0xface) and all of them
|
||||
}
|
||||
|
||||
rule apt32_macos_backdoor_2019_encryption_key {
|
||||
meta:
|
||||
report = "https://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/"
|
||||
strings:
|
||||
$key1 = { 9D 72 74 AD 7B CE F0 DE D2 9B DB B4 28 C2 51 DF 8B 35 0B 92 }
|
||||
$key2 = {2c e4 25 29 5e 2a 20 40 9c a5 13 1e 61 1e 51 6f 2c b7 a7 7f }
|
||||
$key3 = { 8b b2 c4 67 56 5c 63 42 8e f0 cf c5 f4 8d 87 ae 58 0c 5b a4 }
|
||||
$ccc = "CCCrypt" ascii
|
||||
condition:
|
||||
(uint16(0) == 0xfacf or uint16(0) == 0xface) and $ccc and any of ($key*)
|
||||
}
|
||||
|
||||
rule apt32_macos_backdoor_2018 {
|
||||
meta:
|
||||
author = "Amnesty Tech"
|
||||
|
||||
strings:
|
||||
$s1 = "respondDownloadThreadP" ascii
|
||||
$s2 = "checkProcessExist" ascii
|
||||
$s3 = "setFristRandom" ascii
|
||||
$s4 = "getInstalledTime" ascii
|
||||
$s5 = "getSerialNumber" ascii
|
||||
$s6 = "appendPathComponent" ascii
|
||||
$s7 = "initFirstRandom" ascii
|
||||
$s8 = "CFURLToString" ascii
|
||||
$s9 = "GET_DOMAIN_CLIENT_INFO" ascii
|
||||
$s10 = "getFirstRandom_Header" ascii
|
||||
$s11 = "respondLoadLunaThread" ascii
|
||||
|
||||
condition:
|
||||
(uint16(0) == 0xfacf or uint16(0) == 0xface) and 9 of them
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
952c16674bde3c16aa3935b3e01f3f0fb4cbac7ffa130143cbf6ccaa72733068
|
||||
d3a198e18f8c5e9ed54ed4959b471a0f15fbda7d4abf92b7726bc07723e46dd5
|
||||
ecb6186a5e722fa360ece37191589305858a0e176321c9339831f2884dcb0405
|
||||
1599fe6cc77764c17802cfde1ca77f091bb3ec2a49f6cab1c80ee667ea7c752b
|
||||
b8567ce4d0595e6466414999798bcb1dfe01cc5ca1dd058bfc55f92033f0f3d8
|
||||
b252a8d2ec5c7080286fe3f0ad193062f506b5c34c4c797f97717e396c0a22d5
|
||||
9c14cffd79f863fec0a6c0ed337ea82a9044db09afda53b8ac2aef1d49f74f4f
|
||||
5ed6b7b450ead2d0e69faa3069d1e0bd3a6852909092235f75087da0ca05462f
|
||||
a890c88b6c64371242b4047830b9189b4546536c6b11576d0738f0ba1840aded
|
||||
0c41358adeea24d80b35bac4b4f60d93711e32e287343cb604e1fa79b5e5e465
|
||||
5ed6b7b450ead2d0e69faa3069d1e0bd3a6852909092235f75087da0ca05462f
|
||||
148e647885712b69258967c5f8798966fb9b8ae24847dda8aeb880cb6f56b6da
|
||||
acb33adf7429424170f63fa5490ed580cf502de4a7ef00e4b8c962425cd85052
|
||||
5cc8d52fcabfd35042336e095f1f78c2b2884e7826358f5385729cf45ce4d860
|
||||
a574720e7b4f420098a0ac0055089000435439eb61ec6de2077ac0f782a506e9
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user