
Постдиссектор Wireshark на Lua, который расшифровывает и разбирает вендорные IE 802.11 Ubiquiti AirMAX/RouterBoard в фильтруемые поля.
Диссектор Wireshark/tshark для вендорских информационных элементов Ubiquiti AirMAX (AC + M) и сопутствующих Mikrotik / RouterBoard, написанный на Lua.
Это аналог pyrmax для работы с трафиком: логика декодирования повторяет тот Python-пакет поле-в-поле. Формат AC-пакетов был восстановлен из бинарника прошивки AirMAX AC; раскладки M и RouterBoard взяты из ранее опубликованных заметок о более старом вендорском IE AirMAX-M.
AirMAX передаётся внутри 802.11 вендор-специфичных IE (тег 221). Wireshark уже разбирает 802.11-кадр и показывает вендорский IE как непрозрачный blob; wiremax берёт этот blob, расшифровывает его (AES-128-ECB, ключ выводится из MAC-адресов кадра) и отрисовывает разобранное, фильтруемое поддерево.
Tag: Vendor Specific: Ubiquiti Inc (built-in 802.11 dissector)
AirMAX AC (Vendor Specific IE) ← added by 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)
Расшифрованная структура зависит от Message Type: beacon-кадры несут mac_0c / cap_flags / mixed_mode + TLV имён (выше); assoc req/resp несут chainmask, cap_flags и хвостовые поля, зависящие от версии (field_9c, rssi, fwname, txpower); probe req состоит только из заголовка; deauth несёт nonce на основе jiffies и непрозрачный auth-токен (а его исходный MAC замаскирован XOR, и wiremax эту маску снимает).
| Вариант | Покрытие |
|---|---|
| AirMAX AC | внешний заголовок + расшифрованная общая шапка (version + src_mac) + тело, зависящее от типа сообщения и версии (beacon, assoc req/resp, probe req, deauth) + TLV имён |
| AirMAX M | внешняя оболочка + расшифрованные 9 документированных байт (version, msg_type, src_mac, enable) + сырой остаток |
| RouterBoard (Mikrotik) | OUI/type + суб-IE + имя устройства (открытым текстом) |
Незадокументированные области байт показываются как есть (Unknown [n:len]), никогда не выдумываются — та же дисциплина, что и в pyrmax, и в базе знаний ac/.
Постдиссектор (он не заменяет встроенный диссектор 802.11, а выполняется после него). Для каждого кадра он:
wlan.tag.oui, а также wlan.sa / wlan.da через экстракторы Field;00:27:22), M (00:15:6d) или RouterBoard (00:0c:42) — для AC/M дополнительно требуется тип OUI FF FF FF, потому что 00:15:6d используется совместно с Mikrotik и ещё одним IE Ubiquiti, который появляется в том же кадре;AES-128-ECB с ключом = HMAC-SHA1(dst_mac, src_mac)[:16], сначала пробуя захваченный адрес назначения 802.11 и откатываясь к broadcast (identity-кадры используют broadcast-ключ, даже если они unicast) — побеждает тот ключ, у которого встроенный исходный MAC расшифрованной нагрузки совпадает с источником 802.11;Криптография (SHA-1, HMAC-SHA1, расшифровка AES-128) — это самодостаточный чистый Lua: Wireshark не предоставляет Lua никакого крипто-API. Нагрузки — это несколько 16-байтовых блоков, так что производительность не имеет значения. Ключ выводится из публичных MAC-адресов, так что это обфускация, а не безопасность.
Разовый запуск (без установки):
tshark -X lua_script:airmax.lua -r capture.pcap -V
wireshark -X lua_script:airmax.lua capture.pcap
Постоянная установка (GUI Wireshark + tshark): поместите всю папку wiremax/ в каталог Personal Lua Plugins. Точный путь показан в Wireshark в разделе Help ▸ About Wireshark ▸ Folders ▸ Personal Lua Plugins; значения по умолчанию:
| OS | Путь Personal Lua Plugins по умолчанию |
|---|---|
| Linux | ~/.local/lib/wireshark/plugins/ |
| macOS | ~/.local/lib/wireshark/plugins/ (или ~/.config/wireshark/plugins/) |
| Windows | %APPDATA%\Wireshark\plugins\ |
Симлинк идеален во время итераций — правки подхватываются при перезагрузке (Ctrl+Shift+L) без шага копирования:
ln -s "$PWD" ~/.local/lib/wireshark/plugins/wiremax
Wireshark рекурсивно загружает все .lua-файлы из папки плагинов; подмодули в wsairmax/ — обычные модули (безвредны при загрузке по отдельности), а test/selftest.lua внутри Wireshark ничего не делает.
| Фильтр | Значение |
|---|---|
airmax.ac.msg_type | тип сообщения: 1 Beacon, 2 Assoc Req, 3 Assoc Resp, 4 Probe Req, 0xC Deauth |
airmax.ac.flags.encrypted | бит шифрования (0x02) |
airmax.ac.version | версия расшифрованного формата (гейт; TX передаёт 9) |
airmax.ac.src_mac | исходный MAC из расшифрованной шапки (для deauth маска снимается) |
airmax.ac.mac_0c | радио-MAC beacon (BSSID) |
airmax.ac.cap_flags + airmax.ac.cap_flags.chanbw/.high_density/.auth_deauth/.compat_11ax | битовое поле возможностей (§11) |
airmax.ac.radioname, airmax.ac.ssid, airmax.ac.fwname | строки имени/прошивки AC |
airmax.ac.jiffies_nonce, airmax.ac.enc_token | nonce deauth + непрозрачный auth-токен |
airmax.ac.tlv.tag / .len / .data | сырое перечисление TLV |
airmax.m.version, airmax.m.msg_type, airmax.m.src_mac, airmax.m.enable | документированные поля M |
airmax.m.unknown_rest | незадокументированный хвост M |
airmax.rb.device_name | имя устройства RouterBoard |
airmax.ac.key / airmax.m.key | выведенный AES-ключ (генерируется для проверки) |
Примеры:
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
Захваты должны быть в режиме монитора 802.11 (radiotap); управляющие кадры, несущие IE (beacon / probe response / assoc), не зашифрованы на уровне 802.11 — только нагрузка AirMAX внутри IE обёрнута в AES, и wiremax её разворачивает.
test/selftest.lua запускает криптографию и декодеры в автономном интерпретаторе Lua 5.4 (без Wireshark), сверяясь с эталонными векторами, а также стандартными контрольными векторами SHA-1 / HMAC из RFC-2202:
lua test/selftest.lua # from this directory
Сквозная проверка на реальном захвате (в pyrmax есть примеры pcap в 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 # Wireshark entry: ProtoFields + postdissector + tree
├── wsairmax/ # pure-Lua modules (no Wireshark dependency)
│ ├── util.lua # hex / MAC helpers
│ ├── sha1.lua # SHA-1 + HMAC-SHA1
│ ├── aes.lua # AES-128 ECB decrypt
│ ├── crypto.lua # key derivation + decrypt (mirrors pyrmax/_crypto.py)
│ ├── ac.lua # AirMAX AC decoder (outer ksy: airmax_ac; payload hand-written per 09b)
│ ├── m.lua # AirMAX M decoder (ksy: airmax_m[_payload])
│ └── routerboard.lua # RouterBoard decoder (ksy: routerboard)
├── test/selftest.lua # standalone-Lua test harness
└── README.md