This is a static archive of our old Q&A Site. Please post any new questions and answers at

writing dissector using lua scripts


Hello, I'm trying to write wireshark dissector using lua script. I look at the web pages for examples and explanations : However, i still have something that i do not understand. I receive data in EtherNet/IP (Industrial Protocol) using UDP. So i have something like that IP->UDP->EtherNet/IP --> My dissector Until now, i can use my dissector but it always start at the UDP data level. I want it to start and EtherNet/IP data level. Where should i do that ? And How can I do that ?

I have a doubt about three lines that should contains the modification : Maybe i should set root with something but i cannot find which one ? Where can i find information about that ?

local tree = root:add(cip, tvbuf:range(0,pktlen))

Maybe i need to set something different from "udp" here, but where can i find the string for EtherNet/IP protocol ?


Can anyone help me with that ? Thank you very much!

asked 24 Oct '17, 08:47

Nicolas2333's gravatar image

accept rate: 0%

Can you provide a sample capture file (a single packet should be enough)? As I don't know CIP, I cannot be more specific than below without seeing the packet.

CIP dissector is embedded to Wireshark so the first question is whether either the UDP dissector finds out using heuristic that the UDP payload is a CIP one or whether there is an IANA registered UDP port for CIP, which means that the dissector table udp.port would contain a line saying that for this port numberm CIP dissector should be invoked on the payload. If neither is true, you have to add such line to udp.port dissector table for the port number your equipment is using.

The second point is that you have to tell the CIP dissector itself that it should use your Lua dissector for particular types of its payload. The embedded CIP dissector uses two dissector tables: cip.class.iface and cip.data_segment.iface, and if your private payload can be identified using one of the fields used as indice to these tables, you have to register your dissector to one of these tables.

(25 Oct '17, 11:03) sindy

I know you probably wrote this as an answer because of the size.

Can you convert it to a comment, I've tried (after fixing the images for display in a comment) but some OSQA brokeness won't let me?

(26 Oct '17, 12:11) grahamb ♦

If you register your dissector with the UDP port then you will override the CIP dissector, hence the output you see.

You will need to hook your dissector into the CIP one via a dissector table, but I'm not sure if there is a suitable table to do so for a connected data item.

(26 Oct '17, 12:19) grahamb ♦

Placing my comment here as it would otherwise disappear once you would convert your "Answer" into a comment as @grahamb has asked you to.

I am a bit confused by seeing UDP port 2222 on your pictures and 65533 in your Lua code. As you've guessed yourself and as @grahamb wrote, the Lua line below replaces the original CIP dissector (which handles ENIP as well as the two are close twins) by your cip_ddu one (the add method is actually a replace if there already is a record for that index) in UDP dissector's only dissector table (udp.port) for port 65533, but it should not do so for port 2222.

If you are lucky, replacing the line
DissectorTable.get("udp.port"):add(65533, cip_ddu)
DissectorTable.get("cip.data_segment.iface"):add(0xb1, cip_ddu)
(or, possibly, by DissectorTable.get("cip.data_segment.iface"):add(0x31, cip_ddu))
could hook your cip_ddu dissector to the right place.

If you are not lucky, you'll have to extend your Lua dissector with a part duplicating the functionality of the embedded CIP/ENIP dissector as it would mean that none of the existing one's hook points (dissection tables) is the right one you need, and you would hook that extended one to the udp.port table.

(26 Oct '17, 13:14) sindy

Hello, Thank you for your help. I will try that. I will also try to change the answer i made yesterday to comment. It's not working just now. Thank you

(27 Oct '17, 09:39) Nicolas2333

One Answer:


Hello, Thank you for your answer. In fact, actually, using wireshark without the dissector I wrote, i get the Capture_CIP.jpg image. The ENIP protocol is used with UDP protocol. I want to add a dissector to parse the data part at the end of the ENIP packet. "Data : 7905010000..."

To do that i wrote the following lua script: -- creates a Proto object, but doesn't register it yet local cip_ttt = Proto("myCIP","CIP Sub Protocol")

-- multiple ways to do the same thing: create a protocol field (but not register it yet)
local pf_header             =    ("Header", "myCIP.header", ftypes.UINT32)
local pf_div1               =    ("Div1", "myCIP.Divers_1", ftypes.UINT32)
local pf_div2               =    ("Div2", "myCIP.Divers_2", ftypes.UINT32)
local pf_div3               =    ("Div3", "myCIP.Divers_3", ftypes.UINT16)
local pf_IO_Byte1           =    ("IO Table Byte 1", "myCIP.IOByte1", ftypes.UINT8, nil, base.HEX)

local pf_IO_24_2 = ("Bit8", "myCIP.pf_IO_Byte1.bit8", ftypes.BOOLEAN, nil, 8, 0x80) local pf_IO_24_1 = ("Bit7", "myCIP.pf_IO_Byte1.bit7", ftypes.BOOLEAN, nil, 8, 0x40) local pf_IO_14_5 = ("Bit6", "myCIP.pf_IO_Byte1.bit6", ftypes.BOOLEAN, nil, 8, 0x20) local pf_IO_14_4 = ("Bit5", "myCIP.pf_IO_Byte1.bit5", ftypes.BOOLEAN, nil, 8, 0x10) local pf_IO_14_3 = ("Bit4", "myCIP.pf_IO_Byte1.bit4", ftypes.BOOLEAN, nil, 8, 0x08) local pf_IO_14_2 = ("Bit3", "myCIP.pf_IO_Byte1.bit3", ftypes.BOOLEAN, nil, 8, 0x04) local pf_IO_14_1 = ("Bit2", "myCIP.pf_IO_Byte1.bit2", ftypes.BOOLEAN, nil, 8, 0x02) local pf_IO_13_1 = ("Bit1", "myCIP.pf_IO_Byte1.bit1", ftypes.BOOLEAN, nil, 8, 0x01)

cip_ddu.fields = {pf_header, pf_div1, pf_div2, pf_div3, pf_IO_Byte1, pf_IO_24_2, pf_IO_24_1, pf_IO_14_5, pf_IO_14_4, pf_IO_14_3, pf_IO_14_2, pf_IO_14_1, pf_IO_13_1 }

function cip_ddu.dissector(tvbuf,pktinfo,root) – set the protocol column to show our protocol name pktinfo.cols.protocol:set("CIP_perso")

local pktlen = tvbuf:reported_length_remaining()
local tree = root:add(cip_ddu, tvbuf:range(0,pktlen))

--tree:add(pf_trasaction_id, tvbuf:range(0,2))
tree:add(pf_header, tvbuf:range(0,4))

-- add other fields divx
tree:add(pf_div1, tvbuf:range(4,4))
tree:add(pf_div2, tvbuf:range(8,4))
tree:add(pf_div3, tvbuf:range(12,2))

-- add subtree for IO
local IO_byte1 = tvbuf:range(14,1):uint()
local IO_byte1_tree = tree:add(pf_IO_Byte1, IO_byte1)

IO_byte1_tree:add(pf_IO_24_2, IO_byte1)
IO_byte1_tree:add(pf_IO_24_1, IO_byte1)
IO_byte1_tree:add(pf_IO_14_5, IO_byte1) 
IO_byte1_tree:add(pf_IO_14_4, IO_byte1)     
IO_byte1_tree:add(pf_IO_14_3, IO_byte1)     
IO_byte1_tree:add(pf_IO_14_2, IO_byte1)
IO_byte1_tree:add(pf_IO_14_1, IO_byte1)
IO_byte1_tree:add(pf_IO_13_1, IO_byte1)


DissectorTable.get("udp.port"):add(65533, cip_ddu) –DissectorTable.get("etherip"):add(65533, cip_ddu) –local enip_dissector_table = DissectorTable.get("etherip") –enip_dissector_table:add(65533,cip_ddu)

With this script, i got the Capture_Actual_Dissector.jpg image.

The problem i meet, is that my dissector starts from the UDP Data packet, and not the data from the ENIP packet. I think it is due to this line:

DissectorTable.get("udp.port"):add(65533, cip_ddu)

But i do not know how to change it and with which code in order to to what i want. Can you help me understand what’s wrong in my script and what’s the best solution ? Thank you very much.

answered 26 Oct ‘17, 09:25

Nicolas2333's gravatar image

accept rate: 0%

edited 26 Oct ‘17, 12:08

grahamb's gravatar image

grahamb ♦