[Development] Wireshark dissector LUA script programming guide === ###### tags: `development`, `LUA`, `tool`, `wireshark`, `lua`, `dissector` [ToC] # Introduction In order to dissect captrued packets in Wireshark, we need to write a script which is a programming language named lua. ![](https://i.imgur.com/YJ6P5oG.png) The dissector we write will show in packet info (pinfo) of packet list and a tree in packet decode. In this article, I will show how to write this lua script and what will we see and what will we get for each line of lua code. ## Lua > Lua (/ˈluːə/ LOO-ə; from Portuguese: lua [ˈlu.(w)ɐ] meaning moon)[a] is a lightweight, high-level, multi-paradigm programming language designed primarily for embedded use in applications.[2] Lua is cross-platform, since the interpreter of compiled bytecode is written in ANSI C,[3] and Lua has a relatively simple C API to embed it into applications.[4] > > Lua was originally designed in 1993 as a language for extending software applications to meet the increasing demand for customization at the time. It provided the basic facilities of most procedural programming languages, but more complicated or domain-specific features were not included; rather, it included mechanisms for extending the language, allowing programmers to implement such features. As Lua was intended to be a general embeddable extension language, the designers of Lua focused on improving its speed, portability, extensibility, and ease-of-use in development. ## Dissectors > Dissectors are meant to analyze some part of a packet's data. They are similar to their older brothers written in C. Note that Heuristic Dissectors and Post-Dissectors operate differently, and are described separately. This section only refers to pure Dissectors. They have to be registered to handle a type of payload of another protocol (or a raw wiretap type). To be registered, the dissector function has to be assigned to a Proto object. (see examples below) > >When called by Wireshark, they are passed (1) a TVB buffer of the data (a Tvb object), (2) a packet information record (Pinfo object), and (3) a tree root (TreeItem object). > >Dissectors only get called when the packet matches the DissectorTable the Proto is set to, or when the user forces it using "Decode As". > >The user can only "force" it using "Decode As" if the DissectorTable you set your Proto object to is of the correct type; for example, if you set your Proto object to the udp DissectorTable, a user cannot try to decode a link layer using your Proto dissector. Before getting start, we can see that in the window of Wireshark as shown below. The window is composed of three blocks which are packet list, packet decode and packet byte view, respectively. # Implementation ```lua= -- Register a protocol named MSP and followed with its description. -- "MSP" will show in the column of packet list -- "My Simple Protocol" will show in the tree of packet decode msp = Proto("MSP", "My Simple Protocol") -- Create some local variable and array ,and -- these variables will be used in the tree in packet decode local f = msp.fields local vs_state = {[0]="normal",[1]="abnormal"} local vs_pstate = {[0]="Down",[1]="PS1",[2]="PS2",[3]="PS3",[4]="PS4",[5]="PS5",[6]="PS6",[7]="PS7",[8]="PS8",[9]="PS9",[10]="PS10"} local vs_xpstatus = {[0]=" (both Link up)",[1]=" (A down/B up)",[2]=" (A up/B down)",[3]=" (both Link down)"} local vs_msrBP = {[0x00000000]= "N/A",[0x000001]="port 0",[0x000002]="port 1",[0x000004]="port 2",[0x000008]="port 3",[0x000010]="port 4",[0x000020]="port 5",[0x000040]="port 6",[0x000080]="port 7",[0x000100]="port 8",[0x000200]="port 9",[0x000400]="port 10",[0x000800]="port 11",[0x001000]="port 12",[0x002000]="port 13",[0x004000]="port 14",[0x008000]="port 15",[0x010000]="port 16",[0x020000]="port 17",[0x040000]="port 18",[0x080000]="port 19",[0x100000]="port 20",[0x200000]="port 21",[0x400000]="port 22",[0x800000]="port 23",[0x1000000]="port 24",[0x2000000]="port 25",[0x4000000]="port 26",[0x8000000]="port 27",[0x10000000]="port 28",[0x20000000]="port 29",[0x40000000]="port 30",[0x80000000]="port 31"} -- Create some fields in the protocol tree of packet decode, and -- these fields are followed with data type such as -- string, ether mac, int16, uint32 and so on -- And when the data type is set as a uint, we can designated it as -- decimal or heximal and so on f.packetType = ProtoField.string("msp.packetType","LLC Type") f.myId = ProtoField.uint16("msp.myId", "My ID") f.state = ProtoField.uint16("msp.state", "My State",base.DEC,vs_state) f.myMaster = ProtoField.ether("msp.myMaster","My Master") f.Priority = ProtoField.uint16("msp.Priority", "Priority") f.Period = ProtoField.uint32("msp.Period", "Period (s)") f.gcstatus = ProtoField.uint16("msp.gcstatus", "GC Status",base.DEC,vs_pstate) f.e_num = ProtoField.uint16("msp.e_num", "Enabled num") f.a_num = ProtoField.uint16("msp.a_num", "All num") f.BP = ProtoField.uint32("msp.BP", "BP", base.HEX,vs_msrBP) f.plstatus = ProtoField.uint16("msp.plstatus", "PLStatus",base.DEC,vs_xpstatus) f.pstate = ProtoField.uint16("msp.pstate", "Port State",base.DEC,vs_pstate) f.pId = ProtoField.uint16("msp.pId", "PID") f.mypSender = ProtoField.ether("msp.mypSender","Packet Sender") -- This just a packet counter and it is not used here local packet_counter function msp.init() packet_counter = 0 end -- This function is regarded as the main function that -- the argument buffer is the source of packet contents ,and -- pinfo and tree are the object to display our info function msp.dissector(buffer, pinfo, tree) local subtree = tree:add(msp, buffer()) local packetType -- retrieve the last byte of a substring -- in the destination col in the info. if string.sub(tostring(pinfo.dst),-1)=='2' then packetType="DOWN" elseif string.sub(tostring(pinfo.dst),-1)=='3' then packetType="UP" else packetType="WD" end subtree:add(f.packetType, packetType) -- decode the packet from offset 0 and count it down after decoding local offset=0 -- decode for each field in the tree if packetType=="WD" then local myId = buffer(offset,1) subtree:add (f.myId, myId) offset=offset+1 local state = buffer(offset,1) subtree:add(f.state, state) offset=offset+1 local myMaster = buffer(offset,6) subtree:add(f.myMaster, myMaster) offset=offset+6 offset=offset+1 local Priority = buffer(offset,1) subtree:add(f.Priority, Priority) offset=offset+1 local Period = buffer(offset,2) subtree:add(f.Period, Period) offset=offset+2 local gcstatus = buffer(offset,1) subtree:add(f.gcstatus, gcstatus) offset=offset+1 local e_num = buffer(offset,1) subtree:add(f.e_num, e_num) offset=offset+1 local a_num = buffer(offset,1) subtree:add(f.a_num, a_num) offset=offset+1 local BP = buffer(offset,4) subtree:add(f.BP, BP) offset=offset+4 local plstatus = buffer(offset,1) subtree:add(f.plstatus, plstatus) offset=offset+1 -- modify the info columns in the packet list pinfo.cols['protocol'] = "MSP" pinfo.cols.info = "My Ptype: "..pType pinfo.cols.info:append(", ID: ") pinfo.cols.info:append(myId:uint()) pinfo.cols.info:append(", rstatus: ") pinfo.cols.info:append(vs_state[state:uint()]) pinfo.cols.info:append(", MyMaster: "..tostring(myMaster)) pinfo.cols.info:append(", plstatus: ") pinfo.cols.info:append(plstatus:uint()) else local pstate = buffer(offset,1) subtree:add (f.pstate, pstate) offset = offset+1 local pId = buffer(offset,1) subtree:add (f.pId, pId) offset = offset+1 local mypSender = buffer(offset,6) subtree:add (f.mypSender, mypSender) offset = offset+6 local myId = buffer(offset+1,1) subtree:add (f.myId, myId) offset=offset+1 pinfo.cols['protocol'] = "MSP" pinfo.cols.info = "Ptype: "..packetType pinfo.cols.info:append(", ID: ") pinfo.cols.info:append(myId:uint()) pinfo.cols.info:append(", my p node "..tostring(mypSender)) pinfo.cols.info:append(" pid "..pId:uint().." is ") pinfo.cols.info:append(vs_pstate[pstate:uint()]) end end -- this sub dissector MSP is from LLC protocol -- start with a byte value = 0x6b local llc_table = DissectorTable.get("llc.dsap") llc_table:add(0x6b, msp) ``` # Outcomes Below figure is the result of our dissector, and it is clear to see that we decode all bytes we desired successfully. ![](https://i.imgur.com/r9AndV6.png) # Reference - [Wireshark Dissector Lua API](https://wiki.wireshark.org/LuaAPI/Dissector) - [Wireshark Dissector Lua Examples](https://wiki.wireshark.org/Lua/Dissectors#Examples) - [Wireshark lua script usage guide](http://albert-oma.blogspot.com/2016/06/wireshark-lua-script.html)