lua语言学习之自定义wireshark插件来解析自定义协议
- 关于wireshark这个抓包工具
- 关于lua
- 使用lua写wireshark插件
- wireshark接口文档
- 如何在wireshark使用自己写的lua脚本
- 使用教程及完整代码
关于wireshark这个抓包工具
wireshark工具的功能十分强大,它可以抓取你想抓取的主机的所有网络封包。并且对于一般的网络协议,wireshark可以做到自动解析数据。可以用它来干坏事,你也可以用来测试一个你自己封装的网络协议的安全性,再或者测试一个新的协议是否可行等等。剩下的自行百度,本菜鸟也不精通。
关于lua
由于需求,百度第一次发现还有一种叫”撸啊“的语言,不禁让我想起了LOL。(扯远了~) lua是一种用c语言写的轻量级语言,源码好像说只有2.4万行c,安装教程可以百度菜鸟教程。但是当我们在wireshark上使用时是不需要安装环境的,因为wireshark继承了lua的解释器,且给用户留了API供数据包处理。这里有几点要说明的:
- lua语言在wireshark上使用时,你的调试过程完全不依赖lua的环境,所以你不需要安装lua的包,只需要wireshark加载你写的name.lua就可以(可以用文本编辑器写,后缀为.lua)。至于怎么加载,请往下翻。
- lua语言经过我的苦战之后发现其不足之处–虽然它是用c写的,但是它没有继承c语言的位操作。也就是说没有<< >> || &&等操作。要这个有啥用呢? 首先,如果你想要解析一包网络数据里面的一段信息,一般一包数据的发送都是以大端发送,若涉及8bit以上的包解析,你肯定要用到位运算,故用lua你就要想别的办法解决。
- 在wireshark里面的接口和lua的环境没任何关系,你只能用wireshark调试,比较麻烦。
- 剩下的基本能百度到
使用lua写wireshark插件
先看代码和解析,然后再去后面看接口相应文档:
首先打开文本编辑器,新建一个(你想写的名字).lua的文件。加入以下代码:
local _808_proto = Proto ("2013","2013","Self-defined Protocol")
--以下根据协议定义消息字段--
--标识符
local _808_message_flag_start= ProtoField.uint8("_808_message_flag_start", "start_flag", base.HEX) -- 消息标识符
local _808_message_flag_end = ProtoField.uint8("_808._message_flag_end", "end_flag", base.HEX)
--消息头
local _808_message_id = ProtoField.uint16("_808.messageid", "Message ID", base.HEX) -- 消息id
local _808_message_property = ProtoField.uint16("_808_message_property", "Message Property", base.HEX) --消息体
-- 将字段添加都协议中
_808_proto.fields = {
_808_message_flag_start,
_808_message_flag_end,
_808_message_id,
_808_message_property,
}
这段话是创建字段的意思,看下图:
上述代码里出现的变量后面定义的字段名字出现在第一部分红圈里面。然后,怎么让它在后面显示你想解析的字段?继续看下面:
function _808_proto.dissector(tvb, pinfo, treeitem)
这个函数是用来解析报文用的,参数tvb里面放了有用的报文,wireshark自动帮你过滤了tcp/ip报头,tvb从0开始就是你要抓得有用数据。但是tvb并非数组,本菜鸟后来也没有摸清里面的数据结构,反正也不是字符串。解析完成后,用tvb(x,y)的形式取出数据。x指起始位,(从0开始)y指从x起向后几位。
下面贴出部分代码:
function _808_proto.dissector(tvb, pinfo, treeitem)
-- 设置一些 UI 上面的信息
pinfo.cols.protocol:set("_808")
pinfo.cols.info:set("_808 Protocol")
local offset = 0
local tvb_len = tvb:len()
-- 在上一级解析树上创建 _808 的根节点
local _808_tree = treeitem:add(_808_proto, tvb:range(tvb_len))
--创建消息标识位树--
local Ms_flag_bit=_808_tree:add(_808_proto,"MSG_FLAG_BIT")
Ms_flag_bit:add(_808_message_flag_start,tvb(0,1)) --暂不解析
--创建消息头树--
Ms_head_tree=_808_tree:add(_808_proto,"MSG_HEADER: 0x"..tvb(1,16))
Ms_head_tree:add(_808_message_id,tvb(1,2)) --消息id显示
Ms_head_tree:add(_808_message_property,tvb(3,6)) --消息属性显示
--消息属性子树
local Ms_end=_808_tree:add(_808_proto,"end_flag")
Ms_end:add(_808_message_flag_end,tvb(tvb_len-1,1))
end
wireshark接口文档
这里贴出大佬的网站,下面有中文介绍
链接: .声明一下,这位老哥的文档对我这个英语菜鸡给了很大帮助,所以帮他打广告,开个传送门在这里。
如何在wireshark使用自己写的lua脚本
既然写了就要用,那么下面介绍如何运行脚本:
- 打开Wireshark,点击help -> about Wireshark 看看是否支持lua
2. 然后打开wireshark的安装目录下的init.lua文件(可在安装目录下面搜索),看看如下的值是否为false 是则开启了lua插件。
3. 将上述打开的init.lua文件拉到最后,会看见一个名dofile的函数,如下图:
被马赛克的部分就是你的lua脚本的路径了
在dofile函数里面写上自己将lua插件存放的路径即可,为保证不被转义,最好使用”\”分割。
4.完成上述动作后,重启wireshark即可完成插件的重新加载。若要更改此插件,改完后需重启wireshark或者点击分析->重新加载插件即可。
使用教程及完整代码
教程
打开wireshark,若有错误,会有窗口报错。若无则像下面这样使用:
点击Fliter,输入你定义的协议名字,搜索到后,选择网卡设备,点击1或者start开始抓包,开始后需要光标移动到fliter后回车,过滤生效。然后解析你的数据包。
下面贴出部分源代码,由于涉及保密信息,只能贴应用代码,关于解析数据的代码,有大佬可以讨论一下,毕竟没有移位操作可太难了。
local _808_proto = Proto ("2013","2013","Self-defined Protocol")
--以下根据协议定义消息字段--
--标识符
local _808_message_flag_start= ProtoField.uint8("_808_message_flag_start", "start_flag", base.HEX) -- 消息标识符
local _808_message_flag_end = ProtoField.uint8("_808._message_flag_end", "end_flag", base.HEX)
--消息头
--local MSG_HEAD=ProtoField.uint32("_808.MSG_HEAD","MSG_HEAD",)
local _808_message_id = ProtoField.uint16("_808.messageid", "Message ID", base.HEX) -- 消息id
local _808_message_property = ProtoField.uint16("_808_message_property", "Message Property", base.HEX) --消息体属性
---消息体
-- 将字段添加都协议中
_808_proto.fields = {
_808_message_flag_start,
_808_message_flag_end,
_808_message_id,
_808_message_property,
}
function _808_proto.dissector(tvb, pinfo, treeitem)
-- 设置一些 UI 上面的信息
pinfo.cols.protocol:set("_808")
pinfo.cols.info:set("_808 Protocol")
local offset = 0
local tvb_len = tvb:len()
-- 在上一级解析树上创建 _808 的根节点
local _808_tree = treeitem:add(_808_proto, tvb:range(tvb_len))
--创建消息标识位树--
local Ms_flag_bit=_808_tree:add(_808_proto,"MSG_FLAG_BIT")
Ms_flag_bit:add(_808_message_flag_start,tvb(0,1)) --暂不解析
--创建消息头树--
Ms_head_tree=_808_tree:add(_808_proto,"MSG_HEADER: 0x"..tvb(1,16))
Ms_head_tree:add(_808_message_id,tvb(1,2))
Ms_head_tree:add(_808_message_property,tvb(3,6))
--消息属性子树
local Ms_end=_808_tree:add(_808_proto,"end_flag")
Ms_end:add(_808_message_flag_end,tvb(tvb_len-1,1))
end
-- 向 wireshark 注册协议插件被调用的条件
local tcp_port_table = DissectorTable.get("tcp.port")
tcp_port_table:add(8010, _808_proto)