用Lua语言编写Wireshark dissector插件
Wireshark是一款著名的网络协议分析工具,基于GPLv2协议开源,支持Linux、Windows、MacOS等多个操作系统。
Wireshark已经支持数千种协议,对新协议的支持还在不断增加。今天,你发明了一个新的网络协议,也想让Wireshark识别,你该怎么办呢?你有两个选择:
如果你选择了前者,请按下CTRL+D,然后在你改变主意的时候再回来。 Wireshark和Wireshark dissector如果你还没有安装Wireshark,请下载并安装Wireshark。 从功能看,Wireshark可以分为以下几个模块:
要让Wireshark识别你发明的协议,应该从“协议分析”部分入手,也就是编写一个Wireshark dissector。 Wireshark本身是用C语言编写的,用C语言编写dissector是很自然的选择。但是,C语言并不简单,在Windows下编译C语言的代码也并不容易。浏览一遍Wireshark User Guide的目录,你会看到一章Lua Support in Wireshark,这就是编写Wireshark dissector插件的另一种选择。 Lua脚本语言Lua是一种功能强大的、快速的、轻量的、嵌入式的脚本语言。Lua在葡萄牙语里是“月亮”的意思,它不是一个缩写因此不能写成“LUA”。
Lua是一种嵌入式脚本语言,Wireshark嵌入了Lua脚本引擎,因此我们可以使用Lua脚本语言扩展Wireshark。 初识Lua编写的Wireshark dissectorWireshark User Guide,?Example of Dissector written in Lua已经给出了一段Wireshark插件代码,先解读一下: --这个dissector只是把几个协议组合起来而已,并不是识别一种新的协议 do --do...end是Lua语言的语句块关键字,相当于C#语言的{..} --创建一个Proto类的对象,表示一种协议 local p_multi = Proto("multi","MultiProto"); local vs_protos = { [2] = "mtp2", [3] = "mtp3", [4] = "alcap", [5] = "h248", [6] = "ranap", [7] = "rnsap", [8] = "nbap" } --创建几个ProtoField对象,就是主界面中部Packet Details窗格中能显示的那些属性 local f_proto = ProtoField.uint8("multi.protocol","Protocol",base.DEC,vs_protos) local f_dir = ProtoField.uint8("multi.direction","Direction",{ [1] = "incoming", [0] = "outgoing"}) local f_text = ProtoField.string("multi.text","Text") --把ProtoField对象加到Proto对象上 p_multi.fields = { f_proto, f_dir, f_text } --用Dissector.get函数可以获得另外一个协议的解析组件 local data_dis = Dissector.get("data") local protos = { [2] = Dissector.get("mtp2"), [3] = Dissector.get("mtp3"), [4] = Dissector.get("alcap"), [5] = Dissector.get("h248"), [6] = Dissector.get("ranap"), [7] = Dissector.get("rnsap"), [8] = Dissector.get("nbap"), [9] = Dissector.get("rrc"), [10] = DissectorTable.get("sctp.ppi"):get_dissector(3), -- m3ua [11] = DissectorTable.get("ip.proto"):get_dissector(132), -- sctp } --为Proto对象添加一个名为dissector的函数, --Wireshark会对每个“相关”数据包调用这个函数 function p_multi.dissector(buf,pkt,root) --root:add会在Packet Details窗格中增加一行协议 local t = root:add(p_multi,buf(0,2)) --t:add,在Packet Details窗格中增加一行属性, --并指定要鼠标点击该属性时Packet Bytes窗格中会选中哪些字节 t:add(f_proto,1)) t:add(f_dir,buf(1,1)) --这句是将数据的第一个字节转换成无符号整数 local proto_id = buf(0,1):uint() local dissector = protos[proto_id] if dissector ~= nil then dissector:call(buf(2):tvb(),root) elseif proto_id < 2 then t:add(f_text,buf(2)) -- pkt.cols.info:set(buf(2,buf:len() - 3):string()) else --调用另外一个dissector data_dis:call(buf(2):tvb(),root) end end --所有的dissector都是以“table”的形式组织的,table表示上级协议 local wtap_encap_table = DissectorTable.get("wtap_encap") --这个是获得udp协议的DissectorTable,并且以端口号排列 local udp_encap_table = DissectorTable.get("udp.port") wtap_encap_table:add(wtap.USER15,p_multi) wtap_encap_table:add(wtap.USER12,p_multi) --为UDP的7555端口注册这个Proto对象, --当遇到源或目的为UDP7555的数据包,就会调用上面的p_multi.dissector函数 udp_encap_table:add(7555,p_multi) end Wireshark虽然嵌入了Lua解释器,但是默认情况下并没有打开。安装Lua插件的方法是:
一个实用的Wireshark dissector为了演示如何用Lua脚本语言编写一个实用的Wireshark dissector插件,我设计了一个简单的网络协议——ScoreBoard。 ScoreBoard协议用于更新比分牌的数值和背景颜色。服务端监听UDP1127端口,客户端端口任意。 报文格式每个报文的前16字节是固定的识别符identifier: 第17字节表示报文类型operator:
数据部分:
交互流程
识别ScoreBoard协议的Wireshark插件do --协议名称为ScoreBoard,在Packet Details窗格显示为yoursunny.P2008.IS409 ScoreBoard local p_ScoreBoard = Proto("ScoreBoard","yoursunny.P2008.IS409 ScoreBoard") --协议的各个字段 local f_identifier = ProtoField.bytes("ScoreBoard.identifier","Identifier") local f_operator = ProtoField.uint8("ScoreBoard.operator","Operator",base.HEX, --这个字段的数字值都有相应的含义,可以自动对应成字符串 { [0] = "get-value", [1] = "set-value", [128] = "resp-value", [16] = "get-color", [17] = "set-color", [144] = "resp-color"}) --所有可能的字段都要定义,到时没有t:add就不会显示 local f_left = ProtoField.uint32("ScoreBoard.left","Value Left",base.DEC) local f_right = ProtoField.uint32("ScoreBoard.right","Value Right",base.DEC) local f_red = ProtoField.uint8("ScoreBoard.red","Color Red",base.DEC) local f_green = ProtoField.uint8("ScoreBoard.green","Color Green",base.DEC) local f_blue = ProtoField.uint8("ScoreBoard.blue","Color Blue",base.DEC) p_ScoreBoard.fields = { f_identifier, f_operator, f_left, f_right, f_red, f_green, f_blue } local data_dis = Dissector.get("data") local function ScoreBoard_dissector(buf,root) local buf_len = buf:len(); --先检查报文长度,太短的不是我的协议 if buf_len < 17 then return false end --取得前16字节identifier字段的值 local v_identifier = buf(0,16) --验证identifier是否正确 if ((buf(0,1):uint()~=226) or (buf(1,1):uint()~=203) or (buf(2,1):uint()~=181) or (buf(3,1):uint()~=128) or (buf(4,1):uint()~=203) or (buf(5,1):uint()~=9) or (buf(6,1):uint()~=78) or (buf(7,1):uint()~=186) or (buf(8,1):uint()~=163) or (buf(9,1):uint()~=107) or (buf(10,1):uint()~=246) or (buf(11,1):uint()~=7) or (buf(12,1):uint()~=206) or (buf(13,1):uint()~=149) or (buf(14,1):uint()~=63) or (buf(15,1):uint()~=43)) --不正确就不是我的协议 then return false end --取得operator的值 local v_operator = buf(16,1) local i_operator = v_operator:uint() --现在知道是我的协议了,放心大胆添加Packet Details local t = root:add(p_ScoreBoard,buf) --在Packet List窗格的Protocol列也可以“做个小广告” pkt.cols.protocol = "ScoreBoard" t:add(f_identifier,v_identifier) t:add(f_operator,v_operator) if ((i_operator == 1) or (i_operator == 128)) and (buf_len >= 25) then --把存在的字段逐个添加进去 t:add(f_left,buf(17,4)) t:add(f_right,buf(21,4)) elseif ((i_operator == 17) or (i_operator == 144)) and (buf_len >= 20) then t:add(f_red,1)) t:add(f_green,buf(18,1)) t:add(f_blue,buf(19,1)) end return true end function p_ScoreBoard.dissector(buf,root) if ScoreBoard_dissector(buf,root) then --valid ScoreBoard diagram else --data这个dissector几乎是必不可少的;当发现不是我的协议时,就应该调用data data_dis:call(buf,root) end end local udp_encap_table = DissectorTable.get("udp.port") --只需要处理UDP1127端口就可以了 udp_encap_table:add(1127,p_ScoreBoard) end 查看ScoreBoard协议的Wireshark插件效果演示,下载ScoreBoard协议的样例客户端脚本、服务端程序、pcap抓包、Lua插件源码 插件的调试我没有找到非常有效的插件调试方法。当Lua脚本中有语法错误时,Wireshark会在启动时弹出提示框;有调用错误时,会在相关数据包的Packet Details窗格中以红色显示。 你可以把捕获的数据包保存为.pcap文件,每次修改Lua脚本后双击.pcap文件打开Wireshark即可。不必每次都进行Live Capture。 小结Wireshark有了Lua支持后,如虎添翼,大大方便了插件的开发。当你发明了一个网络协议,要让Wireshark支持它的最佳办法就是动手用Lua语言写一个dissector。只要你充分理解自己设计的网络协议,结合Lua语言参考和Wireshark文档(不过有些函数名不够准确、请参考Wireshark源码),写出一个Wireshark插件还是挺容易的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |