Altro giro, altro dissector per Wireshark in Lua…
Salve gente.
Nota: è stata rilasciata una versione migliorativa, v1.1!
Ogni tanto per lavoro mi capita di tanto in tanto di dover mettere le mani su un qualche protocollo XML-based. Il fido Wireshark, al solito, si rivela molto utile per cercare di capire il flusso dei dati e, soprattutto, come sono strutturati.
A essere onesti Wireshark include già un suo dissector XML che supporta molti sotto-formati, ma io ne volevo uno personale/personalizzabile che in qualche modo ricostruisse principalmente/solamente la struttura ad albero dei tag XML.
Così me ne sono scritto uno piccolo in Lua, di esempio…
Si tratta di un esempio minimale (come quello precedente), rapido ma non troppo, non validante e che si “fida” piuttosto ingenuamente della corretta struttura XML dei file letti (di solito i protocolli che tratto sono semplici e senza sbavature: in altri termini i file sono sempre almeno well formed).
Per evitare problemi col dissector XML “standard” di Wireshark, ho ribattezzato il mio “xmlstruct“.
Funzionamento
Il funzionamento è abbastanza semplice:
- si definisce il protocollo per il il dissector: per semplicità verranno intercettate le richieste sulla porta 80 TCP;
- viene letto un pacchetto e si cerca di estrarne i tag XML tramite pattern matching. A ciascuno dei tag estratti viene assegnato un numero di livello nell’albero XML, numero che verrà memorizzato in una apposita Lua table di supporto;
- tale procedura consentirà quindi di mostrare i vari tag estratti nel Packet Details pane (il pannello in basso), organizzati gerarchicamente tramite opportuna indentazione.
Devo ammettere che Lua è estremamente limitato quanto a funzioni di libreria ma nonostante ciò è davvero (davvero) un gran bel linguaggio.
Il dissector…dissezionato!
Per usarlo, al solito, basta:
- creare/copiare il seguente file xmlstruct.lua nella directory di installazione di Wireshark;
- modificare il file init.lua, anch’esso presente nella directory di installazione di Wireshark, abilitando il supporto a Lua e aggiungendo il riferimento al file xmlstruct.lua;
- eseguire Wireshark impostando xmlstruct come filtro per i pacchetti.
Nota: sfortunatamente WordPress non supporta ancora Lua quindi niente sintassi correttamente colorata. Sorry…
--[[
FILE: xml.lua
AUTHOR: Gian Paolo "JP" Ghilardi
LICENSE: released under the terms of GPL v2.0 ("only")
PURPOSE: example of a simple dissector that extracts XML structure
from packets (for Wireshark, written in Lua)
VERSION: 1.0 <<< Now superseded by v1.1 >>>
TESTED ON:
- Wireshark 1.0.6 on Windows XP SP2 x86-32, Lua 5.1
- Wireshark 1.0.5 on MacOSX 10.5.6 PPC, Lua 5.1
REFERENCES:
[1]: https://www.darkcornersoftware.com/confluence/display/open/Helen+Wireshark+Dissector+Plugin
[2]: http://www.wireshark.org/docs/wsug_html_chunked/wsluarm.html
[3]: http://www.lua.org/manual/5.1/manual.html
[4]: http://wiki.wireshark.org/Lua/Examples
]]--
-- protocol declaration
xml_proto = Proto("xmlstruct","XML","Simple XML Dissector (Structure Extractor)")
function xml_proto.dissector(buffer, pinfo, tree)
local data -- packet contents (string format)
local treeItem -- used in Packet Details pane
local tagsTreeItem -- used in Packet Details pane
local tagLevels = {} -- lua table (used to keep tag levels)
local tagCurrLvl = 0; -- current tag level (for indentation)
local cleanTag -- current tag (just the tag name!)
local sPos -- start position (for pattern matching)
local ePos -- end position (for pattern matching)
local tmp -- temp string (for pattern matching)
pinfo.cols.protocol = "XML"
data = buffer():string() -- string version of the buffer (that is a TvbRange)
treeItem = tree:add(xml_proto, buffer(), "Simple XML Dissector")
treeItem:add(buffer(), "FRAME LEN : " .. tostring(pinfo.caplen))
treeItem:add(buffer(), "IP SRC : " .. tostring(pinfo.src))
treeItem:add(buffer(), "IP DEST : " .. tostring(pinfo.dst))
tagsTreeItem = treeItem:add(buffer(), "XML TAGS :")
while true do
sPos, ePos, rawTag = data:find("<([^<>]+)>", ePos)
if sPos == nil or ePos == nil or rawTag == nil then
break
end
if rawTag:sub(1,1) == "/" then -- if it's a closing tag...
tagCurrLvl = tagCurrLvl - 1
else -- if it's an opening tag...
tagCurrLvl = tagCurrLvl + 1
end
cleanTag = rawTag:match("(%w+)")
if tagLevels[cleanTag] == nil then -- if the tag isn't in the table...
tagLevels[cleanTag] = tagCurrLvl -- ... insert it with its tree level
end
tmp = string.rep(" ", tagLevels[cleanTag]) -- indentation proportional to level
tagsTreeItem:add(buffer(sPos-1, ePos-sPos+1), tmp .. "<" .. rawTag .. ">")
end
end
-- get the tcp.port table
tcp_xml_table = DissectorTable.get("tcp.port")
-- register our protocol for handling port 80 in the TCP table
tcp_xml_table:add(80, xml_proto)
Il dissector dal vivo
Il dissector httpex in funzione in MacOSX Leopard 10.5.6 per PPC (Wireshark compilato ed installato tramite Fink). Come test ho scelto questa pagina di esempio da w3schools.com.
Ciau!




Bel lavoro ! Non ho mai fatto tante cose in Lua, ma ne apprezzo la facilità con cui è possibile utilizzarlo come linguaggio di scripting all’interno di tante applicazioni..
Molte grazie. Anche io non ci avevo fatto granchè, almeno fino ad ora…
Suppongo, da quel che vedo in giro, che presto o tardi la conoscenza di Lua sarà un requisito minimo per molte offerte di lavoro per programmatori (attualmente “counts as a plus”). ^^
Curiosità: quanto hai impiegato, complessivamente, a realizzare il dissector ?
Il codice che vedi è tratto da quello di un dissector un più complesso che ho sviluppato per lavoro e che mi è tornato incredibilmente utile in fase di debug…
Ieri sera, non contento della qualità di questa porzione (usavo un algoritmo a due passi), l’ho riscritto a casa in un’oretta e mezza (ero ispirato ^^’ ).
Considera che sapevo già dove mettere le mani, nel senso che conoscevo già un poco Lua e le relative API di Wireshark…
Complessivamente, sommando anche il tempo a lavoro, ti direi 3+ ore in tutto per il solo codice che vedi qui. Sviluppare un equivalente in C di questo dissector richiede senza dubbio molto più tempo, per cui direi che me la sono cavata ragionevolmente in/con poco.
PS: per velocizzare lo sviluppo ed i test in Windows, ho usato un bel pacchetto all-in-one che include l’interprete Lua ed una versione appositamente “customizzata” dell’ottimo editor SciTE.
Ottimo, quindi può valere la pena di investire qualche ora per guadagnare in capacità di analisi / debug ..
Direi decisamente di sì. Nel mio caso le ore investite per imparare a usare Lua in Wireshark mi hanno risparmiato molte più ore e forse addirittura qualche giorno per capire e usare vari protocolli che seguo…
Non hai idea di quanto sia comodo e proficuo controllare il flusso dei pacchetti in transito (ed ispezionarne il contenuto in tempo reale!) senza dover interrompere ogni 2×3 Visual Studio per debuggare e/o riempire tonnellate di log da analizzare in seguito e per giunta manualmente!
PS: mi hai dato l’idea per un post… Grazie!
Non ti preoccupare, ho un’idea ben precisa di cosa significa poter controllare il flusso dei pacchetti, soprattutto quando si comunica con ‘oggetti’ sviluppati da terzi !
Comunque il tuo post conferma quanto ho in mente già da tempo: il tempo impiegato nello sviluppo di strumenti di supporto (che siano scripts, dissectors, piccole applicazioni di simulazione, ecc.) può avere un grande valore di ritorno nel progetto, sia in termini di tempo risparmiato che di qualità del risultato.
Esattamente.
Se non hai nulla in contrario, stavo giusto scrivendo un post sul tema (e citerei i tuoi commenti
).
Allora faccio auto-promozione* con un post vecchio, datato e scritto male.
.. sicuramente farai di meglio .. !!
*puoi anche rimuovere questo commento se ritieni opportuno
Ottimo post, lo citerò di fisso!
PS: non rimuovo il tuo commento perchè è terribilmente valido (non so se riuscirò a far di meglio eh).