Help us understand the problem. What is going on with this article?

Wiresharkで独自プロトコルの解析

More than 3 years have passed since last update.

Wiresharkで独自プロトコルを解析する

いきさつ

WiresharkではLua言語で記述したファイルをプラグインとして扱うことが出来ます。
業務で端末間の通信が怪しかったので、Wiresharkを使うことになりましたが、単にキャプチャーしただけだとバイナリを脳内解析することになります。ちょっと勘弁ということでプラグインを作ることにしました。Lua言語ってなんちゃら?と思うけど、独自プロトコルを解析するくらいであれば簡単に作ることが出来ました。

前準備

Wiresharkのインストールフォルダにある init.lua の設定を変更します。

  • disable_luaをfalse に設定
  • run_user_scripts_when_superuserをtrueに設定
  • ファイルの最終行に「dofile(DATA_DIR.."foo_protcol.lua")」を追記
init.lua
-- Set disable_lua to true to disable Lua support.
disable_lua = false

if disable_lua then
    return
end

-- If set and we are running with special privileges this setting
-- tells whether scripts other than this one are to be run.
run_user_scripts_when_superuser = true

 
 
 

dofile(DATA_DIR.."console.lua")
--dofile(DATA_DIR.."dtd_gen.lua")
dofile(DATA_DIR.."foo_protcol.lua")

luaファイルの作成

Wiresharkのインストールフォルダにて「foo_protcol.lua」を作成します。
通信電文とかポート番号はフィクションです。

  • le_uint() はリトルエンディアンで展開します。
  • uint() はビッグエンディアンで展開します。
foo_protcol.lua
-- foo protocol example
-- プロトコルの定義
foo_proto = Proto("foo","Foo","Foo protocol")
-- パース用の関数定義
function foo_proto.dissector(buffer,pinfo,tree)
    pinfo.cols.protocol = "Foo"
    local subtree = tree:add(foo_proto,buffer(),"Foo Protocol Data")
    subtree:add(buffer(0,1),"cmd_id: " .. buffer(0,1):le_uint())
    subtree:add(buffer(1,1),"req_id: " .. buffer(1,1):le_uint())
    subtree:add(buffer(2,6),"date: " .. buffer(2,1):le_uint() .. "/" .. buffer(3,1):le_uint() .. "/"  .. buffer(4,1):le_uint() .. " "  .. buffer(5,1):le_uint() .. ":"  .. buffer(6,1):le_uint() .. ":"  .. buffer(7,1):le_uint())
    subtree:add(buffer(8,2),"seq_no: " .. buffer(8,2):le_uint())
    subtree:add(buffer(10,1),"rty_cnt: " .. buffer(10,1):le_uint())
end
-- tcp.portテーブルのロード
tcp_table = DissectorTable.get("tcp.port")
-- ポート9999番とプロトコルの紐付けをする
tcp_table:add(9999,foo_proto)

Wiresharkで独自プロトコルが表示された :blush:

Wiresharkを起動して、目的の通信履歴の詳細を表示すると独自プロトコルの解析が表示されます。(画像はじゃっかん加工しています)

foo_protocol.png

電文サイズが足らない場合や分割パケットの場合

TCPのパケットは、一つのパケットで複数の電文が入っていたり、一回で全ての電文が到達しなかったりします。上記の foo_proto.dissector では、そのあたりの考慮を加えます。

まずは電文解析自体のロジックを分けます。

function disp_foo(buffer,pinfo,tree)
    pinfo.cols.protocol = "Foo"
    local subtree = tree:add(foo_proto,buffer(),"Foo Protocol Data")
    subtree:add(buffer(0,1),"cmd_id: " .. buffer(0,1):le_uint())
    subtree:add(buffer(1,1),"req_id: " .. buffer(1,1):le_uint())
    subtree:add(buffer(2,6),"date: " .. buffer(2,1):le_uint() .. "/" .. buffer(3,1):le_uint() .. "/"  .. buffer(4,1):le_uint() .. " "  .. buffer(5,1):le_uint() .. ":"  .. buffer(6,1):le_uint() .. ":"  .. buffer(7,1):le_uint())
    subtree:add(buffer(8,2),"seq_no: " .. buffer(8,2):le_uint())
    subtree:add(buffer(10,1),"rty_cnt: " .. buffer(10,1):le_uint())
end

dissector自体では、受け取ったバッファーのサイズを見て、後続のパケットとアペンドしたり、複数電文を処理するためのループを行うようにします。

function foo_proto.dissector(buffer,pinfo,tree)
    local HEADDER_LENGTH = 17
    if buffer:len() < HEADDER_LENGTH then
        -- ヘッダ部に必要なデータ長が無いので、後続のパケットにアペンドする.
        pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
        return buffer:len() - HEADDER_LENGTH
    end

    while buffer:len() > 0 do
        local length = buffer(13,2):le_uint()
        if (buffer:len() - HEADDER_LENGTH) < length then
            -- データ部に必要なデータ長が無いので、後続のパケットにアペンドする.
            pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
            return buffer:len() - length + HEADDER_LENGTH
        end

        disp_foo(buffer,pinfo,tree)
        if (buffer:len() - (HEADDER_LENGTH + length)) == 0 then
            break
        end
        buffer = buffer:range(HEADDER_LENGTH + length)
    end
end

一つのパケットに複数の電文がある場合はこのように。

packet1.png

分割パケットの場合はこのようになります。

packet2.png

itage
ITAGEは「IT」のAGENCYになることを夢、目標として進化、変化していきます。「It’s It Agency」
http://www.itage.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした