Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/infobyte/pyrmax
Сканеры уязвимостейОбратная инженерияФаззингСетевая безопасностьБезопасность беспроводных сетей
GitHubinfobyte/pyrmax

pyrmax

Декодер/кодировщик кадров беспроводного протокола Ubiquiti AirMAX; разбор pcap-файлов и живых захватов, обнаружение устройств, сканирование на уязвимые прошивки, формирование повреждённых пакетов и эмуляция целей AirMAX AC/M.

Репозиторий
312 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

pyrmax

Декодер и энкодер для кадров wire-протокола Ubiquiti AirMAX, покрывающий как серию AC (прошивка WA), так и серию M (прошивки XW/XM).

  • Декодирование незашифрованных внешних заголовков выполняется с помощью схем Kaitai Struct в каталоге ksy/. Полезная нагрузка AC payload (зависящая от версии, переключается по msg_type, с XOR-снятием маски для deauth) написана вручную в ac.py — эта логика не помещается в parse-only Kaitai.
  • Кодирование написано вручную и зеркалирует путь декодирования поле-в-поле.

Статус

ВариантДекодированиеКодированиеИтерация по pcap
AC✅ все 5 типов сообщений (beacon, assoc req/resp, probe req, deauth)✅ байт-в-байт обратная операция + билдеры + seal✅
Mчастично (9 документированных байт; остальное как unknown_rest)✅ round-trip документированной головы + unknown_rest✅
IE Routerboard.com (компаньон для M)✅ имя устройства + список sub-IEn/a✅

Формат wire AC соответствует docs/ac_wire_format.md ([P]-подтверждено против ubnt_poll_host.ko). Все многобайтовые целые AC — big-endian.

TODO

  • pyrmax.ac.encode(AcPacket) -> bytes — написанная вручную байт-в-байт обратная операция к decode() (+ seal(), to_ie() и конструкторы build_*).
  • pyrmax.m.encode(MPacket) -> bytes — то же для M (+ build_m, seal, to_ie).
  • Точно определить поля AC [open] — точную битовую карту cap_flags, mixed_mode, / (assoc_req), / (assoc_resp), а также deauth (извлекается, но его ключ ещё не ревёрс-инженерен, поэтому проверить невозможно). См. §11-§12.

Командная строка

Пакет поставляется с CLI, управляемым через подкоманды. Запуск: python -m pyrmax COMMAND ....``` usage: python -m pyrmax [-h] [--version] COMMAND ...

COMMAND parse Print each AirMAX frame in detail. discover Summarize devices observed in the capture. scan Live-scan for AirMAX devices and flag vulnerable firmware. emulate Emulate AirMAX AC/M devices (fake targets for scanners).

root@kitploit:~
`parse` и `discover` принимают **либо** файл pcap/pcapng (позиционный аргумент)
**либо** живой беспроводной интерфейс через `-i / --iface IFACE`. Эти два
варианта взаимоисключающие. `scan` принимает те же опции источника (плюс
режим `--active`, который применяется только к живому интерфейсу); `emulate`
работает только с живым интерфейсом.```sh
python -m pyrmax parse     capture.pcap          # offline
python -m pyrmax discover  capture.pcap

sudo python -m pyrmax parse     -i wlan0mon      # live (needs root)
sudo python -m pyrmax discover  -i wlan0mon

Захват в реальном времени предполагает, что интерфейс уже находится в режиме монитора на нужном канале — pyrmax не настраивает ни то, ни другое. Для этого требуется дополнительная опция [live] (pip install pyrmax[live]), которая подтягивает pcapy-ng. Нажмите Ctrl-C для остановки: parse сообщает, сколько кадров он получил; discover выводит агрегированную сводку устройств при выходе.

Коды выхода (общие для обеих команд и обоих режимов источников): 0 при успехе (включая «нет кадров AirMAX» — допустимый результат), 1 для ошибок формата захвата (неверный тип канального уровня, повреждённый файл, невозможно открыть интерфейс), 2 для отсутствующего файла или недопустимых аргументов источника.

parse — покадровый дамп```sh

python -m pyrmax parse capture.pcap

root@kitploit:~
Каждый управляющий кадр 802.11, содержащий вендорный IE AirMAX, формирует один
блок: пакет AC, пакет M и любой сопутствующий IE Routerboard.com, найденный
в том же кадре.```
Found 1 AirMAX frame(s) in capture.pcap: 0 AC, 1 M (1 with Routerboard companion).

=== Frame #0  [M]  ts=1765494974.955358 ===
  802.11   src=04:18:d6:0e:0c:42  dst=24:a4:3c:88:d8:22  bssid=04:18:d6:0e:0c:42
  AirMAX M
    version      15
    msg_type     BEACON  (raw=1)
    src_mac      04:18:d6:0e:0c:42
    enable       1
    unknown_rest b700000000000000000000040418d60e0c420000000000  (23B)
  Routerboard.com IE
    oui_type     0
    unknown      0000
    device_name  'AP Sur HY1315'
    sub_ie       subtype=1  (30B) 040000001f660902ff0f4150205375722048593133313500000000000000

Тот же однопроходный обходчик предоставляется программно как pyrmax.pcap.iter_airmax(path) — он возвращает по одному AirmaxRecord(meta, ac, m, routerboard) для каждого кадра с AirMAX, так что вам не нужно сопоставлять IE M и Routerboard вручную.

discover — сводка по устройствам```sh

python -m pyrmax discover capture.pcap

root@kitploit:~
Кадры группируются по MAC-адресу источника 802.11, пиры накапливаются, а
наблюдения AC payload / M payload / имени устройства Routerboard сводятся в
единый блок для каждого устройства.```
2 device(s) observed in capture.pcap across 12 AirMAX frame(s).

  24:5a:4c:44:57:fd  (AC)
    radioname    'LB1'
    ssid         'labalUBI2'
    ac_msg_types BEACON
    ac_version   9
    cap_flags    0x0000003e
    mixed_mode   0
    frames       8
    first seen   1767046123.708745
    last seen    1767046129.012448
    peers        (broadcast only)

  04:18:d6:0e:0c:42  (M)
    device_name  'AP Sur HY1315'
    msg_types    BEACON
    m_version    15
    m_enable     1
    frames       4
    first seen   1765494974.955358
    last seen    1765494980.341110
    peers        24:a4:3c:88:d8:22

Та же агрегация также является публичной функцией:```python from pyrmax.devices import summarize from pyrmax.pcap import iter_airmax

devices = summarize(iter_airmax("capture.pcap")) for mac, dev in devices.items(): print(mac.hex(":"), dev.device_name or dev.radioname, dev.peers)

root@kitploit:~
## Usage

### Decode a single AirMAX AC message

The decoder expects the bytes of the 802.11 Vendor Specific IE **starting at
the OUI** — the IE wrapper (Element ID `0xDD` + Length) must already be
stripped. `src_mac` / `dst_mac` are lifted from the outer 802.11 frame's
SA / DA.

## Использование

### Декодирование одного сообщения AirMAX AC

Декодер ожидает байты Vendor Specific IE стандарта 802.11, **начиная
с OUI** — обёртка IE (Element ID `0xDD` + Length) уже должна быть
удалена. `src_mac` / `dst_mac` берутся из SA / DA внешнего кадра 802.11.```python
from pyrmax import ac

packet = ac.decode(
    data,                              # bytes starting at b"\x00\x27\x22"
    src_mac="aa:bb:cc:dd:ee:ff",       # accepts str ("aa:bb:..." or "aa-bb-..."
                                       # or "aabbcc...") and raw 6-byte bytes
    dst_mac="ff:ff:ff:ff:ff:ff",       # optional — defaults to broadcast
)

packet.msg_type          # <MsgType.BEACON: 1>
packet.version           # 9 (the wire-format epoch / version gate)
packet.src_mac           # b'\xaa\xbb\xcc\xdd\xee\xff'  (integrity-checked)
packet.radioname         # "lab-rx-1"   (convenience prop, delegates to body)
packet.ssid              # "NetA"
packet.cap_flags         # 0x3e  (None for msg types that have no cap_flags)

# The per-message-type fields live on packet.body, one of:
#   BeaconBody | AssocReqBody | AssocRespBody | ProbeReqBody | DeauthBody
body = packet.body
if isinstance(body, ac.BeaconBody):
    body.mac_0c          # the radio's own MAC / BSSID
    body.cap_flags       # u32 capability bitfield (§11)
    body.mixed_mode      # u32 [open]

msg_type является одним из BEACON / ASSOC_REQ / ASSOC_RESP / PROBE_REQ / DEAUTH. Хвостовые поля, определяемые версией (field_9c, rssi, fwname, txpower, …) равны None, когда version кадра ниже их порога. Deauth выполняет обратный XOR для src_mac с nonce jiffies перед проверкой целостности и предоставляет 16-байтовый enc_token как непрозрачные байты (его ключ ещё не обращён, поэтому проверить его нельзя).

Обход списка AC TLV

Тела, несущие name-TLV (beacon, assoc_req), сохраняют поток — включая завершающую запись Padding — дословно в body.tlvs. radioname, ssid и fwname предоставляются как удобные свойства пакета; всё остальное остаётся в сыром виде.```python body = packet.body for tlv in getattr(body, "tlvs", ()): if tlv.tag == ac.TlvTag.PADDING: continue print(f"{tlv.tag.name:<10} ({len(tlv.data)} bytes): {tlv.data!r}")

root@kitploit:~
### Декодирование одного сообщения AirMAX M

Та же форма, меньшая поверхность — документированы только 9 байт полезной нагрузки M;
остальное сохраняется без изменений в `unknown_rest`. **Примечание:** полезная нагрузка M
сама по себе не содержит поля SSID — для этого смотрите стандартный IE SSID 802.11
в окружающем beacon или probe response (отображается как
`FrameMeta.ssid` при итерации через `pyrmax.pcap`).```python
from pyrmax import m

packet = m.decode(data, src_mac="aa:bb:cc:dd:ee:ff")

packet.version           # 1
packet.msg_type          # <MsgType.BEACON: 1>
packet.src_mac           # b'\xaa\xbb\xcc\xdd\xee\xff'
packet.enable            # 1
packet.unknown_rest      # b'\xde\xad\xbe\xef...'   # opaque, RE pending

Формирование сообщений (encode)

encode(packet, dst_mac=…) — это побайтно точная инверсия decode — encode(decode(x)) == x для корректно сформированного кадра. Она сериализует тело (повторно применяя версионные проверки и, для deauth, XOR-маску src_mac), дополняет до блока AES, шифрует ключом, производным от packet.src_mac, и выдаёт байты начиная с OUI. Оберните с помощью to_ie(), чтобы получить полный вендорский IE 0xDD.

Конструкторы build_* избавляют от необходимости собирать вложенные тела вручную:```python from pyrmax import ac

A beacon (mac_0c defaults to src_mac; broadcast key, as beacons use)

pkt = ac.build_beacon(src_mac="24:5a:4c:44:57:fd", radioname="LB1", ssid="labalUBI2", cap_flags=0x3e) ie = ac.to_ie(ac.encode(pkt)) # full 802.11 vendor IE, ready to embed

An authenticated deauth — the encoder XOR-masks the src with the jiffies nonce

deauth = ac.build_deauth(src_mac="24:5a:4c:44:57:fd", jiffies_nonce=0xdeadbeef) raw = ac.encode(deauth, dst_mac="24:a4:3c:88:d8:22")

Others: ac.build_assoc_req / build_assoc_resp / build_probe_req, and m.build_m

root@kitploit:~
Для фаззинга / PoC, `seal()` шифрует **произвольный** открытый текст и формирует внешний заголовок — так что вы можете создавать намеренно искажённые полезные нагрузки (поддельный `msg_type`, неверные длины, тела суб-блоков), которые структурированный кодировщик никогда бы не создал:```python
frame = ac.seal(b"\xde\xad\xbe\xef", src_mac="aa:bb:cc:dd:ee:ff",
                dst_mac="ff:ff:ff:ff:ff:ff", msg_type=0xEE)  # zero-padded to 16

Структурированный encode вызывает EncodeError для любых данных, которые нельзя передать по сети (значение TLV > 255 байт, шифротекст ≥ 0x101); seal по замыслу допускает больше.

Потоковая обработка пакетов из pcap или pcapng

pyrmax.pcap находит vendor IEs AirMAX внутри управляющих кадров 802.11, извлекает MAC-адреса из внешнего заголовка 802.11 и передаёт всё в нужный декодер. Как .pcap, так и .pcapng определяются автоматически. Кадры, которые не удаётся декодировать (неверный ключ, искажённые данные, посторонний vendor IE), молча пропускаются — итерация останавливается только по достижении EOF.```python from pyrmax import pcap

for meta, packet in pcap.iter_ac("capture.pcap"): print( f"{meta.timestamp:.3f} " f"{meta.src_mac.hex(':')} → {meta.dst_mac.hex(':')} " f"{packet.msg_type.name:<10} " f"radio={packet.radioname!r} ssid={packet.ssid!r}" )

for meta, packet in pcap.iter_m("capture.pcapng"): print( f"{meta.timestamp:.3f} " f"{packet.msg_type.name:<10} " f"src={packet.src_mac.hex(':')} enable={packet.enable}" )

root@kitploit:~
`meta` — это `FrameMeta(timestamp, src_mac, dst_mac, bssid)`. Извлечение Channel/RSSI
из radiotap находится в списке TODO.

### Извлечение имени устройства из Routerboard.com IE

Кадры AirMAX M почти всегда сопровождаются вендорским IE Mikrotik / Routerboard.com (OUI `00:0C:42`) в том же управляющем кадре 802.11. Его суб-IE subtype-1 содержит имя устройства.```python
from pyrmax import pcap

for meta, packet in pcap.iter_routerboard("capture.pcap"):
    print(f"{meta.src_mac.hex(':')}  →  {packet.device_name!r}")
    # "AP Sur HY1315"

Декодер Routerboard также доступен отдельно — передавайте данные IE, начиная с OUI:```python from pyrmax import routerboard

packet = routerboard.decode(ie_data) packet.device_name # "AP Sur HY1315" packet.sub_ies # tuple of SubIe(subtype, data)

root@kitploit:~
Соотнесите пакеты Routerboard с пакетами M в одном и том же захвате, сопоставляя `meta.timestamp` + `meta.src_mac`.

### `scan` — поиск уязвимых устройств

Сниффит интерфейс в режиме монитора (или pcap-файл) в поисках устройств AirMAX и помечает уязвимые из них. Требует дополнительную зависимость `[scan]` (`scapy`) и, для захвата в реальном времени, права root.```sh
# offline — scan a capture (no root)
python -m pyrmax scan capture.pcap

# live, passive — read versions only from traffic that happens to fly
sudo python -m pyrmax scan -i wlan0mon --channel 36

# live, active — force AirMAX AC APs to disclose their firmware
sudo python -m pyrmax scan -i wlan0mon --channel 36 --active

Версия определяет уязвимость по-разному в зависимости от варианта. Задействованы два номера версии: версия протокола (wire-format), содержащаяся в каждом AirMAX IE (включая маяки), и версия прошивки AC (fwname), которая передаётся только при ассоциации.``` AirMAX AC ──> proto < 9 ? ──yes──────────────┐ │no ├──> VULNERABLE ▼ │ fw <= 8.7.20 ? ──yes───────────┘ ├──no───────> PATCHED └──unknown──> UNDETERMINED

AirMAX M ───> proto < 15 ? ──yes──> VULNERABLE └──no───────────> UNDETERMINED

root@kitploit:~
Поскольку `proto` находится в маяке, **старые** устройства (эпоха AC < 9,
версия M < 15) обнаруживаются **пассивно**. Для вынесения вердикта `PATCHED` для
AC нужна версия прошивки, поэтому требуется либо захваченная ассоциация,
либо `--active` (активное рукопожатие — auth → assoc → чтение `fwname` из assoc-resp
— это полный, побайтово точный обмен станцией Ubiquiti).

Флаги: `--channel N` (зафиксироваться на одном канале, иначе переключаться), `--seconds N`,
`--cutoff X.Y.Z` (AC уязвим, если `fw <= cutoff`, по умолчанию `8.7.20`),
`--src MAC` (источник для активного зондирования, например PTP-пир), `--vuln-only`,
`--no-set-channel`. Код выхода — **3**, если найдено любое уязвимое устройство
(удобно для скриптов), иначе `0`.```
AirMAX: 5 device(s) (3 AC, 2 M), 2 vulnerable (AC fw <= 8.7.20 or protocol version below the fixed epoch).

  1c:6a:1b:00:00:01  AC  VulnAC            ch36   v8.7.19    VULNERABLE     rssi=-40dBm  peers=0
  1c:6a:1b:00:00:04  M   VulnM             ch36   v14        VULNERABLE     rssi=-42dBm  peers=0
  1c:6a:1b:00:00:03  AC  PatchedAC         ch36   v8.7.24    patched        rssi=-41dBm  peers=0
  1c:6a:1b:00:00:02  AC  UndetAC           ch36   epoch9     undetermined   rssi=-41dBm  peers=0
  1c:6a:1b:00:00:05  M   UndetM            ch36   v15        undetermined   rssi=-43dBm  peers=0

emulate — имитация целей AirMAX

Передавайте маячки (beacon) от одного или нескольких поддельных устройств AirMAX AC/M и, для AC, отвечайте на handshake обнаружения, чтобы активный сканер считывал эмулированную версию прошивки. Требуется дополнительный пакет [emulate] (scapy), интерфейс в режиме монитора и root. Полезно для тестирования scan без реального оборудования.```sh sudo python -m pyrmax emulate -i wlan1mon --channel 36
-d ac/8.7.19/VulnAC -d ac/9/UndetAC -d ac/8.7.24/PatchedAC
-d m/14/VulnM -d m/15/UndetM

root@kitploit:~
Каждый `-d` (повторяемый) — это `TYPE/VERSION[/SSID[/MAC]]`, разделённый `/`, поэтому
двоеточия в MAC безопасны:

- `ac/8.7.19` — современный AC, прошивка `8.7.19` (эпоха 9, раскрывает `fwname`)
- `ac/9` — современная эпоха AC, **без** строки прошивки → сканер видит
  `undetermined`
- `ac/7` — **старая** AC, эпоха 7 в формате кадра (< 9) → уязвим, обнаружен по
  маяку
- `m/14` — AirMAX M, версия 14 (< 15) → уязвим
- `m/15` — AirMAX M на исправленной эпохе → undetermined

Без `-d` эмулируется демонстрационный парк. `--no-respond` — только маяки (AC
прошивка тогда не раскроет версию). Версия прошивки AC живёт только в
assoc-resp, поэтому и существует responder.

### Тест обоих вместе на одной машине

`scripts/hwsim_testbed.sh` создаёт два виртуальных радиоустройства через `mac80211_hwsim`
поэтому вы можете запустить `emulate` на одном и `scan` на другом без оборудования:```sh
sudo ./scripts/hwsim_testbed.sh up 36    # prints EMU_IFACE / SCAN_IFACE
# ...run emulate on EMU_IFACE and scan on SCAN_IFACE (two terminals)...
sudo ./scripts/hwsim_testbed.sh down

scripts/demo_5_devices.sh выполняет весь процесс от начала до конца — поднимает радио, эмулирует описанный выше парк из 5 устройств, запускает scan --active и завершает работу:```sh sudo ./scripts/demo_5_devices.sh 36

root@kitploit:~
### Обработка ошибок

Несоответствия схемы и нарушения целостности вызывают `pyrmax.DecodeError`.
Наиболее частая причина — неправильный ключ (неверные `src_mac` / `dst_mac`,
переданные в `decode()` для данного кадра).```python
from pyrmax import ac, DecodeError

try:
    packet = ac.decode(data, src_mac=src, dst_mac=dst)
except DecodeError as exc:
    print(f"skipping frame: {exc}")

Дополнительные возможности

  • pip install pyrmax[pcap] (или uv sync --extra pcap) — подтягивает dpkt, чтобы pyrmax.pcap.iter_ac(path) / iter_m(path) могли потоково читать пакеты из захватов .pcap или .pcapng (тип канала DLT_IEEE802_11_RADIO). Формат определяется автоматически по магическому числу файла.
  • pip install pyrmax[live] — добавляет pcapy-ng для захвата в реальном времени с беспроводного интерфейса в режиме монитора. Используется флагом CLI -i / --iface и программным генератором pyrmax.pcap.iter_airmax_live(iface).
  • pip install pyrmax[scan] — добавляет scapy для команды scan (перехват/декодирование в реальном времени + активное рукопожатие принудительной ассоциации).

Установите несколько сразу, например: uv sync --extra scan --extra emulate.

Структура```

pyrmax/ ├── ksy/ # Kaitai Struct source schemas │ ├── airmax_ac.ksy # AC cleartext outer header (payload decode is hand-written in ac.py) │ ├── airmax_m.ksy # M outer (OUI marker + encrypted blob) │ ├── airmax_m_payload.ksy # M decrypted payload (9 documented bytes) │ └── routerboard.ksy # Mikrotik / Routerboard.com vendor IE ├── src/pyrmax/ │ ├── init.py │ ├── ac.py # AC decode/encode API + AcPacket dataclass │ ├── m.py # M decode/encode API + MPacket dataclass │ ├── routerboard.py # Routerboard IE decoder + RouterboardPacket │ ├── pcap.py # iter_ac / iter_m / iter_routerboard / iter_airmax / iter_airmax_live │ ├── devices.py # summarize() — per-device aggregation │ ├── vuln.py # firmware-version parse + is_vulnerable() │ ├── scan.py # Scanner — live/pcap discovery + active handshake + vuln verdict │ ├── emulate.py # Emulator — fake AC/M targets (scapy) │ ├── main.py # python -m pyrmax CLI │ ├── exceptions.py │ ├── _crypto.py # AES-128-ECB + HMAC-SHA1 KDF (internal) │ └── _generated/ # kaitai-struct-compiler output (committed) ├── scripts/ │ ├── hwsim_testbed.sh # two virtual radios (mac80211_hwsim) for scan<->emulate │ └── demo_5_devices.sh # end-to-end 5-device emulate + scan demo └── tests/ ├── samples/ # raw frame captures (currently empty) ├── test_ac.py ├── test_m.py ├── test_crypto.py ├── test_pcap.py ├── test_routerboard.py ├── test_devices.py ├── test_cli.py └── test_integration.py # real-capture round-trips

root@kitploit:~
## Разработка```sh
uv sync                    # create .venv and install runtime + dev deps
uv run pytest              # run tests
uv run ruff check          # lint
uv run pyright             # static type check

Configuration lives in pyproject.toml ([tool.pyright]):

  • typeCheckingMode = "basic" — выявляет структурные проблемы без борьбы с границей dpkt / kaitaistruct / pycryptodome (эти пакеты не поставляют заглушки типов).
  • src/pyrmax/_generated/ исключается — файлы, сгенерированные Kaitai, уже содержат # type: ignore и перезаписываются при каждом запуске kaitai-struct-compiler.
  • Границы с dpkt, затрагивающие динамические атрибуты (например, MGMT_Frame.src), преодолеваются с аннотацией Any на локальном связывании, а не разбросанными комментариями ignore.

Перегенерация парсеров Kaitai

Сгенерированные Python-файлы в src/pyrmax/_generated/ сохранены в репозитории, поэтому пакет устанавливается без инструментария Kaitai. Чтобы перегенерировать их после изменения .ksy:```sh kaitai-struct-compiler -t python --outdir src/pyrmax/_generated/ ksy/*.ksy

root@kitploit:~
Скачать инструмент
field_14
field_9c
sta_field_68
ic_6b8
enc_token
docs/ac_wire_format.md
  • Проверить декодеры AC для version < 9 на реальных захватах — билдер TX всегда выдаёт только версию 9, поэтому пути для младших версий (нетегированное имя, отсутствующие хвостовые поля) реализованы по спецификации, но не проверены на проводе.
  • Ревёрс-инжиниринг остальной части полезной нагрузки M (байты 9+ в unknown_rest) — пока непрозрачно.
  • Выводить метаданные radiotap в pcap.FrameMeta: канал, RSSI, скорость. Сейчас заполняются только метка времени/MAC/BSSID.
  • Фикстуры реальных захватов в tests/samples/ — сейчас: airmax_ac_beacon.pcap (1 кадр, beacon) и airmax_m_probe_response.pcap (1 кадр, probe response). Другие варианты (assoc req/resp, многофреймовые захваты) по-прежнему приветствуются.
  • Отправка пакетов — команды scan (активная force-assoc) и emulate внедряются через scapy (экстры [scan] / [emulate]). См. scan.py / emulate.py.
  • pip install pyrmax[emulate] — добавляет scapy для команды emulate (инъекция beacon-кадров + ответ на рукопожатие обнаружения от имени поддельных устройств).