Create a Wireshark dissector in Lua

You have a custom protocol and would like to give your users the ability to visualize it in Wireshark? If your answer is yes, this post is for you.

I recommend using Wireshark’s embedded Lua interpreter, and its API for Lua. It is the easiest way to prototype dissectors which, for performance reasons, may later be rewritten in C. At the time of writing, I am still using Wireshark 1.2.1, but you might consider using the latest version.

Let us begin with some sample code.

Protocol dissector script in Lua

We use a chained dissector, it adds functionality to dissect packets of an existing protocol, such as packets destined to a particular tcp port. It receives only the payload part of the original protocol packet as the input buffer in the dissector function.

Running the Lua script in Wireshark

Here are the steps required to get the above code running. If your Wireshark version is 1.4 or better, skip step 3.

  1. Edit and save the lua script above to any folder (e.g. c:\myproto) and call the file myproto.lua
  2. Open init.lua in the Wireshark installation directory for editing. You will need Admin privileges on Windows Vista and 7.
  3. Comment out the following line in init.lua (single line comments begin with --):
    disable_lua = true; do return end;
  4. Add the following lines to init.lua (at the very end):
  5. Change MYPROTO_SCRIPT_PATH to point to the folder where you saved the script in step 1
  6. Run Wireshark
  7. Load a capture file that has the packets of your custom protocol or start a live capture

Here’s a figure that shows the protocol dissector in action.


50 thoughts on “Create a Wireshark dissector in Lua

  1. Hello, I am using ubuntu 11.10

    I followed your method along with if 0 and running_superuser then
    local disabled_lib = {}
    to make Lua work its still throwing out dofile disabled error.

    i am using 1.6.2 version

  2. Hello,
    I am trying to isolate a custom protocol that comes in the data part of udp using Lua scripts in Wireshark. How can i recognize these with flag values of the custom headers that come sequncially after udp headers in udp’s data.
    Any Idea where there is a proper list of comands pertaining to wireshark-lua script writing.
    A big Thanx in Advance.

    I am using latest wireshark version.

    Edwin Abraham

    1. Writing a dissector for UDP is very much like writing a dissector for TCP. You can register to dissect UDP packets with a particular port as follows

      local udp_dissector_table = DissectorTable.get("udp.port")
      dissector = udp_dissector_table:get_dissector(8002)
        -- you can call dissector from function p_myproto.dissector above
        -- so that the previous dissector gets called
      udp_dissector_table:add(8002, p_myproto)

      For help on Wireshark’s LUA API please refer to For Lua related information see the manual at

      1. Okay suppose I did this. How does Wireshark know that this is my custom protocol. Like where is the filter option there? Lets say I can check that this is my custom protocol with a flag. Anyway of getting the data part of udp and then compare it?
        and is there a way to tell wireshark to look at all my udp ports not just a specific one?

        1. Q. Okay suppose I did this. How does Wireshark know that this is my custom protocol.

          A. You create a new Proto object, that is how it knows.

          Q. Like where is the filter option there? Lets say I can check that this is my custom protocol with a flag.

          A. You specify the fields by setting the fields property of your Proto object. You can add fields dynamically from the dissector function of your Proto object by using the root parameter. Wireshark cannot filter based on those fields though. You don’t need any additional flags, you can filter packets based on the procotol name to begin with.

          Q. Anyway of getting the data part of udp and then compare it?

          A. You can use the buf object, a parameter of the dissector function, to get the data and do whatever you want with it.

          Q. …and is there a way to tell wireshark to look at all my udp ports not just a specific one?

          A. You can register your protocol dissector against as many ports as you wish. Just repeat the following several times with different port numbers

          dissector = udp_dissector_table:get_dissector(8002)
          udp_dissector_table:add(8002, p_myproto)
  3. Thanx for the info firstly. One last question.

    The protocol I have to recognize is a udp packet where the data part of udp will act as headers for the rest of the data in the packet. Its a completely new packet and only way to Identify whether the udp that comes is of that custom protocol is a field that is 12th (unsigned long) from the udp headers. Now I defined all the names of the headers with uint32. But it still doesn’t understand that its myproto. I feel its because I haven’t asked it to recognize that. Now the only way it will recognize is by comparing the 12th uint32 data with some value.

    I understood the part of the udp ports , the protocol creation, but from the udp packet how will it know its my packet. For that what do I do? You said with the name of the protocol. But from where the packet?

    1. You can do that with something like the following in the dissector function

      if buf(11):uint() == val then
        -- dissect
        -- call the previous dissector and quit
        dissector:call(buf, pkt, root)
  4. Hello!
    Thanks you for yours tutor. I have a problem with my dissector, and i need yours help. After running LUA script, I want to count total packets that appear in myproto. So, i dont know how to do :|. Can u help me,pls?.
    Sorry my english is not good

    1. Hello! The dissector function is called once for each packet. You can maintain a global counter (defined outside the function) and increment it each time the dissector function is called, e.g.

      local count = 0
      function p_myproto.dissector (buf, pkt, root)
        count = count + 1
  5. Hi,
    I see the following error thrown while the Wireshark GUI loads:
    Lua: Error during loading:
    C:\Program Files\Wireshark\myproto.lua:1: unexpected symbol near ‘{‘

    I have copied the script as is and placed “myproto.lua” in folder where “init.lua” is located (c:\Program Files\Wireshark )and added

    dofile(“myproto.lua”) at the end .

    Request to please help solve the issue

    1. Hi Santosh. The code as posted should work. Check that you didn’t add any extra characters into the script by mistake. Please tell more about your environment – OS version, Wireshark version etc.

      1. Devendra,
        Thanks I actually posted it on a rtf file that had extra charecters appended before the actual script. I used notepad and its fine now and working.

        Thanks for the post as it is tailor made for my use.

        Wanted to know are there ways to convert the hex data in the payload and display it as a decimal value when we expand the subtree for the custom protocol.

        Ex. Subtree lists “Squence Number: 3886” , for the value 0f2e in the payload.

        I use wireshark version 1.8.0 on Windows XP


        1. Hi Santosh. The buf parameter of the dissector function is of type Tvb. You can obtain a TvbRange by doing something like buf(offset, 2). TvbRange has methods that return integer and other values. For your case you can use something like buf(offset, 2):uint(). Remember to change offset to the position in the buffer you want to read your value from. If the byte order of the data is little endian you can use le_uint. Follow the Wireshark Lua API link above for further details.

  6. Thanks Devendra.
    I was able to get my requirement of the previous post however, facing the issue while adding new protocol fields.

    only buf(x,x) ; where x=0,1,2,3,4 are accepted

    i.e, for Ex.If I attempt subtree:add(f_command, buf(4,5)) or subtree:add(f_command, buf(5,5)),

    It fails with error thrown as, [Dissector bug, protocol KODRTPOTCP: proto.c:1115: failed assertion “DISSECTOR_ASSERT_NOT_REACHED”].

    Can you please let me know what could be the problem.


    1. You are most certainly exceeding the bounds of the buffer. You should create a TvbRange like buf(offset, length). The second parameter is the length of the field, not the end index/offset.

        1. It is intelligent enough to determine that the range has just 2 bytes (16 bits) and create an integer value from that. I hope that answers your question. If not, I don’t understand your question.

  7. Yes it’s obvious. Missed it. Thanks.

    I plan to use control structure (if/else) and depending upon the value of payload data decoded, append text to the subtree, but I am facing issue in the same.

    local f_cmd = ProtoField.uint32(“Koproto.cmd”, “Version”,base.DEC)

    The above command displays the Version in subtree (as 2) correctly but when I use it in if/else statement, it’s not able to resolve, i.e

    if f_cmd == 2 then
    subtree:add(f_cmd, buf(1,1)):append_text(” Version is 2″)
    subtree:add(f_cmd, buf(1,1)):append_text(” Version is not 2″)

    This Is failing.

    Unfortunately cannot print the value of “f_cmd” to verify what it holds actually.

    Can you please let me know what could be the issue?


    1. f_cmd is like a template, not the actual field. You can read the value directly from buf as TvbRange and using one of its methods, then use that value in the if statement.

  8. Hi,
    Thanks for your reply.
    I face following error when I tried working with bitstring:

    Lua: Error during loading:
    error loading module ‘bitstring’ from file ‘C:\Program Files\Wireshark\bitstring.dll’:
    %1 is not a valid Win32 application.

    Can I know what could be the reason for the same?

    Followed following steps:
    1. Copy ‘bitstring.dll’ to your wireshark directory. This file provides ‘bitstring’ library for Lua.
    2. Copy ‘coap.lua’ to somewhere in your wireshark directory. For example, /plugins/coap/coap.lua.
    3. Open ‘init.lua’ in your wireshark root directory. Comment the line ‘disable_lua = true’ or change it to ‘disable_lua = false’.
    4. Add ‘dofile(“/plugins/coap/coap.lua”)’ at the end of the file(init.lua)

  9. I made a slight change to associate the dissector with port 80 because I have a test pcap with that traffic. At the bottom of the page in the screenshot shows a filterable field called myproto.command that links to 0x ebff. When I run this script it parses out the bytes but my bytes (2 bytes from traffic) show up as text. If this data is text then I cannot filter or use tshark command. Can you shed some light on this matter? I have tried a lot of different things and cannot get it to work:( Also, I am evaluating the lua script directly in wireshark via the evaluate option and then I refresh my test pcap.

  10. Hello, I’m trying to create a protocol using Lua. But I want to put the protocol defined in analyze- enabled protocols in wireshark. If you do not mind Do you think you can help me?

    1. If I understand you correctly, you want the protocol to appear in the dialog that appears when you go to the Analyze menu and select Enabled Protocols…

      That being the case, there is nothing you need to do. If you’ve created the dissector as shown above, it will appear in the Enabled Protocols dialog.

  11. Sir, how do I use bitfield function to extract values from a 2 byte buffer, suppose I want firt 6 bit value from byte 1 then remaining 10 bit value from byte 1 & 2. Please help me.

      1. Sir, how to extract bit field values when 2 byte data is in little endian format . How could I convert the little endian byte into big endian byte order.

  12. Thank you for the guide Devendra. This is my first dissector, and it has been a big help.

    My main goal is to see the Message ID value in the packet columns, for quick reference. Would I go about this by printing that string to the Info column, or into a separate column?

    Would you be able to give me an example of how to correlate a range of hex to assigned string values? There is a 4 byte range in the data I need to dissect into about a dozen specific message types. (e.g. 00:1d:0f:01 = “Request Connect”, 00:1d:0b:01 = Keepalive, etc)

    I was hoping to make something that looked like:

    My Protocol
    Message ID: [convert hex values to defined message type e.g. “Request Connect” or “Keepalive” ]
    Payload size: [in bytes]
    Payload: [ display text, pulled from data, depending on payload size]
    Port #: [numerical]

    Thanks in advance!

  13. I figured out how to build a table to match multiple message types. I also figured out how to append info to a packet list column.

    I still can’t figure out how to create a new column, for that info, from within the script. Do you have any idea if that is possible?


    1. There’s no documented way to add additional columns. Suggest adding information to dissection tree below, and/or append to Glad you figured the rest.

  14. Hi Devendra,
    Thank you for the wonderful tutorial. I am facing an issue when registering the dissectors in init.lua file. So for I have created four different dissectors for 4 different types of TCP Packets and I have registered the dissectors in the same way that you have specified. When I was created the first three dissectors and added them to init.lua, on opening up wireshark, the dissectors were able to correctly dissect the packets. However after creating the fourth dissector and adding it to init.lua, upon reopening wireshark, the dissectors stopped working altogether. If I make arbitrary changes in the ordering of dissectors in init.lua, then one or two of these dissectors work. I find this issue quite strange enough. Please let me know what could be done in this situation.

    Thanks in Advance.

  15. Thanks for your post, it’s really helpful.
    Only one more question: I’m trying to write dissector for a special case.
    I use ENIP protocol on UDP. I want to write a dissector to decode data part of the ENIP protocol.
    Until now, the dissector i wrote is beginning dissection on UDP.
    How can I configure dissector to start at the beginning of data part of ENIP protocol ? Do I need to create dissector for ENIP protocol as if it is already existing in wireshark ?
    Thank you

  16. Thank you Devendra,
    My question is more where should I define the start of my dissector in the lua script ?
    I try different things to configure my lua script to start at data part of enip protocol. But i always get an error such as “no such dissector table”.
    In order to dissect data in enip protocol, i try things such as :
    enip_dissector_table = DissectorTable.get(“enip.encap_data”)
    where cip_inside is the dissector i define in my lua script.

    If i use “DissectorTable.get(“udp.port”):add(65533, cip_ddu)” my dissector start in the UDP packet.

    Do you have any idea where is my error ?

    Thank you,

    1. I am not familiar with ENIP protocol, but there is no subdissector table called enip.encap_data in the dissector, so you’ll not be able to call DissectorTable.get with that name. If you look at function proto_register_enip in packet-enip.c, it registers subdissector table names enip.sud.iface, enip.srrd.iface, and I believe none of these are useful.

      If I understand you correctly, you want to dissect the content of enip.encap_data field. Assuming you’ve registered your own dissector with udp.port, you can first call the enip (or cip) dissector from your protocol’s dissector function, as follows

          local proto = Dissector.get("enip")
          if proto ~= nil then
              proto:call(buf, pkt, root)
              -- dissect enip.encap_data now

      You can use the information in post to recover enip.encap_data field and dissect it.

      Hope that helps.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s