
Postdissector de Wireshark baseado em Lua que descriptografa e analisa IEs de fornecedor 802.11 da Ubiquiti AirMAX/RouterBoard em campos filtráveis.
Um dissector Wireshark/tshark para Information Elements proprietários da Ubiquiti AirMAX (AC + M) e da Mikrotik / RouterBoard, escrito em Lua.
É a contraparte over-the-wire do pyrmax: a lógica de decodificação espelha esse pacote Python campo por campo. O formato de pacote AC foi obtido por engenharia reversa do firmware AirMAX AC; os layouts de M e RouterBoard vêm de notas publicadas anteriormente sobre o vendor IE AirMAX-M mais antigo.
O AirMAX trafega dentro de IEs vendor-specific do 802.11 (tag 221). O Wireshark já parseia o quadro 802.11 e mostra o vendor IE como um blob opaco; o wiremax pega esse blob, o descriptografa (AES-128-ECB, chave derivada dos MACs do quadro) e renderiza uma subárvore parseada e filtrável.
Tag: Vendor Specific: Ubiquiti Inc (dissector 802.11 integrado)
AirMAX AC (Vendor Specific IE) ← adicionado pelo wiremax
Flags: 0x02 ( .... ..1. = Encrypted: True )
Message Type: Beacon (1)
Encrypted Length: 48
[Decrypted payload (AES-128-ECB)]
[AES Key …: 1f162a13… (dst=broadcast)]
Version: 9
Source MAC: 24:5a:4c:44:57:fd
Radio MAC (mac_0c): 24:5a:4c:44:57:fd
Capability Flags: 0x0000003e
Mixed Mode: 0
Radioname: LB1
SSID: labalUBI2
TLV: Radioname (1), len 3
TLV: SSID (2), len 9
TLV: Padding (0)
O layout descriptografado depende do Message Type: beacons carregam mac_0c / cap_flags /
mixed_mode + TLVs de nome (acima); assoc req/resp carregam chainmasks, cap_flags e
campos finais controlados por versão (field_9c, rssi, fwname, txpower); probe req é
apenas cabeçalho; deauth carrega um nonce de jiffies e um token de autenticação opaco (e seu
MAC de origem é mascarado com XOR, que o wiremax desmascara).
| Variante | Cobertura |
|---|---|
| AirMAX AC | cabeçalho externo + cabeçalho comum descriptografado (version + src_mac) + corpo por tipo de mensagem e controlado por versão (beacon, assoc req/resp, probe req, deauth) + TLVs de nome |
| AirMAX M | casca externa + 9 bytes documentados descriptografados (version, msg_type, src_mac, enable) + restante bruto |
| RouterBoard (Mikrotik) | OUI/tipo + sub-IEs + nome do dispositivo (texto claro) |
Regiões de bytes não documentadas são exibidas brutas (Unknown [n:len]), nunca inventadas —
a mesma disciplina do pyrmax e da base de conhecimento ac/.
Um pós-dissector (não substitui o dissector 802.11 integrado, ele roda depois dele). Para cada quadro, ele:
wlan.tag.oui além de wlan.sa / wlan.da via extratores Field;00:27:22), M (00:15:6d) ou RouterBoard (00:0c:42)
— para AC/M também exige o tipo de OUI FF FF FF, pois 00:15:6d é
compartilhado com a Mikrotik e com outro IE da Ubiquiti que aparece no mesmo
quadro;AES-128-ECB, chave = HMAC-SHA1(dst_mac, src_mac)[:16], tentando primeiro o
destino 802.11 capturado e depois recorrendo ao broadcast (quadros de identidade usam
a chave de broadcast mesmo quando unicast) — o vencedor é aquele cujo MAC de origem
embutido no payload descriptografado corresponde à origem 802.11;A criptografia (SHA-1, HMAC-SHA1, descriptografia AES-128) é Lua pura autossuficiente — o Wireshark não expõe API de criptografia para Lua. Os payloads têm poucos blocos de 16 bytes, então desempenho é irrelevante. A chave é derivada de MACs públicos; portanto, isto é ofuscação, não segurança.
Uso único (sem instalação):
tshark -X lua_script:airmax.lua -r capture.pcap -V
wireshark -X lua_script:airmax.lua capture.pcap
Persistente (GUI do Wireshark + tshark): coloque a pasta inteira wiremax/ em um
diretório de Plugins Lua Pessoais. O caminho exato é mostrado no Wireshark em
Ajuda ▸ Sobre o Wireshark ▸ Pastas ▸ Personal Lua Plugins; os padrões são:
| SO | Caminho padrão de Personal Lua Plugins |
|---|---|
| Linux | ~/.local/lib/wireshark/plugins/ |
| macOS | ~/.local/lib/wireshark/plugins/ (ou ~/.config/wireshark/plugins/) |
| Windows | %APPDATA%\Wireshark\plugins\ |
Um symlink é ideal durante iterações — as edições são aplicadas ao recarregar
(Ctrl+Shift+L) sem etapa de cópia:
ln -s "$PWD" ~/.local/lib/wireshark/plugins/wiremax
O Wireshark carrega recursivamente cada .lua sob a pasta de plugins; os submódulos
em wsairmax/ são módulos simples (inofensivos se carregados isoladamente) e
test/selftest.lua não faz nada dentro do Wireshark.
| Filtro | Significado |
|---|---|
airmax.ac.msg_type | tipo de mensagem: 1 Beacon, 2 Assoc Req, 3 Assoc Resp, 4 Probe Req, 0xC Deauth |
airmax.ac.flags.encrypted | bit de criptografia (0x02) |
airmax.ac.version | versão do formato descriptografado (o portão; TX emite 9) |
airmax.ac.src_mac | MAC de origem do cabeçalho descriptografado (deauth o desmascara) |
airmax.ac.mac_0c | MAC de rádio do beacon (BSSID) |
airmax.ac.cap_flags + airmax.ac.cap_flags.chanbw/.high_density/.auth_deauth/.compat_11ax | campo de bits de capacidade (§11) |
airmax.ac.radioname, airmax.ac.ssid, airmax.ac.fwname | strings de nome / firmware do AC |
airmax.ac.jiffies_nonce, airmax.ac.enc_token | nonce de deauth + token de autenticação opaco |
airmax.ac.tlv.tag / .len / .data | varredura bruta de TLV |
airmax.m.version, airmax.m.msg_type, airmax.m.src_mac, airmax.m.enable | campos documentados do M |
airmax.m.unknown_rest | cauda não documentada do M |
airmax.rb.device_name | nome do dispositivo RouterBoard |
airmax.ac.key / airmax.m.key | chave AES derivada (gerada, para verificação) |
Exemplos:
tshark -r cap.pcap -Y 'airmax.ac.ssid' -T fields -e wlan.sa -e airmax.ac.ssid
tshark -r cap.pcap -Y 'airmax.m.msg_type == 1' -T fields -e airmax.m.src_mac
tshark -r cap.pcap -Y 'airmax.rb.device_name' -T fields -e airmax.rb.device_name
As capturas devem ser em modo monitor 802.11 (radiotap); os quadros de gerenciamento que carregam os IEs (beacon / probe response / assoc) não são criptografados na camada 802.11 — apenas o payload AirMAX dentro do IE é envolvido em AES, e o wiremax o desenvelopa.
test/selftest.lua executa a criptografia e os decodificadores sob o interpretador
Lua 5.4 autônomo (sem Wireshark), verificando vetores de referência além de vetores
SHA-1 / HMAC RFC-2202 padrão:
lua test/selftest.lua # a partir deste diretório
Ponta a ponta contra uma captura real (o pyrmax inclui pcaps de exemplo em
tests/samples/):
tshark -X lua_script:airmax.lua -r airmax_ac_beacon.pcap -V
tshark -X lua_script:airmax.lua -r airmax_m_probe_response.pcap -V
wiremax/
├── airmax.lua # entrada do Wireshark: ProtoFields + pós-dissector + árvore
├── wsairmax/ # módulos Lua puros (sem dependência do Wireshark)
│ ├── util.lua # auxiliares hex / MAC
│ ├── sha1.lua # SHA-1 + HMAC-SHA1
│ ├── aes.lua # descriptografia AES-128 ECB
│ ├── crypto.lua # derivação de chave + descriptografia (espelha pyrmax/_crypto.py)
│ ├── ac.lua # decodificador AirMAX AC (ksy externo: airmax_ac; payload escrito manualmente conforme 09b)
│ ├── m.lua # decodificador AirMAX M (ksy: airmax_m[_payload])
│ └── routerboard.lua # decodificador RouterBoard (ksy: routerboard)
├── test/selftest.lua # harness de teste Lua autônomo
└── README.md