Wireshark supports thousands of protocols now. But there are still some new protocols not supported and private protocols are not either. Fortunately, we can write dissectors by ourselves and add them to wireshark without changing wireshark source code.
Wireshark supports plug-ins developed by C or Lua. Comparing with C, Lua is a script language, platform independent and easy for debugging. Here is an example of developing wireshark plug-in by Lua.
Suppose we want to develop a dissector for DHCPv4 Bulk Leasequery. It is TCP based protocol and one DHCPv4 Bulk Leasequery packet includes two parts, 1: size of the remaining part (2 bytes), 2: a bootp packet contains Leasequery information.
To make it simple, we take an assumption, one TCP packet contains only one Leasequery packet and there is no TCP reassemble issue.
In the script, first, we define a new protocol p_lqv4
and the two fields f_size
, f_text
, which consist of leasequery packet. Then the most important part, dissector function p_lqv4.dissector(buf, pkt, root)
, the input paramter buf
is the data buffer for this dissector to parse and the pkt
is the packets information for reassemble, etc; and the root
is the parsed protocol tree shown in the “Packet Details” pane.
do
local p_lqv4 = Proto("lqv4","Leasequery v4");
local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
local f_text = ProtoField.string("lqv4.content","bin")
p_lqv4.fields = { f_size, f_text }
function p_lqv4.dissector(buf, pkt, root)
local totalsize = buf:len()
if leftsize <= 2 then
return
end
local size = buf(0,2):uint()
local t = root:add(p_lqv4,buf(0,totalsize))
t:add(f_size,buf(0,2))
local dissector = Dissector.get("bootp")
if dissector ~= nil then
dissector:call(buf(2,size):tvb(),pkt,t)
end
end
local wtap_encap_table = DissectorTable.get("wtap_encap")
local tcp_encap_table = DissectorTable.get("tcp.port")
wtap_encap_table:add(wtap.USER15,p_lqv4)
wtap_encap_table:add(wtap.USER12,p_lqv4)
tcp_encap_table:add(67,p_lqv4)
end
When there are multi-leasequery messages in one TCP packet, we can use a cursor offset
to indicate the start of one leasequery packet and use while
to go through each leasequery packet inside the TCP packet.
do
local p_lqv4 = Proto("lqv4","Leasequery v4");
local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
local f_text = ProtoField.string("lqv4.content","bin")
p_lqv4.fields = { f_size, f_text }
function p_lqv4.dissector(buf, pkt, root)
local offset = 0
local totalsize = buf:len()
local leftsize = buf:len()
while leftsize > 0 do
local size = buf(offset,2):uint()
local nxtpdu = offset + size + 2
local t = root:add(p_lqv4,buf(offset,2))
t:add(f_size,buf(offset,2))
local dissector = Dissector.get("bootp")
if dissector ~= nil then
dissector:call(buf(offset+2,size):tvb(),pkt,t)
end
offset = nxtpdu
leftsize = buf(offset):tvb():len()
end
end
local wtap_encap_table = DissectorTable.get("wtap_encap")
local tcp_encap_table = DissectorTable.get("tcp.port")
wtap_encap_table:add(wtap.USER15,p_lqv4)
wtap_encap_table:add(wtap.USER12,p_lqv4)
tcp_encap_table:add(67,p_lqv4)
end
In order to support TCP reassemble, we need to us two parameters desegment_len
and desegment_offset
in the input parameter pkt
. desegment_len
is a variable to indicate wireshark how many bytes needed to complete this parse, wireshark will try to find the following packets to reassemble them together. desegment_offset
is a cursor indicates how many bytes have been processed.
do
local p_lqv4 = Proto("lqv4","Leasequery v4");
local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
local f_text = ProtoField.string("lqv4.content","bin")
p_lqv4.fields = { f_size, f_text }
function p_lqv4.dissector(buf, pkt, root)
local offset = pkt.desegment_offset or 0
local totalsize = buf:len()
local leftsize = buf:len() - offset
if leftsize < 2 then
pkt.desegment_len = DESEGMENT_ONE_SEGMENT
pkt.desegment_offset = offset
return
end
local size = buf(offset,2):uint()
local nxtpdu = offset + size + 2
if nxtpdu > totalsize then
pkt.desegment_len = nxtpdu - buf:len()
pkt.desegment_offset = offset
return
end
local t = root:add(p_lqv4,buf(offset,2))
t:add(f_size,buf(offset,2))
local dissector = Dissector.get("bootp")
if dissector ~= nil then
dissector:call(buf(offset+2,size):tvb(),pkt,t)
end
end
local wtap_encap_table = DissectorTable.get("wtap_encap")
local tcp_encap_table = DissectorTable.get("tcp.port")
wtap_encap_table:add(wtap.USER15,p_lqv4)
wtap_encap_table:add(wtap.USER12,p_lqv4)
tcp_encap_table:add(67,p_lqv4)
end
Combining the above three parts described in Chapter 3 together, then we have a full-featured dissector shown as below. This DHCPv4 Leasequery dissector supports multi leasequery messages within one TCP packet and TCP reassemble for Leasequery message. The following gives the complete code of this dissector.
--[[
This is for DHCPv4 Bulk leasequery dissector,
For Windowns, cp this file to System\Program Files\Wireshark
For Linux, cp this file to /etc/wireshark
Add "dofile("packet_lqv4.lua")" to the bottom of File "init.lua"
Author: ylxxwx@gmail.com
--]]
do
local p_lqv4 = Proto("lqv4","Leasequery v4");
local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
local f_text = ProtoField.string("lqv4.text","Text")
local p_port = 67
p_lqv4.fields = { f_size, f_text }
function p_lqv4.dissector(buf,pkt,root)
local offset = pkt.desegment_offset or 0
local totalsize = buf:len()
local leftsize = buf:len() - offset
while leftsize > 0 do
if leftsize < 2 then
pkt.desegment_len = DESEGMENT_ONE_SEGMENT
pkt.desegment_offset = offset
return offset
end
local size = buf(offset,2):uint()
local nxtpdu = offset + size + 2
if nxtpdu > totalsize then
pkt.desegment_len = nxtpdu - totalsize
pkt.desegment_offset = offset
return
end
local lqblock = root:add(p_lqv4,buf(offset,size + 2))
lqblock:add(f_size,buf(offset,2))
local dissector = Dissector.get("bootp")
if dissector ~= nil then
dissector:call(buf(offset+2,size):tvb(),pkt,lqblock)
end
pkt.cols.protocol = "DHCPv4BulkLeasequery"
offset = nxtpdu
leftsize = buf(offset):tvb():len()
if leftsize == 0 then
pkt.desegment_len = 0
pkt.desegment_offset = 0
return
end
end
end
local wtap_encap_table = DissectorTable.get("wtap_encap")
local tcp_encap_table = DissectorTable.get("tcp.port")
wtap_encap_table:add(wtap.USER15,p_lqv4)
wtap_encap_table:add(wtap.USER12,p_lqv4)
tcp_encap_table:add(p_port,p_lqv4)
end
Click Menu
->Help
->About Wireshark
. If you find without Lua
, you need to upgrade wireshark to the latest version. If you find with Lua 5.2
, congratulations. You can go to 5.2.
Copy the dissector to wireshark directory. In different system the wireshark directory is different, shown below.
System | Path |
---|---|
windows | System\Program Files\Wireshark |
Linux | /etc/wireshark |
Add dofile("[dissector file]")
to the file init.lua
which locates in the wireshark directory. Then restart wireshark. It works.
原文:http://www.cnblogs.com/ylxxwx/p/4985379.html