Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
pyrmax — Décodeur/encodeur pour les trames du protocole sans fil Ubiquiti AirMAX ; analyse des captures pcap/en direct, découverte de périphériques, recherche de firmware vulnérables, fabrication de paquets malformés et émulation de cibles AirMAX AC/M. | Kitploit
Outils/GitHubGitHub/infobyte/pyrmax
Scanners de VulnérabilitésRétro-ingénierieFuzzingSécurité RéseauSécurité Sans Fil
GitHubinfobyte/pyrmax

pyrmax

Décodeur/encodeur pour les trames du protocole sans fil Ubiquiti AirMAX ; analyse des captures pcap/en direct, découverte de périphériques, recherche de firmware vulnérables, fabrication de paquets malformés et émulation de cibles AirMAX AC/M.

Voir le dépôt
3il y a 11 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

pyrmax

Décodeur et encodeur pour les trames du protocole de communication Ubiquiti AirMAX, couvrant les séries AC (firmware WA) et M (firmware XW/XM).

  • Décodage des en-têtes externes en clair est piloté par les schémas Kaitai Struct sous ksy/. La charge utile AC (sélectionnée selon la version, commutée sur msg_type, avec le démasquage XOR du deauth) est écrite à la main dans ac.py — cette logique ne convient pas à un Kaitai de simple parsing.
  • Encodage est écrit à la main pour refléter le chemin de décodage champ pour champ.

Statut

VarianteDécodageEncodageItération pcap
AC✅ les 5 types de message (beacon, assoc req/resp, probe req, deauth)✅ inverse octet-exact + constructeurs + seal✅
Mpartiel (9 octets documentés ; le reste sous unknown_rest)✅ aller-retour de l'en-tête documenté + unknown_rest✅
IE Routerboard.com (compagnon de M)✅ nom du périphérique + liste des sous-IEn/a✅

Le format de transmission AC suit docs/ac_wire_format.md ([P]-confirmé par rapport à ubnt_poll_host.ko). Tous les entiers multi-octets AC sont en big-endian.

TODO

  • pyrmax.ac.encode(AcPacket) -> bytes — inverse octet-exact écrit à la main de decode() (+ seal(), to_ie() et les constructeurs build_*).
  • pyrmax.m.encode(MPacket) -> bytes — idem pour M (+ build_m, seal, to_ie).
  • Déterminer précisément les champs AC [open] — cap_flags carte de bits exacte, mixed_mode, / (assoc_req), / (assoc_resp), et le du deauth (extractible mais sa clé n'a pas encore été rétro-conçue, donc il ne peut pas être vérifié). Voir §11-§12.

Outil en ligne de commande

Le paquet est fourni avec une CLI basée sur des sous-commandes. Lancez-la avec 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` et `discover` acceptent **soit** un fichier pcap/pcapng (positionnel)
**soit** une interface sans fil en direct via `-i / --iface IFACE`. Les deux sont
mutuellement exclusifs. `scan` accepte les mêmes options de source (plus un
mode `--active` qui ne s'applique qu'à une interface en direct) ; `emulate` est
uniquement en direct.```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

La capture en direct suppose que l'interface est déjà en mode monitor sur le canal d'intérêt — pyrmax ne le configure pas non plus. Elle nécessite l'extension optionnelle [live] (pip install pyrmax[live]) qui installe pcapy-ng. Appuyez sur Ctrl-C pour arrêter : parse indique combien de trames ont été diffusées ; discover affiche le résumé agrégé des appareils à la sortie.

Codes de sortie (partagés par les deux commandes et les deux modes de source) : 0 en cas de succès (y compris « aucune trame AirMAX » — un résultat valide), 1 pour les erreurs de format de capture (mauvais type de liaison, fichier corrompu, impossible d'ouvrir l'interface), 2 pour fichier manquant ou arguments de source invalides.

parse — vidage trame par trame```sh

python -m pyrmax parse capture.pcap

root@kitploit:~
Chaque trame de gestion 802.11 transportant un IE de fournisseur AirMAX produit un
bloc : paquet AC, paquet M, et tout IE compagnon Routerboard.com trouvé dans la même trame.```
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

Le même analyseur en une seule passe est exposé programmatiquement via pyrmax.pcap.iter_airmax(path) — il génère un AirmaxRecord(meta, ac, m, routerboard) pour chaque trame contenant de l'AirMAX, vous n'avez donc pas besoin de corréler à la main les IE M et Routerboard.

discover — résumé de l'appareil```sh

python -m pyrmax discover capture.pcap

root@kitploit:~
Les trames sont regroupées par MAC source 802.11, les pairs s'accumulent, et les observations AC payload / M payload / nom d'appareil Routerboard se regroupent en un seul bloc par appareil.```
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

La même agrégation est aussi une fonction publique :```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:~
## Utilisation

### Décoder un seul message AirMAX AC

Le décodeur attend les octets de l’IE Vendor Specific 802.11 **en partant de
l’OUI** — l’enveloppe IE (Element ID `0xDD` + Longueur) doit déjà être
retirée. `src_mac` / `dst_mac` sont extraits du SA / DA de la trame 802.11
externe.```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 est l'une de BEACON / ASSOC_REQ / ASSOC_RESP / PROBE_REQ / DEAUTH. Les champs de fin conditionnés par la version (field_9c, rssi, fwname, txpower, …) sont None lorsque la version de la trame est inférieure à leur seuil. Deauth annule le XOR de src_mac avec le nonce jiffies avant la vérification d'intégrité et expose le enc_token de 16 octets comme des octets opaques (sa clé n'est pas encore inversée, il ne peut donc pas être vérifié).

Parcourir la liste des TLV AC

Les corps qui portent des TLV de nom (beacon, assoc_req) préservent le flux — y compris l'entrée Padding de fin — tel quel sur body.tlvs. radioname, ssid et fwname sont exposés comme des propriétés de commodité sur le paquet ; tout le reste demeure brut.```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:~
### Décodez un message AirMAX M

Même forme, surface plus petite — seuls 9 octets de la charge utile M sont documentés ;
le reste est préservé tel quel dans `unknown_rest`. **Remarque :** la charge utile M
elle-même n'a pas de champ SSID — pour cela, reportez-vous à l'IE SSID 802.11 standard
sur la balise ou la réponse de sonde environnante (affiché sous
`FrameMeta.ssid` lors de l'itération via `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

Créer des messages (encode)

encode(packet, dst_mac=…) est l'inverse exact au niveau octet de decode — encode(decode(x)) == x pour une trame bien formée. Il sérialise le corps (ré-applique les gardes de version et, pour deauth, le masque XOR src_mac), complète le bloc AES, chiffre avec la clé dérivée de packet.src_mac, et émet les octets à partir d'OUI. Enveloppez avec to_ie() pour une IE vendor complète 0xDD.

Les constructeurs build_* vous évitent d'assembler les corps imbriqués à la main :```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:~
Pour le fuzzing / les PoC, `seal()` chiffre un texte clair **arbitraire** et construit l'en-tête externe — vous pouvez ainsi créer des payloads délibérément malformés (`msg_type` erroné, longueurs incorrectes, corps de sous-blocs) que l'encodeur structuré ne produirait jamais :```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

Structured encode lève EncodeError sur tout ce qui ne peut pas être transmis sur le fil (une valeur TLV > 255 octets, un texte chiffré ≥ 0x101) ; seal est permissif par conception.

Diffuser les paquets d'un pcap ou pcapng

pyrmax.pcap trouve les IE de fournisseur AirMAX dans les trames de gestion 802.11, extrait les MAC de l'en-tête 802.11 externe, et transmet le tout au bon décodeur. Les fichiers .pcap et .pcapng sont détectés automatiquement. Les trames qui échouent au décodage (mauvaise clé, corrompues, IE de fournisseur sans rapport) sont ignorées silencieusement — l'itération ne s'arrête qu'à la fin du fichier (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` est une `FrameMeta(timestamp, src_mac, dst_mac, bssid)`. L'extraction canal/RSSI
à partir du radiotap figure sur la liste TODO.

### Récupérer le nom de l'appareil à partir d'une IE Routerboard.com

Les trames AirMAX M sont presque toujours accompagnées d'une IE de fabricant Mikrotik /
Routerboard.com (OUI `00:0C:42`) dans la même trame de gestion 802.11.
Sa sous-IE de sous-type 1 porte le nom de l'appareil.```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"

Le décodeur Routerboard est également disponible en version autonome — passez les données IE à partir de l'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:~
Corrélerez les paquets Routerboard avec les paquets M dans la même capture en
faisant correspondre `meta.timestamp` + `meta.src_mac`.

### `scan` — trouver les appareils vulnérables

Sniffez une interface en mode moniteur (ou un pcap) pour les appareils AirMAX et signalez
ceux qui sont vulnérables. Nécessite l'extra `[scan]` (`scapy`) et, pour une capture en direct,
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

La version détermine différemment la vulnérabilité selon la variante. Deux numéros de version sont impliqués : la version de protocole wire-format portée dans chaque IE AirMAX (y compris les balises), et la version du firmware AC (fwname) qui ne circule que dans l'échange d'association.``` 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:~
Parce que `proto` est dans le beacon, les appareils **anciens** (AC epoch < 9, version M < 15) sont détectés **passivement**. Pour atteindre un verdict `PATCHED` pour AC, il faut la version du firmware, donc soit une association capturée, soit `--active` (le handshake actif — auth → assoc → lire le `fwname` de l'assoc-resp — est un échange de station Ubiquiti complet et fidèle à l'octet).

Options : `--channel N` (verrouiller un canal, sinon sauter), `--seconds N`,
`--cutoff X.Y.Z` (vulnérable à AC si `fw <= cutoff`, défaut `8.7.20`),
`--src MAC` (source pour la sonde active, ex. le pair PTP), `--vuln-only`,
`--no-set-channel`. Le code de sortie est **3** quand un appareil vulnérable est trouvé (pratique pour les scripts), sinon `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 — fausses cibles AirMAX

Émettez des balises en tant qu'un ou plusieurs faux appareils AirMAX AC/M et, pour AC, répondez au handshake de découverte afin qu'un scanner actif lise la version du firmware émulé. Nécessite l'extra [emulate] (scapy), une interface en mode monitor, et root. Utile pour tester scan sans matériel réel.```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:~
Chaque `-d` (répétable) est `TYPE/VERSION[/SSID[/MAC]]`, séparé par `/` afin que les
deux-points du MAC soient sans danger :

- `ac/8.7.19` — AC moderne, firmware `8.7.19` (epoch 9, révèle `fwname`)
- `ac/9` — epoch de l'AC moderne, **aucune** chaîne de firmware → le scanner voit
  `undetermined`
- `ac/7` — **ancien** AC, epoch au format filaire 7 (< 9) → vulnérable, détecté à partir de
  la balise
- `m/14` — AirMAX M, version 14 (< 15) → vulnérable
- `m/15` — AirMAX M à l'epoch corrigé → indéterminé

Sans `-d`, une flotte de démonstration est émulée. Avec `--no-respond`, uniquement des balises (le
firmware AC ne divulguera alors rien). La version du firmware AC ne se trouve que dans la
`assoc-resp`, c'est pourquoi le répondeur existe.

### Tester les deux ensemble sur une même machine

`scripts/hwsim_testbed.sh` crée deux radios virtuelles via `mac80211_hwsim`
afin que vous puissiez exécuter `emulate` sur l'une et `scan` sur l'autre sans matériel :```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 fait tout de bout en bout — démarre les radios, émule la flotte de 5 appareils ci-dessus, exécute scan --active, puis arrête tout :```sh sudo ./scripts/demo_5_devices.sh 36

root@kitploit:~
### Gestion des erreurs

Les incohérences de schéma et les échecs d'intégrité lèvent `pyrmax.DecodeError`. La
cause la plus fréquente est une mauvaise clé (mauvais `src_mac` / `dst_mac` fourni à
`decode()` pour la trame concernée).```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}")

Extras optionnels

  • pip install pyrmax[pcap] (ou uv sync --extra pcap) — installe dpkt pour que pyrmax.pcap.iter_ac(path) / iter_m(path) puissent diffuser les paquets depuis des captures .pcap ou .pcapng (type de liaison DLT_IEEE802_11_RADIO). Le format est détecté automatiquement à partir du nombre magique du fichier.
  • pip install pyrmax[live] — ajoute pcapy-ng pour la capture en direct depuis une interface sans fil en mode moniteur. Utilisé par l'option -i / --iface de la CLI et par le générateur programmatique pyrmax.pcap.iter_airmax_live(iface).
  • pip install pyrmax[scan] — ajoute scapy pour la commande scan (sniff/décodage en direct + la poignée de main force-assoc active).

Installez plusieurs d'un coup, p.ex. uv sync --extra scan --extra emulate.

Structure```

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:~
## Développement```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

La configuration se trouve dans pyproject.toml ([tool.pyright]):

  • typeCheckingMode = "basic" — détecte les problèmes structurels sans se heurter à la frontière dpkt / kaitaistruct / pycryptodome (ces paquets ne fournissent pas de stubs de types).
  • src/pyrmax/_generated/ est exclu — les fichiers générés par Kaitai portent déjà # type: ignore et sont écrasés à chaque exécution de kaitai-struct-compiler.
  • Les frontières vers dpkt qui touchent des attributs dynamiques (par ex. MGMT_Frame.src) sont franchies avec une annotation Any sur la liaison locale plutôt qu'avec des commentaires ignore dispersés.

Régénérer les parseurs Kaitai

Les fichiers Python générés sous src/pyrmax/_generated/ sont versionnés afin que le paquet s'installe sans chaîne d'outils Kaitai. Pour régénérer après modification d'un .ksy :```sh kaitai-struct-compiler -t python --outdir src/pyrmax/_generated/ ksy/*.ksy

root@kitploit:~
Télécharger l’outil
field_14
field_9c
sta_field_68
ic_6b8
enc_token
docs/ac_wire_format.md
  • Vérifier les décodeurs AC version < 9 sur des captures réelles — le constructeur TX n'émet jamais que la version 9, donc les chemins de version inférieure (nom non balisé, champs de fin manquants) sont implémentés d'après la spécification mais non vérifiés sur le fil.
  • Rétro-concevoir le reste de la charge utile M (octets 9 et plus dans unknown_rest) — actuellement opaque.
  • Exposer les métadonnées radiotap sur pcap.FrameMeta : canal, RSSI, débit. Actuellement, seuls l'horodatage, les MAC et le BSSID sont renseignés.
  • Captures réelles de test dans tests/samples/ — actuellement : airmax_ac_beacon.pcap (1 trame, beacon) et airmax_m_probe_response.pcap (1 trame, réponse de probe). D'autres variantes (assoc req/resp, captures multi-trames) sont toujours les bienvenues.
  • Envoi de paquets — les commandes scan (force-association active) et emulate injectent via scapy (les extras [scan] / [emulate]). Voir scan.py / emulate.py.
  • pip install pyrmax[emulate] — ajoute scapy pour la commande emulate (injecter des balises + répondre à la poignée de main de découverte en tant que faux appareils).