aegis-node 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aegis_node-0.1.0/PKG-INFO +76 -0
- aegis_node-0.1.0/README.md +57 -0
- aegis_node-0.1.0/aegis_node/__init__.py +4 -0
- aegis_node-0.1.0/aegis_node/__main__.py +4 -0
- aegis_node-0.1.0/aegis_node/adapters.py +128 -0
- aegis_node-0.1.0/aegis_node/agent.py +3104 -0
- aegis_node-0.1.0/aegis_node.egg-info/PKG-INFO +76 -0
- aegis_node-0.1.0/aegis_node.egg-info/SOURCES.txt +12 -0
- aegis_node-0.1.0/aegis_node.egg-info/dependency_links.txt +1 -0
- aegis_node-0.1.0/aegis_node.egg-info/entry_points.txt +2 -0
- aegis_node-0.1.0/aegis_node.egg-info/requires.txt +1 -0
- aegis_node-0.1.0/aegis_node.egg-info/top_level.txt +1 -0
- aegis_node-0.1.0/pyproject.toml +37 -0
- aegis_node-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aegis-node
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Aegis WiFi Node Agent — connect a local USB WiFi adapter to the Aegis pentest platform
|
|
5
|
+
Author-email: Divolt <hello@divoltbtc.com>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://divoltbtc.com
|
|
8
|
+
Project-URL: Documentation, https://portal.aegis.divoltbtc.com
|
|
9
|
+
Keywords: pentest,wifi,wireless,security,aegis
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Security
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.28
|
|
19
|
+
|
|
20
|
+
# Aegis WiFi Node Agent
|
|
21
|
+
|
|
22
|
+
Connect a local USB WiFi adapter to the [Aegis](https://divoltbtc.com) pentest platform for wireless network assessments.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pipx install aegis-node
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If pipx is not available:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install --user aegis-node
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. Check system readiness
|
|
40
|
+
aegis-node preflight
|
|
41
|
+
|
|
42
|
+
# 2. Auto-install missing tools (requires sudo)
|
|
43
|
+
aegis-node preflight --install
|
|
44
|
+
|
|
45
|
+
# 3. Connect to Aegis (opens browser for authorization)
|
|
46
|
+
aegis-node connect
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The `connect` command opens your browser to authorize the device.
|
|
50
|
+
Confirm the verification code matches your terminal, click **Authorize Device**, and the agent connects automatically.
|
|
51
|
+
|
|
52
|
+
## Options
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
aegis-node connect # browser auth (default server)
|
|
56
|
+
aegis-node connect --no-browser # print URL instead of opening browser
|
|
57
|
+
aegis-node connect --server URL # custom server URL
|
|
58
|
+
aegis-node preflight # check adapter + tools
|
|
59
|
+
aegis-node preflight --install # auto-install missing tools
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Requirements
|
|
63
|
+
|
|
64
|
+
- Linux (Kali recommended) or WSL2
|
|
65
|
+
- Python 3.9+
|
|
66
|
+
- USB WiFi adapter with monitor mode support (e.g., WIFISKY WS-980WG, Alfa AWUS036ACM)
|
|
67
|
+
- aircrack-ng, nmap, hashcat, tcpdump (auto-installed via `preflight --install`)
|
|
68
|
+
|
|
69
|
+
## Supported adapters
|
|
70
|
+
|
|
71
|
+
| Adapter | Chipset | Monitor | Inject | Bands |
|
|
72
|
+
|---------|---------|---------|--------|-------|
|
|
73
|
+
| WIFISKY WS-980WG | RTL8187L | Yes | Yes | 2.4 GHz |
|
|
74
|
+
| Alfa AWUS036ACM | MT7612U | Yes | Yes | 2.4+5 GHz |
|
|
75
|
+
| Alfa AWUS036ACH | RTL8812AU | Yes | Yes | 2.4+5 GHz |
|
|
76
|
+
| Alfa AWUS036NHA | AR9271 | Yes | Yes | 2.4 GHz |
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Aegis WiFi Node Agent
|
|
2
|
+
|
|
3
|
+
Connect a local USB WiFi adapter to the [Aegis](https://divoltbtc.com) pentest platform for wireless network assessments.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pipx install aegis-node
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If pipx is not available:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install --user aegis-node
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# 1. Check system readiness
|
|
21
|
+
aegis-node preflight
|
|
22
|
+
|
|
23
|
+
# 2. Auto-install missing tools (requires sudo)
|
|
24
|
+
aegis-node preflight --install
|
|
25
|
+
|
|
26
|
+
# 3. Connect to Aegis (opens browser for authorization)
|
|
27
|
+
aegis-node connect
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The `connect` command opens your browser to authorize the device.
|
|
31
|
+
Confirm the verification code matches your terminal, click **Authorize Device**, and the agent connects automatically.
|
|
32
|
+
|
|
33
|
+
## Options
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
aegis-node connect # browser auth (default server)
|
|
37
|
+
aegis-node connect --no-browser # print URL instead of opening browser
|
|
38
|
+
aegis-node connect --server URL # custom server URL
|
|
39
|
+
aegis-node preflight # check adapter + tools
|
|
40
|
+
aegis-node preflight --install # auto-install missing tools
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
- Linux (Kali recommended) or WSL2
|
|
46
|
+
- Python 3.9+
|
|
47
|
+
- USB WiFi adapter with monitor mode support (e.g., WIFISKY WS-980WG, Alfa AWUS036ACM)
|
|
48
|
+
- aircrack-ng, nmap, hashcat, tcpdump (auto-installed via `preflight --install`)
|
|
49
|
+
|
|
50
|
+
## Supported adapters
|
|
51
|
+
|
|
52
|
+
| Adapter | Chipset | Monitor | Inject | Bands |
|
|
53
|
+
|---------|---------|---------|--------|-------|
|
|
54
|
+
| WIFISKY WS-980WG | RTL8187L | Yes | Yes | 2.4 GHz |
|
|
55
|
+
| Alfa AWUS036ACM | MT7612U | Yes | Yes | 2.4+5 GHz |
|
|
56
|
+
| Alfa AWUS036ACH | RTL8812AU | Yes | Yes | 2.4+5 GHz |
|
|
57
|
+
| Alfa AWUS036NHA | AR9271 | Yes | Yes | 2.4 GHz |
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""USB WiFi adapter detection and capability probing."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
import re
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
|
|
9
|
+
log = logging.getLogger('aegis.wifi_node.adapters')
|
|
10
|
+
|
|
11
|
+
# VID:PID → (chipset, driver, monitor_default, inject_default)
|
|
12
|
+
KNOWN_ADAPTERS: dict[str, tuple[str, str, bool, bool]] = {
|
|
13
|
+
# Proven pentest adapters
|
|
14
|
+
'0e8d:7612': ('MT7612U', 'mt76x2u', True, True),
|
|
15
|
+
'148f:761a': ('MT7612U', 'mt76x2u', True, True),
|
|
16
|
+
'0b05:17d1': ('MT7612U', 'mt76x2u', True, True), # ASUS USB-AC54
|
|
17
|
+
'0cf3:9271': ('AR9271', 'ath9k_htc', True, True), # Alfa AWUS036NHA
|
|
18
|
+
'0bda:8812': ('RTL8812AU', 'rtl8812au', True, True),
|
|
19
|
+
'0bda:881a': ('RTL8812AU', 'rtl8812au', True, True),
|
|
20
|
+
'0846:9052': ('RTL8812AU', 'rtl8812au', True, True), # Netgear A6100
|
|
21
|
+
'0bda:8187': ('RTL8187L', 'rtl8187', True, True), # WIFISKY WS-980WG
|
|
22
|
+
# Managed-mode only
|
|
23
|
+
'0bda:c832': ('RTL8832CU', 'rtl8832cu', False, False), # NEWFAST NF-U353
|
|
24
|
+
'0bda:b832': ('RTL8832CU', 'rtl8832cu', False, False),
|
|
25
|
+
'0bda:c82c': ('RTL8822CU', 'rtl8822cu', False, False),
|
|
26
|
+
'0bda:8179': ('RTL8188EUS', 'rtl8188eu', False, False),
|
|
27
|
+
'2357:011e': ('RTL8812AU', 'rtl8812au', True, True), # TP-Link T4U
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _run(cmd: list[str], timeout: int = 10) -> str:
|
|
32
|
+
try:
|
|
33
|
+
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
34
|
+
return r.stdout + r.stderr
|
|
35
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
|
36
|
+
return ''
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def detect_adapters() -> list[dict]:
|
|
40
|
+
"""Detect USB WiFi adapters via lsusb + iw dev."""
|
|
41
|
+
adapters = []
|
|
42
|
+
lsusb = _run(['lsusb'])
|
|
43
|
+
for line in lsusb.splitlines():
|
|
44
|
+
m = re.match(r'Bus \d+ Device \d+: ID (\w{4}:\w{4})\s+(.*)', line)
|
|
45
|
+
if not m:
|
|
46
|
+
continue
|
|
47
|
+
vid_pid = m.group(1).lower()
|
|
48
|
+
desc = m.group(2).strip()
|
|
49
|
+
if vid_pid not in KNOWN_ADAPTERS:
|
|
50
|
+
continue
|
|
51
|
+
chipset, driver, mon_default, inj_default = KNOWN_ADAPTERS[vid_pid]
|
|
52
|
+
adapters.append({
|
|
53
|
+
'vid_pid': vid_pid,
|
|
54
|
+
'chipset': chipset,
|
|
55
|
+
'driver': driver,
|
|
56
|
+
'description': desc,
|
|
57
|
+
'cap_monitor_mode': mon_default,
|
|
58
|
+
'cap_injection': inj_default,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
# Enrich with iw interface info
|
|
62
|
+
iw_out = _run(['iw', 'dev'])
|
|
63
|
+
ifaces = _parse_iw_dev(iw_out)
|
|
64
|
+
for a in adapters:
|
|
65
|
+
for iface in ifaces:
|
|
66
|
+
if iface.get('type') == 'managed':
|
|
67
|
+
a.setdefault('interface', iface['name'])
|
|
68
|
+
a.setdefault('mac', iface.get('addr', ''))
|
|
69
|
+
break
|
|
70
|
+
|
|
71
|
+
return adapters
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _parse_iw_dev(output: str) -> list[dict]:
|
|
75
|
+
"""Parse `iw dev` output into a list of interface dicts."""
|
|
76
|
+
ifaces = []
|
|
77
|
+
current: dict | None = None
|
|
78
|
+
for line in output.splitlines():
|
|
79
|
+
line = line.strip()
|
|
80
|
+
if line.startswith('Interface'):
|
|
81
|
+
if current:
|
|
82
|
+
ifaces.append(current)
|
|
83
|
+
current = {'name': line.split()[-1]}
|
|
84
|
+
elif current:
|
|
85
|
+
if line.startswith('addr'):
|
|
86
|
+
current['addr'] = line.split()[-1]
|
|
87
|
+
elif line.startswith('type'):
|
|
88
|
+
current['type'] = line.split()[-1]
|
|
89
|
+
if current:
|
|
90
|
+
ifaces.append(current)
|
|
91
|
+
return ifaces
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def probe_monitor_mode(interface: str) -> bool:
|
|
95
|
+
"""Test if an interface supports monitor mode via iw."""
|
|
96
|
+
if not interface:
|
|
97
|
+
return False
|
|
98
|
+
out = _run(['iw', 'phy'])
|
|
99
|
+
return 'monitor' in out.lower()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def probe_injection(interface: str) -> bool:
|
|
103
|
+
"""Test packet injection via aireplay-ng (requires monitor mode active)."""
|
|
104
|
+
if not shutil.which('aireplay-ng'):
|
|
105
|
+
return False
|
|
106
|
+
out = _run(['aireplay-ng', '--test', interface], timeout=15)
|
|
107
|
+
return 'Injection is working!' in out
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def detect_host_tools() -> dict[str, bool]:
|
|
111
|
+
"""Check which security tools are available on the host."""
|
|
112
|
+
tools = {}
|
|
113
|
+
for tool in ('airmon-ng', 'airodump-ng', 'aireplay-ng', 'aircrack-ng',
|
|
114
|
+
'nmap', 'hashcat', 'hcxdumptool', 'hcxpcapngtool',
|
|
115
|
+
'hostapd', 'dnsmasq', 'tcpdump', 'tshark', 'iw', 'iwconfig',
|
|
116
|
+
'reaver', 'arpspoof', 'macchanger'):
|
|
117
|
+
tools[tool] = shutil.which(tool) is not None
|
|
118
|
+
return tools
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def get_host_info() -> dict:
|
|
122
|
+
"""Collect host OS and hostname."""
|
|
123
|
+
import platform
|
|
124
|
+
return {
|
|
125
|
+
'os': f'{platform.system()} {platform.release()}',
|
|
126
|
+
'hostname': platform.node(),
|
|
127
|
+
'tools': detect_host_tools(),
|
|
128
|
+
}
|