Lua で dissector を記述するときの Tips

このページには Wireshark で 独自プロトコルの dissector を Lua で記述するための Tips が書いてあります。

Wireshark の dissector はすべて C で書かれております。それに対して Lua は dissector のプロトタイピング用に使う言語として位置づけられています。

ドキュメント #

Wireshark における Lua に関するドキュメント #

Lua の日本語ドキュメント #

下記のリンクは Wireshark とは関係はありませんが、Wireshark を通じて Lua を初めて使う人が多いのではないかと思いますので、Lua に関するドキュメントを載せてあります。

実践編 #

設定 (Preferences) #

プロトコルによってはパケット解析をするために事前情報が必要となるものがあります。 Wireshark では Edit -> Preferences -> Protocols から各種プロトコルの設定として、事前情報を与えることができます。 ここでは独自プロトコルの dissector を記述する際にこの設定の使い方を触れます。

設定 (Preferences) のドキュメント #

Wireshark の公式ドキュメントにおいて、下記の節で 設定 (Preference) についての説明があります。

  • 11.6.5.5 proto.prefs: Proto オブジェクトは主にプロトコルを分析するために使いますが、設定を登録するためにも使います。その設定を登録するテーブルが Proto.prefs です。
    • 11.6.5.6 proto.prefs_changed: 設定が変更されたときに呼び出される関数です。
  • 11.6.4 Prefs: Proto.prefs の説明がこの説に書かれています。
  • 11.6.3 Pref: 設定で使う変数オブジェクトです。

設定 (Preferences) の使い方 #

使い方の参考としてテストコードである dissector.lua を例に見ていきます。

Proto オブジェクトには、設定を登録するための Proto.prefs というテーブル(連想配列・ハッシュ)が用意されております。 Proto.prefs テーブルには Pref オブジェクトを登録します。

dissector.lua での Proto オブジェクトは dns で定義されています。下記のコードで dns.prefsPref オブジェクトを登録しています。

dns.prefs.debug = Pref.enum("Debug", default_settings.debug_level,
                            "The debug printing level", debug_pref_enum)

dns.prefs.port  = Pref.uint("Port number", default_settings.port,
                            "The UDP port number for MyDNS")

dns.prefs.heur  = Pref.bool("Heuristic enabled", default_settings.heur_enabled,
                            "Whether heuristic dissection is enabled or not")

Proto.prefs テーブルに Pref オブジェクトを登録するだけで、Wireshark 上でプロトコルの設定が表示されるようになります。

Proto.prefs に登録された変数は Wireshark の設定から変更が可能で、Wireshark を再起動しても変更した値を保持し続けます。 dissector.lua では設定の値に基づいて dissector の振る舞いを変えています。 具体的には Proto.prefs_changed() を使って default_settings というローカル変数を上書きして dissector でその変数を見て振る舞いを変えています。

-- a function for handling prefs being changed
function dns.prefs_changed()
    dprint2("prefs_changed called")

    default_settings.debug_level  = dns.prefs.debug
    reset_debug_level()

    default_settings.heur_enabled = dns.prefs.heur

    if default_settings.port ~= dns.prefs.port then
        -- remove old one, if not 0
        if default_settings.port ~= 0 then
            dprint2("removing MyDNS from port",default_settings.port)
            DissectorTable.get("udp.port"):remove(default_settings.port, dns)
        end
        -- set our new default
        default_settings.port = dns.prefs.port
        -- add new one, if not 0
        if default_settings.port ~= 0 then
            dprint2("adding MyDNS to port",default_settings.port)
            DissectorTable.get("udp.port"):add(default_settings.port, dns)
        end
    end
end