Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Wiresharkの 
解析プラグインを作る 
@unkn0wnbit 
2014/9/29 #ssmjp 2014/09
Agenda 
 Wiresharkとは 
 解析プラグインを作るには 
 解析対象プロトコルを定義 
 解析スクリプトの作成 
 既存の解析プラグインの拡張 
 ビット演算 
 おまけ 
2
01. WIRESHARKとは 
3
4 
Wiresharkとは 
 パケットキャプチャツール 
 標準で多彩なプロトコルを解析できるプラ 
グインが付属 
 独自のプロトコルは解析できない 
 独自のプロトコルを解析する場合 
1. 人間デコーダになる 
2. 解析用の...
5 
Wiresharkのパケット処理の流れ 
0100111010101010101110 ネットワーク上を流れるパケット 
キャプチャフィルタ 
解析プラグイン 
ディスプレイフィルタ 
Wireshark画面出力 
キャプチャするパケット...
02. 解析プラグインを作るには 
6
7 
解析プラグインを作るには 
 方法は2つ 
 C/C++言語で作成 
 Wiresharkに組み込まれたLuaスクリプト言 
語で作成 
 今回はLuaで作成します 
面倒そう… 
きっとお手軽
8 
Luaを使う準備(1/2) 
 WiresharkでLuaが有効か確認 
 コンパイル時にLuaの使用を指定 
 公式版Win/Macバイナリともにデフォルトで有効 
 Linuxはディストリビューションによるかも 
http:/...
9 
Luaを使う準備(2/2) 
 最新バージョン(1.12.1)はデフォルトで使用可能 
 古い設定ファイルを使い回している場合は確認 
 init.lua 内の以下の行を確認 
 disable_lua = true; の行をfa...
10 
動作確認(1/2) 
 Tools – Lua – Evaluate 
 Evaluate Luaダイアログ
11 
動作確認(2/2) 
 ダイアログにプログラム入力 
local tw = TextWindow.new("Test Program"); 
tw:set("Hello World!") 
 Evaluateボタンを押すと…
12 
Luaスクリプト使用方法(1/2) 
 通常はスクリプトをファイルに保存して、 
Wiresharkの起動時に読み込ませる。 
wireshark.exe -X lua_script:C:/wireshark_plugins/hoge...
13 
Luaスクリプト使用方法(2/2) 
 毎回同じスクリプトを使う場合 
 init.luaに以下を追記 
 dofile(”C:/wireshark_plugins/hoge.lua”) 
 Global configurati...
03. 解析対象プロトコルを定義 
14
15 
解析対象プロトコルを定義(1/4) 
 解析対象とする簡単なプロトコルを定義 
 乱数文字列生成プロトコル 
 クライアントはサーバに任意の長さの乱数を要 
求する 
 サーバは指定された長さの乱数を文字列として、 
クライアン...
16 
解析対象プロトコルを定義(2/4) 
 パケットフォーマット 
 Command Code 
 データ長:1バイト 
 Request or Response 
 Data Length 
 データ長:2バイト 
 Req...
17 
解析対象プロトコルを定義(3/4) 
 Command Code 
 Request 
 0x01 
 Response 
 0x51 
 不明なCommand Codeが要求されたとき 
 0xFFを返す
18 
解析対象プロトコルを定義(4/4) 
 UDP版およびTCP版を実装 
 MTUを超えるデータをやりとりする場合、 
TCPの使用を想定。 
 使用ポート番号:10000
04. 解析スクリプトの作成 
19
20 
Wiresharkで見てみる(UDP版) 
Response 
Packet List 
Packet Details 
Packet Bytes
宣言したプロトコルで使用 
するフィールドを定義 
21 
解析スクリプト(UDP版) 
do 
udp_rngp_proto = Proto("RNGP_UDP", "Random Number Generater Protocol (UDP...
22 
解析スクリプト(UDP版) 
Response
23 
Wiresharkで見てみる(TCP版) 
Response
宣言したプロトコルで使用 
するフィールドを定義 
24 
解析スクリプト(TCP版) 
do 
tcp_rngp_proto = Proto("RNGP_TCP", "Random Number Generater Protocol (TCP...
25 
解析スクリプト(TCP版) 
 TCPセグメント再構築イメージ 
1パケット目2パケット目 
1パケット目でdissectorに渡されるbuffer内容 
必要なデータ長に満たないので、pinfo.desegment_lenに 
DE...
26 
解析スクリプト(TCP版) 
Response
05. 既存の解析プラグインの拡張 
27
28 
ところで… 
 独自のプロトコルの解析より、既存の解 
析プラグインを拡張したい、と思うことの 
方が多いかもしれません。 
 この機能が使えます。 
 postdissector 
 chained dissector 
 ...
29 
postdissector 
 postdissectorとは 
 dissectorが呼び出された後に呼び出される 
dissector 
 同じパケットを複数のdissectorで処理する。 
 種類に関係なく、全てのパケッ...
30 
postdissectorのイメージ 
dissector 
ARP IP 
TCP UDP 
postdissector 
… 
… 
25 80 53 68 … 
各dissectorで処理が行われた後に 
必ず呼び出されるdiss...
31 
postdissector例 
TCPの場合に送信元/先IPアドレス 
とポートの組み合わせをPacket 
Detailsに追加。 
http://wiki.wireshark.org/Lua/Dissectors より 
-- tr...
32 
postdissector例実行結果 
定義したプロトコルやフィールドはディス 
プレイフィルタとして指定できる。 
Packet Detailsにも情報を追加できる。 
この例では、TCPの場合のみTrivial 
Protocol ...
33 
chained dissector 
 chained dissectorとは 
 あるdissectorが呼び出された後に続けて呼 
び出されるdissector 
 同じパケットを複数のdissectorで処理する 
 特定...
34 
chained dissectorのイメージ 
dissector 
ARP IP 
TCP UDP 
chained 
dissector 
… 
… 
25 80 53 68 … 
特定のdissectorに紐付けられて 
呼び出さ...
35 
chained dissector例 
do 
local http_suspicious_proto = Proto("http_suspicious", "Suspicious HTTP Traffic") 
local F_sus...
36 
chained dissector例実行結果 
定義したプロトコルやフィールドはディス 
プレイフィルタとして指定できる。 
Packet Detailsにも情報を追加できる。 
この例では、疑わしいHTTPのリクエストに 
Suspi...
37 
TAP 
 TAPとは 
 主に統計情報収集用として使用される。 
 全てのパケットに対して呼び出される。 
 フィルタを設定して、該当するパケットのみを処 
理することも可能。 
 キャプチャフィルタの影響は受ける。 
 ...
38 
TAPのイメージ 
0100111010101010101110 
キャプチャフィルタ 
解析プラグイン 
ディスプレイフィルタ 
Wireshark画面出力 
TAP 
dissectorとは独立して 
パケットを解析。
39 
TAP例 
do 
local function menuable_tap() 
-- Declare the window we will use 
local tw = TextWindow.new("Address Counter...
40 
TAP例実行結果 
Tools – Test – Packetsが追加される。 
メニューを実行して、パケットキャプチャを 
行うと、送信元または送信先ごとのパケット 
数がウィンドウに表示される。 
Wiresharkの名前解決を有効...
06. ビット演算 
41
42 
Luaのビット演算 
 Lua 5.2でビット演算がサポート 
 公式版WindowsバイナリはLua 5.2組み込み 
 公式版MacバイナリはLua 5.1組み込み 
 いずれも、Wireshark 1.12.1で確認 
...
Luaビット演算 
 API 
 bit32.arshift, bit32.band, bit32.bnot, bit32.bor, bit32.btest, 
bit32.bxor, bit32.bextract, bit32.lrota...
44 
まとめ 
 パケット単位の解析 
 今まさにキャプチャしたパケットのみが解析対象 
 過去のパケットの情報は取得できない 
 1つのプロトコルにつき、1つのdissector 
 単一のdissectorでRequestとRe...
45 
参考 
 Wireshark 
 Wireshark User’s Guide 
 https://www.wireshark.org/docs/wsug_html_chunked/wsluarm.html 
 https://...
46 
Q & A
おまけ 
 Lua以外のバインディング言語 
 SSL復号 
 サーバの証明書を使う 
 ブラウザの暗号鍵を使う 
47 
今回やりません。 
ググって!
Lua以外のバインディング 
おまけ1 
48
Lua以外のバインディング言語 
 Aboutダイアログをよくみると… 
49
Pythonバインディングの実際のところ 
 withoutなのでWireshark wikiを見てみる 
http://wiki.wireshark.org/Python より 
50
pyresharkについて 
 LuaのようにTCPやUDPのポート毎に 
dissectorを登録するようなAPIが用意さ 
れていない。 
 tcp_table = DissectorTable.get("tcp.port") 
 t...
ブラウザ側の暗号鍵を使ったSSL復号 
おまけ2 
52
WiresharkでSSL復号 
 よく見かける方法として、サーバのSSL秘密鍵を 
Wiresharkに設定して、パケットキャプチャの解析を行う 
手順が解説されている。 
 自分がSSL秘密鍵を持っていない場合、通信内容が分 
からない...
ブラウザの暗号鍵で復号 
 SSLKEYLOGFILE環境変数を設定する 
 SSLKEYLOGFILE=/path/to/sslkeylog.txt 
 Wiresharkで以下を設定 
 Edit – Preferences – P...
SSLKEYLOGFILEフォーマット 
 CLIENT_RANDOM <space> <64 bytes of hex encoded 
client_random> <space> <96 bytes of hex encoded mas...
使用ブラウザの制限 
 SSLKEYLOGFILE環境変数を見てログファイルを作る 
のは、NSS(Network Security Services)ライブラリであ 
るため、同様の手順が取れるのは同ライブラリを使用 
するブラウザ、ツール...
参考 
 pyreshark 
 https://github.com/ashdnazg/pyreshark 
 Psst. Your Browser Knows All Your Secrets. 
 https://isc.sans...
58 
Q & A
Upcoming SlideShare
Loading in …5
×

Wiresharkの解析プラグインを作る ssmjp 201409

23,054 views

Published on

How to make a Wireshark plugin to dissect an original protocol with Lua.
And, How to decrypt SSL (using PFS (ex. ECDHE) key exchange) with Wireshark.

Published in: Internet
  • Writing good research paper is quite easy and very difficult simultaneously. It depends on the individual skill set also. You can get help from research paper writing. Check out, please ⇒ www.HelpWriting.net ⇐
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Did u try to use external powers for studying? Like ⇒ www.HelpWriting.net ⇐ ? They helped me a lot once.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • There is a useful site for you that will help you to write a perfect and valuable essay and so on. Check out, please ⇒ www.WritePaper.info ⇐
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❶❶❶ http://bit.ly/369VOVb ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/369VOVb ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Wiresharkの解析プラグインを作る ssmjp 201409

  1. 1. Wiresharkの 解析プラグインを作る @unkn0wnbit 2014/9/29 #ssmjp 2014/09
  2. 2. Agenda  Wiresharkとは  解析プラグインを作るには  解析対象プロトコルを定義  解析スクリプトの作成  既存の解析プラグインの拡張  ビット演算  おまけ 2
  3. 3. 01. WIRESHARKとは 3
  4. 4. 4 Wiresharkとは  パケットキャプチャツール  標準で多彩なプロトコルを解析できるプラ グインが付属  独自のプロトコルは解析できない  独自のプロトコルを解析する場合 1. 人間デコーダになる 2. 解析用のプラグインを書く
  5. 5. 5 Wiresharkのパケット処理の流れ 0100111010101010101110 ネットワーク上を流れるパケット キャプチャフィルタ 解析プラグイン ディスプレイフィルタ Wireshark画面出力 キャプチャするパケットをフィルタリング パケットを解析 表示するパケットをフィルタリング 解析した結果を表示
  6. 6. 02. 解析プラグインを作るには 6
  7. 7. 7 解析プラグインを作るには  方法は2つ  C/C++言語で作成  Wiresharkに組み込まれたLuaスクリプト言 語で作成  今回はLuaで作成します 面倒そう… きっとお手軽
  8. 8. 8 Luaを使う準備(1/2)  WiresharkでLuaが有効か確認  コンパイル時にLuaの使用を指定  公式版Win/Macバイナリともにデフォルトで有効  Linuxはディストリビューションによるかも http://wiki.wireshark.org/Lua より
  9. 9. 9 Luaを使う準備(2/2)  最新バージョン(1.12.1)はデフォルトで使用可能  古い設定ファイルを使い回している場合は確認  init.lua 内の以下の行を確認  disable_lua = true; の行をfalse に変更  Windows  C:Program FilesWiresharkinit.lua  Mac  /Applications/Wireshark.app/Contents/Resources/share/wire shark/init.lua  Linux (Debian 7)  /usr/share/wireshark/init.lua
  10. 10. 10 動作確認(1/2)  Tools – Lua – Evaluate  Evaluate Luaダイアログ
  11. 11. 11 動作確認(2/2)  ダイアログにプログラム入力 local tw = TextWindow.new("Test Program"); tw:set("Hello World!")  Evaluateボタンを押すと…
  12. 12. 12 Luaスクリプト使用方法(1/2)  通常はスクリプトをファイルに保存して、 Wiresharkの起動時に読み込ませる。 wireshark.exe -X lua_script:C:/wireshark_plugins/hoge.lua  -X オプションは複数回指定可能  ディレクトリのデリミタは“” or “/”  tsharkも同様(GUIのAPIは使えない)  tshark版Hello World print("Hello World!")
  13. 13. 13 Luaスクリプト使用方法(2/2)  毎回同じスクリプトを使う場合  init.luaに以下を追記  dofile(”C:/wireshark_plugins/hoge.lua”)  Global configuration  C:Program FilesWiresharkinit.lua  Personal configuration  C:Users<user_name>AppDataRoamingWiresharki nit.lua  各フォルダの確認方法  Help – About Wireshark – Folders
  14. 14. 03. 解析対象プロトコルを定義 14
  15. 15. 15 解析対象プロトコルを定義(1/4)  解析対象とする簡単なプロトコルを定義  乱数文字列生成プロトコル  クライアントはサーバに任意の長さの乱数を要 求する  サーバは指定された長さの乱数を文字列として、 クライアントに返す
  16. 16. 16 解析対象プロトコルを定義(2/4)  パケットフォーマット  Command Code  データ長:1バイト  Request or Response  Data Length  データ長:2バイト  Request時:要求するデータ長を指定  Response時:Data部の長さを指定  Data  データ長:Data Lengthで指定されたバイト数  Request時:存在しない  Response時:応答する実データ  データの並びはビッグエンディアン bits 8 1 Command Code Data Length Data
  17. 17. 17 解析対象プロトコルを定義(3/4)  Command Code  Request  0x01  Response  0x51  不明なCommand Codeが要求されたとき  0xFFを返す
  18. 18. 18 解析対象プロトコルを定義(4/4)  UDP版およびTCP版を実装  MTUを超えるデータをやりとりする場合、 TCPの使用を想定。  使用ポート番号:10000
  19. 19. 04. 解析スクリプトの作成 19
  20. 20. 20 Wiresharkで見てみる(UDP版) Response Packet List Packet Details Packet Bytes
  21. 21. 宣言したプロトコルで使用 するフィールドを定義 21 解析スクリプト(UDP版) do udp_rngp_proto = Proto("RNGP_UDP", "Random Number Generater Protocol (UDP)") command_prtf = ProtoField.new("RNGP command", "rngp_udp.command", ftypes.UINT8) length_prtf = ProtoField.new("RNGP length", "rngp_udp.length", ftypes.UINT16) random_prtf = ProtoField.new("RNGP Random Numbers", "rngp_udp.random", ftypes.STRING) udp_rngp_proto.fields = {command_prtf, length_prtf, random_prtf} function udp_rngp_proto.dissector(buffer, pinfo, tree) local command_names = { [0x01] = "Request Random Numbers", [0x51] = "Response Random Numbers", [0xFF] = "Unknown Request/Response Command", } local command = buffer(0,1):uint() local length = buffer(1,2):uint() local subtree = tree:add(udp_rngp_proto, "Random Number Generater Protocol Data") subtree:add_packet_field(command_prtf, buffer:range(0,1), ENC_ASCII, "Command:", string.format("0x%02x", command), command_names[command]) subtree:add_packet_field(length_prtf, buffer(1,2), ENC_ASCII, "Length:", length) if command >= 0x51 and command ~= 0xFF then disp_data(command, buffer(3, length):tvb(), subtree) end pinfo.cols.protocol = "RNGP(UDP)" if command_names[command] == nil then pinfo.cols.info = "Malformed Request/Response Command" else pinfo.cols.info = command_names[command] end end udp_table = DissectorTable.get("udp.port") udp_table:add(10000, udp_rngp_proto) end function disp_data(command, buffer, tree) if command == 0x51 then tree:add_packet_field(random_prtf, buffer(0), ENC_ASCII) end end 新しいプロトコルを宣言 定義したdissectorを 10000/udpに登録 buffer : Wiresharkから渡されるパケットのバッファ(tvb) pinfo : Packet List情報 tree : Packet Details内ツリー情報 buffer(X, Y):uint() bufferのXバイト目からYバイトを unsigned intとして切り出す tree:add(), add_packet_field() Packet Details内のツリーに アイテムを追加 Packet ListのProtocolカラムと Infoカラムの内容を設定 dissector(パケットを解析する関数)を定義 (パケットを受け取るたびに呼び出される)
  22. 22. 22 解析スクリプト(UDP版) Response
  23. 23. 23 Wiresharkで見てみる(TCP版) Response
  24. 24. 宣言したプロトコルで使用 するフィールドを定義 24 解析スクリプト(TCP版) do tcp_rngp_proto = Proto("RNGP_TCP", "Random Number Generater Protocol (TCP)") command_prtf = ProtoField.new("RNGP command", "rngp_tcp.command", ftypes.UINT8) length_prtf = ProtoField.new("RNGP length", "rngp_tcp.length", ftypes.UINT16) random_prtf = ProtoField.new("RNGP Random Numbers", "rngp_tcp.random", ftypes.STRING) tcp_rngp_proto.fields = {command_prtf, length_prtf, random_prtf} function tcp_rngp_proto.dissector(buffer, pinfo, tree) local command_names = { [0x01] = "Request Random Numbers", [0x51] = "Response Random Numbers", [0xFF] = "Unknown Request/Response Command", } local command = buffer(0,1):uint() local length = buffer(1,2):uint() if command == 0x51 and buffer:len() < (3 + length) then pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT return buffer:len() - (3 + length) end local subtree = tree:add(tcp_rngp_proto, "Random Number Generater Protocol Data") subtree:add_packet_field(command_prtf, buffer:range(0,1), ENC_ASCII, "Command:", string.format("0x%02x", command), command_names[command]) subtree:add_packet_field(length_prtf, buffer(1,2), ENC_ASCII, "Length:", length) if command >= 0x51 and command ~= 0xFF then disp_data(command, buffer(3, length):tvb(), subtree) end pinfo.cols.protocol = "RNGP(TCP)" if command_names[command] == nil then pinfo.cols.info = "Malformed Request/Response Command" else pinfo.cols.info = command_names[command] end return 3 + length end tcp_table = DissectorTable.get("tcp.port") tcp_table:add(10000, tcp_rngp_proto) End function disp_data(command, buffer, tree) if command == 0x51 then tree:add_packet_field(random_prtf, buffer(0), ENC_ASCII) end end 新しいプロトコルを宣言 dissectorを定義 定義したdissectorを 10000/tcpに登録 bufferのデータ長がプロトコルで指定された長 さよりも短い場合、必要なデータ長になるまで 処理を行わない。 次にdissectorが呼び出される際、bufferに後 続のパケットのペイロードがアペンドされる。 TCPセグメント再構築
  25. 25. 25 解析スクリプト(TCP版)  TCPセグメント再構築イメージ 1パケット目2パケット目 1パケット目でdissectorに渡されるbuffer内容 必要なデータ長に満たないので、pinfo.desegment_lenに DESEGMENT_ONE_MORE_SEGMENTをセットして、 dissectorからreturnする。 サーバが返すデータ 2パケット目でdissectorに渡されるbuffer内容 WiresharkはDESEGMENT_ONE_MORE_SEGMENTがセットされている場合、 次のパケットのペイロードをbufferにアペンドしてdissectorに渡す。 必要なデータ長か否かはdissectorが判断する。
  26. 26. 26 解析スクリプト(TCP版) Response
  27. 27. 05. 既存の解析プラグインの拡張 27
  28. 28. 28 ところで…  独自のプロトコルの解析より、既存の解 析プラグインを拡張したい、と思うことの 方が多いかもしれません。  この機能が使えます。  postdissector  chained dissector  TAP
  29. 29. 29 postdissector  postdissectorとは  dissectorが呼び出された後に呼び出される dissector  同じパケットを複数のdissectorで処理する。  種類に関係なく、全てのパケットに対して呼び出 される。  通常のdissectorと同様にパケットの情報へ のアクセスやPacket Detailsのツリーにアイ テムを追加できる
  30. 30. 30 postdissectorのイメージ dissector ARP IP TCP UDP postdissector … … 25 80 53 68 … 各dissectorで処理が行われた後に 必ず呼び出されるdissector
  31. 31. 31 postdissector例 TCPの場合に送信元/先IPアドレス とポートの組み合わせをPacket Detailsに追加。 http://wiki.wireshark.org/Lua/Dissectors より -- trivial postdissector example -- declare some Fields to be read ip_src_f = Field.new("ip.src") ip_dst_f = Field.new("ip.dst") tcp_src_f = Field.new("tcp.srcport") tcp_dst_f = Field.new("tcp.dstport") -- declare our (pseudo) protocol trivial_proto = Proto("trivial","Trivial Postdissector") -- create the fields for our "protocol" src_F = ProtoField.string("trivial.src","Source") dst_F = ProtoField.string("trivial.dst","Destination") conv_F = ProtoField.string("trivial.conv","Conversation","A Conversation") -- add the field to the protocol trivial_proto.fields = {src_F, dst_F, conv_F} -- create a function to "postdissect" each frame function trivial_proto.dissector(buffer,pinfo,tree) -- obtain the current values the protocol fields local tcp_src = tcp_src_f() local tcp_dst = tcp_dst_f() local ip_src = ip_src_f() local ip_dst = ip_dst_f() if tcp_src then local subtree = tree:add(trivial_proto,"Trivial Protocol Data") local src = tostring(ip_src) .. ":" .. tostring(tcp_src) local dst = tostring(ip_dst) .. ":" .. tostring(tcp_dst) local conv = src .. "->" .. dst subtree:add(src_F,src) subtree:add(dst_F,dst) subtree:add(conv_F,conv) end end -- register our protocol as a postdissector register_postdissector(trivial_proto) パケット内で読み取るフィー ルドを宣言 新しいプロトコルを宣言 宣言したプロトコルで使用 するフィールドを定義 postdissectorを定義 postdissectorを登録
  32. 32. 32 postdissector例実行結果 定義したプロトコルやフィールドはディス プレイフィルタとして指定できる。 Packet Detailsにも情報を追加できる。 この例では、TCPの場合のみTrivial Protocol Dataツリーが追加される。
  33. 33. 33 chained dissector  chained dissectorとは  あるdissectorが呼び出された後に続けて呼 び出されるdissector  同じパケットを複数のdissectorで処理する  特定のプロトコルに関してのみ呼び出される  通常のdissectorと同様にパケットの情報へ のアクセスやPacket Detailsのツリーにアイ テムを追加できる
  34. 34. 34 chained dissectorのイメージ dissector ARP IP TCP UDP chained dissector … … 25 80 53 68 … 特定のdissectorに紐付けられて 呼び出されるdissector
  35. 35. 35 chained dissector例 do local http_suspicious_proto = Proto("http_suspicious", "Suspicious HTTP Traffic") local F_suspicious_uri = ProtoField.string("http.suspicious_uri", "Suspicious Request URI") local F_suspicious_host = ProtoField.string("http.suspicious_host", "Suspicious Host Header") http_suspicious_proto.fields = {F_suspicious_uri, F_suspicious_host} local f_request_uri = Field.new("http.request.uri") local f_host = Field.new("http.host") local original_http_dissector function http_suspicious_proto.dissector(buffer, pinfo, tree) original_http_dissector:call(buffer, pinfo, tree) if f_request_uri() then local uri = tostring(f_request_uri()) local host = tostring(f_host()) chained dissectorの処理を行う前に、 オリジナルのdissectorで処理を行う。 if string.match(uri, "%.exe") and string.match(host, "[^j][^p]:%d+") then local subtree = tree:add(http_suspicious_proto, buffer) subtree:add(F_suspicious_uri, buffer(), uri) :set_text("URI : " .. uri) subtree:add(F_suspicious_host, buffer(), host) :set_text("Host : " .. host) end end end local tcp_dissector_table = DissectorTable.get("tcp.port") original_http_dissector = tcp_dissector_table:get_dissector(8080) tcp_dissector_table:add(8080, http_suspicious_proto) end 新しいプロトコルを宣言 宣言したプロトコルで使用 するフィールドを定義 パケット内で読み取るフィー ルドを宣言 chained dissectorを定義 リクエストされているURIとHostヘッダ から疑わしいか判断。 chained dissectorを登録 8080/tcpに登録されているオリジナルの dissectorをバックアップ。
  36. 36. 36 chained dissector例実行結果 定義したプロトコルやフィールドはディス プレイフィルタとして指定できる。 Packet Detailsにも情報を追加できる。 この例では、疑わしいHTTPのリクエストに Suspicious HTTP Trafficツリーが追加さ れる。
  37. 37. 37 TAP  TAPとは  主に統計情報収集用として使用される。  全てのパケットに対して呼び出される。  フィルタを設定して、該当するパケットのみを処 理することも可能。  キャプチャフィルタの影響は受ける。  ディスプレイフィルタの影響は受けない。  dissectorとは異なり、Packet Detailsのツ リーにアイテムは追加できない。
  38. 38. 38 TAPのイメージ 0100111010101010101110 キャプチャフィルタ 解析プラグイン ディスプレイフィルタ Wireshark画面出力 TAP dissectorとは独立して パケットを解析。
  39. 39. 39 TAP例 do local function menuable_tap() -- Declare the window we will use local tw = TextWindow.new("Address Counter") -- This will contain a hash of counters of appearances of a certain address local ips = {} -- this is our tap local tap = Listener.new(); function remove() -- this way we remove the listener than otherwise will remain running indifinitelly tap:remove(); end -- we tell the window to call the remove() function when closed tw:set_atclose(remove) -- this function will be called once for each packet function tap.packet(pinfo,tvb) local src = ips[tostring(pinfo.src)] or 0 local dst = ips[tostring(pinfo.dst)] or 0 ips[tostring(pinfo.src)] = src + 1 ips[tostring(pinfo.dst)] = dst + 1 end -- this function will be called once every few seconds to update our window function tap.draw(t) tw:clear() for ip,num in pairs(ips) do tw:append(ip .. "t" .. num .. "n"); end end -- this function will be called whenever a reset is needed -- e.g. when reloading the capture file function tap.reset() tw:clear() ips = {} end end -- using this function we register our fuction -- to be called when the user selects the Tools->Test->Packets menu register_menu("Test/Packets", menuable_tap, MENU_TOOLS_UNSORTED) end Listener.new(“frame”, “ip.addr == 10.0.0.0/8”) のようにフィルタリングをすることも可能。 TAPを生成 送信元または送信先ごとにパケット数をカウント パケットを受け取るたびに 呼び出される関数 テキストウィンドウに 結果を表示 Toolsメニューにスクリプトを 実行するメニューを追加 http://www.wireshark.org/docs/wsug_html_chunked/wslua_tap_example.html より
  40. 40. 40 TAP例実行結果 Tools – Test – Packetsが追加される。 メニューを実行して、パケットキャプチャを 行うと、送信元または送信先ごとのパケット 数がウィンドウに表示される。 Wiresharkの名前解決を有効にすると、ドメ イン名などが解決された結果で集計される。
  41. 41. 06. ビット演算 41
  42. 42. 42 Luaのビット演算  Lua 5.2でビット演算がサポート  公式版WindowsバイナリはLua 5.2組み込み  公式版MacバイナリはLua 5.1組み込み  いずれも、Wireshark 1.12.1で確認  Linuxはディストリビューションによるかも  Debian 7では、Wireshark 1.8.2のパッケージ(Lua 5.1)  Lua 5.1では外部ライブラリを使えば可能  bitop : http://bitop.luajit.org/  Lua 5.1/5.2用  使うならばこちらがお勧めだが、Lua 5.2とAPIが異なる  Debian 7ではパッケージが用意されている(lua-bitop)  bitlib : https://github.com/LuaDist/bitlib  Lua 5.1用  もうメンテナンスされていないっぽい
  43. 43. Luaビット演算  API  bit32.arshift, bit32.band, bit32.bnot, bit32.bor, bit32.btest, bit32.bxor, bit32.bextract, bit32.lrotate, bit32.lshift, bit32.replace, bit32.rrotate, bit32.rshift  詳細:http://www.lua.org/manual/5.2/manual.html#6.7  “0x1234” と“0xFF00” のANDの動作確認  Tools – Lua – Evaluate で以下を入力 43 local tw = TextWindow.new("BitOp Test Program"); band_val = bit32.band(0x1234, 0xFF00) tw:set("lua version: " .. _VERSION .."n" .. band_val )
  44. 44. 44 まとめ  パケット単位の解析  今まさにキャプチャしたパケットのみが解析対象  過去のパケットの情報は取得できない  1つのプロトコルにつき、1つのdissector  単一のdissectorでRequestとResponseを解析  chained dissectorなどで既存のdissectorの拡張は可能  WiresharkでLuaを使うにはコンパイル時に指定する必要あり  公式配布バイナリ(Win/Mac)版は標準で組み込み済み  Windowsバイナリ:Lua 5.2  Macバイナリ:Lua 5.1  Linux版はディストリビューションによって異なる可能性あり  Lua 5.2未満の場合はビット演算ができない  外部ライブラリ(bitop)を使えば可能  ただし、本家LuaとAPIが異なる
  45. 45. 45 参考  Wireshark  Wireshark User’s Guide  https://www.wireshark.org/docs/wsug_html_chunked/wsluarm.html  https://www.wireshark.org/docs/wsug_html_chunked/lua_module_Proto.html#lua_class_ProtoField  https://www.wireshark.org/docs/wsug_html_chunked/lua_module_Tree.html  The Wireshark Wiki  http://wiki.wireshark.org/Lua  http://wiki.wireshark.org/Lua/Dissectors  http://wiki.wireshark.org/Lua/Examples  http://wiki.wireshark.org/Lua/Taps  Wireshark 1.2.9 ソースコードアーカイブ内  README.developer  README.tapping  Lua  http://www.lua.org/manual/5.2/manual.html#6.7  その他  Googleブックス(http://books.google.co.jp/books)  Wireshark and Ethereal network protocol analyzer toolkit  実践パケット解析: Wiresharkを使ったトラブルシューティング  http://www.lua.org/  http://bitop.luajit.org/  http://luaforge.net/projects/bitlib/
  46. 46. 46 Q & A
  47. 47. おまけ  Lua以外のバインディング言語  SSL復号  サーバの証明書を使う  ブラウザの暗号鍵を使う 47 今回やりません。 ググって!
  48. 48. Lua以外のバインディング おまけ1 48
  49. 49. Lua以外のバインディング言語  Aboutダイアログをよくみると… 49
  50. 50. Pythonバインディングの実際のところ  withoutなのでWireshark wikiを見てみる http://wiki.wireshark.org/Python より 50
  51. 51. pyresharkについて  LuaのようにTCPやUDPのポート毎に dissectorを登録するようなAPIが用意さ れていない。  tcp_table = DissectorTable.get("tcp.port")  tcp_table:add(10000, tcp_rngp_proto)  TCP/IPヘッダを自力でゴリゴリ解析する 必要がありそう。  面倒そうなので試すのをやめました…。 51
  52. 52. ブラウザ側の暗号鍵を使ったSSL復号 おまけ2 52
  53. 53. WiresharkでSSL復号  よく見かける方法として、サーバのSSL秘密鍵を Wiresharkに設定して、パケットキャプチャの解析を行う 手順が解説されている。  自分がSSL秘密鍵を持っていない場合、通信内容が分 からない!  外部のサービスを使う場合とか  Fiddlerとか使えば見えますが  しかし、SSL秘密鍵がなくても、ブラウザ側が持ってい る暗号鍵でSSL復号を行うことができる。 53
  54. 54. ブラウザの暗号鍵で復号  SSLKEYLOGFILE環境変数を設定する  SSLKEYLOGFILE=/path/to/sslkeylog.txt  Wiresharkで以下を設定  Edit – Preferences – Protocols – SSL – (Pre)-Master- Secret log filename  display filter で“ssl” を設定  適当なパケットを選択して、Follow SSL Stream  Packet BytesのDecrypted SSL dataタブ等  鍵交換プロトコルがRSAでもECDHE(Perfect Forward Secrecy)でも復号可能  PFSだとサーバのSSL秘密鍵を持っていても復号できない 54
  55. 55. SSLKEYLOGFILEフォーマット  CLIENT_RANDOM <space> <64 bytes of hex encoded client_random> <space> <96 bytes of hex encoded master secret>  RSA <space> <16 bytes of hex encoded encrypted pre master secret> <space> <96 bytes of hex encoded pre master secret> 55
  56. 56. 使用ブラウザの制限  SSLKEYLOGFILE環境変数を見てログファイルを作る のは、NSS(Network Security Services)ライブラリであ るため、同様の手順が取れるのは同ライブラリを使用 するブラウザ、ツールのみ。  NSSを使用する主なブラウザは、Firefox, PC版 Chrome(Win/Mac/Linux版含む)のみ。  Android版ChromeはOpenSSLを使用  PC版ChromeもBoringSSLを使い始めた場合は使えなくない  他のブラウザの場合はメモリダンプするくらいしか手が ないんじゃ…。 56
  57. 57. 参考  pyreshark  https://github.com/ashdnazg/pyreshark  Psst. Your Browser Knows All Your Secrets.  https://isc.sans.edu/diary/Psst.+Your+Browser+Knows+All+Your+Secrets./16415  NSS Key Log Format  https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format  Chrome: From NSS to OpenSSL  https://docs.google.com/document/d/1ML11ZyyMpnAr6clIAwWrXD53pQgNR-DppMYwt9XvE6s/ edit?pli=1#heading=h.n30fi956cpfk  SSL/TLS & Perfect Forward Secrecy  http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html  ディフィー・ヘルマン鍵共有  http://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%95%E3%82%A3%E3%83%BC %E3%83%BB%E3%83%98%E3%83%AB%E3%83%9E%E3%83%B3%E9%8D%B5%E5%85%B 1%E6%9C%89  Diffie–Hellman key exchange  http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange 57
  58. 58. 58 Q & A

×