Lua plugin for Wireshark

In the arsenal of ICT ( ICT , information and communications technology) personnel used for network analysis, wireshark is undoubtedly the sword of heaven. Although it has a long history, its sharpness is undiminished. Due to the open source, it is convenient for users to develop again. The appearance and function of the sword are almost perfect. If you can use this sword proficiently, it will be beneficial and harmless for walking in the arena.

Wireshark has its own analysis plug-in for the current mainstream protocol, such as IP, ARP, TCP, UDP, HTTP, DHCP, etc. But in actual applications, these protocols are usually only the carriers of our data transmission process. Many communication protocols between software are private. For example, the interaction protocol between the game client and the server is usually private, and Wireshark cannot be specific. Analyzing the meaning between the various fields, only the received binary data can be displayed, which brings certain difficulties to the analysis of the protocol and the troubleshooting, especially when the content of the protocol is more complicated.

Through wireshark, you can know the content of each field, but if the message structure is complex, you need to calculate the offset to get the specified field value; in addition, if the message structure contains bit field fields, it is more complicated and hurts your eyes; finally, it cannot be used The specified field in the message field performs message filtering operations. Based on the above reasons, in order to help analysis, it is imperative to write plug-in script analysis. This article starts with a custom simple message protocol and analyzes how to write a Wireshark plug-in in Lua to parse custom messages.

-- 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 language is a weak language and does not need to be compiled. The usage of Lua plugin is as follows:

1. Put the script file directly in the wireshark installation directory

2. Find the init.lua file in the current path and add the dofile(DATA_DIR.."test.lua) statement at the end of it

3. Restart wireshark.

Guess you like

Origin blog.csdn.net/u013318019/article/details/106629214