因为平时工作中对外提供的产品,使用了私有的自定义协议,wireshark抓包分析时需要一个个对序号和字段,十分不方便,学习后,发现wireshark支持lua插件的形式编写自定义的协议解析,将相关方法、学习中的心得进行分享。

 

插件的加载配置

  1. 打开wireshark -->帮助-->关于wireshark -->文件夹 -->全局配置
  2. 点击进入全局配置文件夹,找到init.lua文件,打开(ubuntu需要通过chmod修改文件权限,可以直接无脑777)
  3. 打开init.lua,最后一行,将自定义解析的lua脚本也放到init.lua同目录下,然后,红框中替换为自己编写的自定义脚本   先确认enable_lua:true
  4. 而后重启wireshark或者使用快捷键ctrl+shift+h便可以重载脚本,新创建的解析脚本即开始生效。

lua脚本相关知识

创建Proto对象

local Customize_Protocol = Proto('Protocol_Name','Protcol_Desc')
local protoName = 'protocol_name'

上述代码,Protocol_Name字段用于自定义Wireshark报文界面的Protocol列的名称

wireshark为啥不选Python来做插件 wireshark实用插件_lua

 

Protocol_Desc用于定义报文解析字段中的协议字段名称,类似于UDP/TCP

wireshark为啥不选Python来做插件 wireshark实用插件_字段_02

 

protocol_name用于自定义wireshark显示过滤器时输入的协议名称字段

wireshark为啥不选Python来做插件 wireshark实用插件_lua_03

关于Proto对象的详细说明,参考wireshark官方文档:

11.3. Functions For New Protocols And Dissectors

 

wireshark为啥不选Python来做插件 wireshark实用插件_字段_04

 

添加协议字段(使用ProtoField对象)

用于在wireshark解析树中增加节点

local section1 = ProtoField.type1(protoName .. ".name1", "Desc1", parse_type1)
local section2 = ProtoField.type2(protoName .. ".name2", "Desc2", parse_type2)

参数说明:

ProtoFiled.type:指字段的类型,不同参数对应的后续参数说明也可以参考该文档

name1:显示过滤器中可以以该名字来进行显示过滤,比如protocol_name.name1==xxx,用于过滤自定义协议指定字段中特定值

Desc1:在Wireshark解析树中的名称

parse_type1:Wireshark中显示的类型

以ProtoFiled.byte为例子:

wireshark为啥不选Python来做插件 wireshark实用插件_自定义_05

关于ProtoFiled对象的参数说明,可以参考官方文档:

11.3. Functions For New Protocols And Dissectors

定义完成各个字段的信息后,需要添加到自定义协议的field中

-- (1) register fields
Customize_Protocol.fields = {section1,section2...sectionx}

具体的解析功能

可以定义函数进行复杂逻辑的解析,一般会针对指定数据进行解析,使用到的方法有:

function Customize_Protocol.dissector(buffer, pinfo, tree)
    local buffer_length = buffer:len()
    if buffer_length == 0 then return end
    local identifier = buffer(0,x)
    if (identifier:uint() ~= 0xFFFF) then return end
    -- set the name of protocol column
    pinfo.cols.protocol = Customize_Protocol.name
    

    -- create a sub tree representing the PTC data
    local subtree = tree:add(Customize_Protocol, buffer(), "Protocol Desc")
    local section1_subtree = subtree:add(Customize_Protocol, buffer(), "Section1")

    -- (2) add fields
    section1_subtree:add_le(section2, buffer(0, 2))
    
    section1_subtree:add(section3, buffer(4, 4)) --network endian
end

参数解释:

buffer:某个报文的报文内容(如果后续绑定了tcp/udp就是tcp/udp的payload字段,否则就是抓取到的整个报文)

文档描述:11.6. Functions For Handling Packet Data

pinfo:报文界面的显示内容

文档描述:

11.5. Obtaining Packet Information

tree:协议解析时的结构,需要添加子节点则操作该参数

文档描述:

11.7. Adding Information To The Dissection Tree

子树节点可以继续添加节点,tree.add返回的是新的treeitem节点

local section1_subtree = subtree:add(Customize_Protocol, buffer(), "Section1")

    -- (2) add fields
    section1_subtree:add_le(section2, buffer(0, 2))
    
    section1_subtree:add(section3, buffer(4, 4)) --network endian

上述就是在sub_tree节点下添加了section2/3两个节点

下面代码用于判断如果没有报文字段,退出不解析

local buffer_length = buffer:len()
    if buffer_length == 0 then return end
local identifier = buffer(0,2)
    if (identifier:uint() ~= 0xFFFF) then return end

上面代码用于判断特殊的头部标识,例子为头部为ffff

在添加字段,即使用sub_tree.add方法时需要注意:

add/add_le是针对解析时不同端序来处理(也就是大小端)

wireshark为啥不选Python来做插件 wireshark实用插件_自定义_06

 

如果sub_tree后想增加新的备注项目,可以使用方法:

wireshark为啥不选Python来做插件 wireshark实用插件_自定义_07

绑定端口

使用TCP时

local tcp_port = DissectorTable.get("tcp.port")
-- bind port to protocol
tcp_port:add(xxxx, Customize_Protocol)

使用UDP时:

local udp_port = DissectorTable.get("udp.port")
-- bind port to protocol
udp_port:add(xxxx, Customize_Protocol)

参考文档

Chapter 10. Lua Support in Wireshark