ネットワーク分析に使用されるICT(ICT、情報通信技術)担当者の兵器庫では、wiresharkは間違いなく天国の剣です。長い歴史がありますが、その鋭さは衰えていません。オープンソースであるため、ユーザーにとって便利です。剣の外観と機能はほぼ完璧です。この剣を上手に使えば、アリーナを歩くのに有益で無害になります。
Wiresharkには、IP、ARP、TCP、UDP、HTTP、DHCPなどの現在の主流プロトコル用の独自の分析プラグインがあります。ただし、実際のアプリケーションでは、これらのプロトコルは通常、データ送信プロセスのキャリアにすぎません。ソフトウェア間の多くの通信プロトコルはプライベートです。たとえば、ゲームクライアントとサーバー間の対話プロトコルは通常プライベートであり、Wiresharkを特定することはできません。さまざまなフィールド間の意味では、受信したバイナリデータのみを表示できます。これは、特にプロトコルの内容がより複雑な場合に、プロトコルの分析とトラブルシューティングに一定の困難をもたらします。
Wiresharkを使用すると、各フィールドの内容を知ることができますが、メッセージ構造が複雑な場合は、オフセットを計算して指定されたフィールド値を取得する必要があります。さらに、メッセージ構造にビットフィールドフィールドが含まれている場合は、より複雑になり、目を痛める;最後に使用できませんメッセージフィールドの指定されたフィールドは、メッセージフィルタリング操作を実行します。上記の理由に基づいて、分析を支援するために、プラグインスクリプト分析を作成することが不可欠です。この記事は、カスタムのシンプルなメッセージプロトコルから始めて、カスタムメッセージを解析するためにLuaでWiresharkプラグインを作成する方法を分析します。
-- Tetra NM_Agnet message protocol Lua script
-- [email protected]
-- V1.0
-- 2020.06.08 10:34:16
-- create dissector message object
local tetra_fls_message_name = "Tetra_NM_Agent"
local tetra_fls_message_brief = "Dissector all message for Tetra NM Agent"
local tetra_fls_proto = Proto(tetra_fls_message_name, tetra_fls_message_brief)
--[[
local tetra_fls_proto_msg_id = ProtoField.uint8("msg_id","msg id",base.HEX,
{
[0xB1]="HELLO",
[0xB2]="TX_CONTROL",
[0XB3]="CELL_CONFIGURE",
[0XB4]="FLS_ALARM_REPORT",
[0XB5]="STILL-ALIVE",
[0XB7]="FLS-RESET",
[0xB8]="DSP_CLOSE",
[0xB9]="RRU_VERSION_UPGRADE",
[0xBA]="RRU_VERSION_REPORT/QUERY",
[0xBB]="RRU_VERSION_ACTIVE",
[0xBC]="RRU_ALARM_REPORT",
[0xBD]="CELL_DELETE"
}
)
--]]
local tetra_fls_proto_msg_id = ProtoField.uint8("msg_id","msg id",base.HEX)
local tetra_fls_proto_msg_length = ProtoField.uint32("msg_len","msg len",base.DEC)
local tetra_fls_proto_msg_crc = ProtoField.uint32("msg_crc","msg crc",base.HEX)
local tetra_fls_proto_msg_body = ProtoField.bytes("msg_body","msg body")
local tetra_fls_proto_hello_ver = ProtoField.uint8("version","version",base.HEX)
local tetra_fls_proto_hello_controller_identifier = ProtoField.uint8("controller_id","controller id",base.HEX)
local tetra_fls_proto_hello_session_identifier = ProtoField.uint8("session_id","session id",base.HEX)
local tetra_fls_proto_hello_still_alive = ProtoField.uint8("still_alive","still alive",base.HEX)
local tetra_fls_proto_hello_ack_status = ProtoField.uint8("dsp_status","dsp status",base.HEX)
local tetra_fls_proto_hello_ack_mem = ProtoField.uint32("share_memory","share memory",base.HEX)
local tetra_fls_proto_rru_upgrade_sw_path = ProtoField.string("rru_upgrade_sw_path","rru upgrade sw path")
local tetra_fls_proto_rru_upgrade_sw_name = ProtoField.string("rru_upgrade_sw_name","rru upgrade sw name")
local tetra_fls_proto_rru_upgrade_fw_path = ProtoField.string("rru_upgrade_fw_path","rru upgrade fw path")
local tetra_fls_proto_rru_upgrade_fw_name = ProtoField.string("rru_upgrade_fw_name","rru upgrade fw name")
local tetra_fls_proto_rru_upgrade_ack = ProtoField.uint8("rru_upgrade_ack","rru upgrade ack",base.HEX)
local tetra_fls_proto_rru_query = ProtoField.uint32("rru_query","rru query",base.HEX)
local tetra_fls_proto_rru_query_ack_sw = ProtoField.string("rru_upgrade_ack_sw_name","rru upgrade ack sw")
local tetra_fls_proto_rru_query_ack_fw = ProtoField.string("rru_upgrade_ack_fw_name","rru upgrade ack fw")
local tetra_fls_proto_rru_active_sw = ProtoField.string("rru_upgrade_active_sw_name","rru upgrade active sw")
local tetra_fls_proto_rru_active_fw = ProtoField.string("rru_upgrade_active_fw_name","rru upgrade active fw")
local tetra_fls_proto_rru_active_ack = ProtoField.uint8("rru_upgrade_active_ack","rru upgrade active ack",base.HEX)
local tetra_fls_proto_rru_alarm_valid = ProtoField.uint16("rru_alarm_valid","rru alarm valid",base.HEX)
local tetra_fls_proto_rru_alarm_code = ProtoField.uint32("rru_alarm_code","rru alarm code",base.HEX)
local tetra_fls_proto_rru_alarm_sucode = ProtoField.uint32("rru_alarm_sucode","rru alarm sucode",base.HEX)
local tetra_fls_proto_rru_alarm_clear_flag = ProtoField.uint32("rru_alarm_clear_flag","rru alarm clear flag",base.HEX)
local tetra_fls_proto_rru_alarm_timestamp = ProtoField.string("rru_alarm_timestamp","rru alarm timestamp")
local tetra_fls_proto_rru_alarm_additional = ProtoField.string("rru_alarm_additional","rru alarm additional")
local tetra_fls_proto_cell_delete = ProtoField.uint32("cell_delete","cell delete",base.HEX)
local tetra_fls_proto_cell_delete_ack = ProtoField.uint8("cell_delete_ack","cell delete ack",base.HEX)
tetra_fls_proto.fields = {
tetra_fls_proto_msg_id,
tetra_fls_proto_msg_length,
tetra_fls_proto_msg_crc,
tetra_fls_proto_msg_body,
tetra_fls_proto_hello_ver,
tetra_fls_proto_hello_controller_identifier,
tetra_fls_proto_hello_session_identifier,
tetra_fls_proto_hello_still_alive,
tetra_fls_proto_hello_ack_status,
tetra_fls_proto_hello_ack_mem,
tetra_fls_proto_rru_upgrade_sw_path,
tetra_fls_proto_rru_upgrade_sw_name,
tetra_fls_proto_rru_upgrade_fw_path,
tetra_fls_proto_rru_upgrade_fw_name,
tetra_fls_proto_rru_upgrade_ack,
tetra_fls_proto_rru_query,
tetra_fls_proto_rru_query_ack_sw,
tetra_fls_proto_rru_query_ack_fw,
tetra_fls_proto_rru_active_sw,
tetra_fls_proto_rru_active_fw,
tetra_fls_proto_rru_active_ack,
tetra_fls_proto_rru_alarm_valid,
tetra_fls_proto_rru_alarm_code,
tetra_fls_proto_rru_alarm_sucode,
tetra_fls_proto_rru_alarm_clear_flag,
tetra_fls_proto_rru_alarm_timestamp,
tetra_fls_proto_rru_alarm_additional,
tetra_fls_proto_cell_delete,
tetra_fls_proto_cell_delete_ack
}
------------------------------------------------ message table --------------------------------------------------
local colomn_message = {
[0xB1] = "HELLO",
[0xB2] = "TX_CONTROL",
[0xB3] = "CELL_CONFIGURE",
[0xB4] = "FLS_ALARM_REPORT",
[0xB5] = "STILL_ALIVE",
[0xB6] = "RESERVED",
[0xB7] = "FLS_RESET",
[0xB8] = "DSP_CLOSE",
[0xB9] = "RRU_VERSION_UPGRADE",
[0xBA] = "RRU_VERSION_REPORT/QUERY",
[0xBB] = "RRU_VERSION_ACTIVE",
[0xBC] = "RRU_ALARM_REPORT",
[0xBD] = "CELL_DELETE",
}
function tetra_fls_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol:set("Tetra NM Agent message")
pinfo.cols.info:set("Tetra NM Agent proto")
local buffer_total_len = buffer:len()
local buffer_tree = tree:add(tetra_fls_proto, buffer:range(buffer_total_len))
local buffer_header_len = 12
local buffer_body_len = buffer_total_len - buffer_header_len
local offset = 0
buffer_tree:add(tetra_fls_proto_msg_length, buffer(offset, 4))
local msg_len = buffer(offset,4):uint()
offset = offset + 4
buffer_tree:add(tetra_fls_proto_msg_id, buffer(offset, 1))
local msg_id = buffer(offset, 1):uint()
offset = offset + 1
--buffer_tree:add(tetra_fls_proto_msg_id, buffer(offset, 1))
offset = offset + 1
--buffer_tree:add(tetra_fls_proto_msg_id, buffer(offset, 1))
offset = offset + 1
--buffer_tree:add(tetra_fls_proto_msg_id, buffer(offset, 1))
offset = offset + 1
buffer_tree:add(tetra_fls_proto_msg_crc, buffer(offset, 4))
offset = offset + 4
local tetra_nm_msg_body = buffer_tree:add(tetra_fls_proto_msg_body, buffer(offset, buffer_total_len - offset))
local body_0 = buffer(offset, 1):uint()
local nm_msg = "#NM_Agent_MSG#".." ".."APP <-> FLS".." "
local nm_msg_to_fls = "#NM_Agent_MSG#".." ".."APP -> FLS".." "
local nm_msg_to_app = "#NM_Agent_MSG#".." ".."FLS -> APP".." "
if (msg_id == 0xB1) then
if (buffer_body_len == 4) then
tetra_nm_msg_body:add(tetra_fls_proto_hello_ver, buffer(offset, 1))
offset = offset + 1
tetra_nm_msg_body:add(tetra_fls_proto_hello_controller_identifier, buffer(offset, 1))
offset = offset + 1
tetra_nm_msg_body:add(tetra_fls_proto_hello_session_identifier, buffer(offset, 1))
offset = offset + 1
tetra_nm_msg_body:add(tetra_fls_proto_hello_still_alive, buffer(offset, 1))
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 12) then
offset = offset + 3
tetra_nm_msg_body:add(tetra_fls_proto_hello_ack_status, buffer(offset, 1))
offset = offset + 1
tetra_nm_msg_body:add(tetra_fls_proto_hello_ack_mem, buffer(offset, 4))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xB3) then
if (buffer_body_len == 19) then
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 4) then
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xB4) then
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id])
elseif (msg_id == 0xB5) then
if (body_0 == 0xff) then
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
elseif (body_0 <= 2) then
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xB9) then
if (buffer_body_len == 432) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_upgrade_sw_path, buffer(offset, 200))
offset = offset + 200
tetra_nm_msg_body:add(tetra_fls_proto_rru_upgrade_sw_name, buffer(offset, 16))
offset = offset + 16
tetra_nm_msg_body:add(tetra_fls_proto_rru_upgrade_fw_path, buffer(offset, 200))
offset = offset + 200
tetra_nm_msg_body:add(tetra_fls_proto_rru_upgrade_fw_name, buffer(offset, 16))
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 4) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_upgrade_ack, buffer(offset, 1))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xBA) then
if (buffer_body_len == 4) then
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 80) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_query_ack_sw, buffer(offset, 40))
offset = offset + 40
tetra_nm_msg_body:add(tetra_fls_proto_rru_query_ack_fw, buffer(offset, 40))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xBB) then
if (buffer_body_len == 80) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_active_sw, buffer(offset, 40))
offset = offset + 40
tetra_nm_msg_body:add(tetra_fls_proto_rru_active_fw, buffer(offset, 40))
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 1) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_active_ack, buffer(offset, 1))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xBD) then
if (buffer_body_len == 4) then
pinfo.cols.info:set(nm_msg_to_fls..colomn_message[msg_id])
elseif (buffer_body_len == 1) then
tetra_nm_msg_body:add(tetra_fls_proto_cell_delete_ack, buffer(offset, 1))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id].."_ACK")
else
pinfo.cols.info:set("#ERROR# unknown message")
end
elseif (msg_id == 0xBC) then
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_valid, buffer(offset, 2))
offset = offset + 2
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_code, buffer(offset, 4))
offset = offset + 4
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_sucode, buffer(offset, 4))
offset = offset + 4
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_clear_flag, buffer(offset, 4))
offset = offset + 4
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_timestamp, buffer(offset, 20))
offset = offset + 20
tetra_nm_msg_body:add(tetra_fls_proto_rru_alarm_additional, buffer(offset, 20))
pinfo.cols.info:set(nm_msg_to_app..colomn_message[msg_id])
else
pinfo.cols.info:set(nm_msg..colomn_message[msg_id])
end
end
-- register for wireahark
local udp_port_table = DissectorTable.get("udp.port")
-- bind udp port
for i,port in ipairs{5025,5045} do
udp_port_table:add(port,tetra_fls_proto)
end
Lua言語は弱い言語であり、コンパイルする必要はありません。Luaプラグインの使用法は次のとおりです。
1.スクリプトファイルをwiresharkのインストールディレクトリに直接配置します
2.現在のパスでinit.luaファイルを見つけ、その最後にdofile(DATA_DIR .. "test.lua)ステートメントを追加します。
3.wiresharkを再起動します。