Highlighting problems in Lua dissectors


Here’s a snippet of code from nordic_ble dissector that shows how you can highlight problems in Lua dissectors using add_expert_info

        local item  = tree:add_le(hf_nordic_ble_micok, tvb(UART_PACKET_FLAGS_INDEX, 1), micok > 0)
        if micok == 0 then
            -- MIC is bad
            item:add_expert_info(PI_CHECKSUM, PI_WARN, "MIC is bad")
            item:add_expert_info(PI_UNDECODED, PI_WARN, "Decryption failed (wrong key?)")

NOTE I recommend using add_proto_expert_info because add_expert_info is now deprecated.

Advertisements

Wireshark dissector in Lua for custom protocol over WebSockets


It is fairly easy to write a Wireshark dissector in Lua for your custom protocol over WebSockets. To understand the basics of writing, and using, dissectors for Wireshark in Lua, see Create a Wireshark dissector in Lua.

Here’s a template to get you started with writing your custom dissector. Replace port number 8002, with the port number where your WebSocket server listens for incoming connections, and the dissector should be called.

wireshark-websocket.png

You can also register the dissector using declared WebSocket protocol name. Retrieve the ws.protocol dissector table instead of ws.port, and add your dissector to the dissector table using protocol name (a string) instead of port number.

If using WebSockets over SSL/TLS, you need to specify the server’s private key file in SSL protocol dissector‘s configuration, so that Wireshark can decrypt the traffic. The protocol field in configuration should be set to http.

Analyzing iBeacon traffic using nRF BLE Sniffer


I’ve been troubleshooting iBeacons lately, and Bluetooth LE Sniffer from Adafruit is my go-to tool for sniffing Bluetooth LE (BLE) traffic such as iBeacon advertisements. iBeacon detection can vary a lot depending on advertisement interval and timing, and signal strength and its variance with distance, line of sight (or lack thereof), interference with other iBeacons etc.

nRF Sniffer software captures all BLE traffic in libpcap format that can be viewed in Wireshark 2.4. If you’re using an older version of Wireshark, I have ported the native dissector to Lua that should work starting from Wireshark 1.12.

Here’s an iBeacon advertisement dissected using the nordic_ble Lua dissector, and Wireshark’s native btle dissector, on OS X. Note that iBeacon payload proprietary to Apple is not yet decoded by Wireshark’s btle dissector.

btle_adv_ind.png

Using data from the packet shown above, Apple’s proprietary payload has the following format

02 - ID
15 - Length (21 bytes)
3aa46f0c80784773be800255132aefda - 128-bit UUID
e4f2 - major number
e4c1 - minor number
b6 - two's complement of calibrated TX power

A filter such as btcommon.eir_ad.entry.data contains e4:f2:e4:c1 can be used to filter packets based on major and minor numbers.

Handling variable number of arguments in Lua


Here’s a quick example of how variable number of arguments can be handled in Lua. It has been tested with Lua 5.1 and 5.2.

function SomeFunction(...)
    local list = {...}
    print(string.format("Received %d arguments:", #list))

    -- print all arguments
    print(...)

    -- print all arguments again using a for loop
    for i = 1, #list, 1 do
        print(list[i])
    end
end

SomeFunction("hello", "world")

Getting started with Corona SDK


This post has links and references for getting started with Corona SDK on a Mac, and running your apps on an iOS device.

Download and install Corona SDK. You’ll need a free starter or a paid account at coronalabs.com to activate the SDK.

You can write your own app in Lua, or execute sample applications using Corona Simulator application. Corona SDK has several libraries at your disposal. I am particularly interested in UI development, and bridging Lua and C to access external hardware such as Bluetooth LE peripherals. That ability to build native extensions requires a paid enterprise license.

You can build and deploy the app to an iOS device for further testing. The build process happens online and requires an internet connection.

Lua dofile and globals


I have been doing dissector development for Wireshark in Lua for a while now. Lua’s mechanism for reusing code organized across multiple files comes in two flavors, dofile and require. For historical reasons, we’ve been using dofile quite exclusively.

Our dissector files mostly contain global functions, and local or global tables. The tables are used to determine which function should be called to dissect a particular message, to look-up names that map to particular key values, and so on. If a script file needs a function or table in another file, we simply dofile the other file at the top. Lua interpreter will recognize all globals (functions and variables without local) of the other file from that point onwards.

Let’s consider an example. Here’s file1.lua

function f1()
  print("f1 called")
  f2()
end

dofile("file2.lua")

f1()

Here’s file2.lua, located in the same folder as file1.lua

function f2()
  print("f2 called")
end

When you run file1.lua, this is what you get

$ lua file1.lua
f1 called
f2 called

Lua only encounters call to global f2 inside function f1 when we call function f1 towards the end of file1.lua. If we call f1 right at the beginning of file1.lua we get

$ lua file1.lua
lua: file1.lua:2: attempt to call global 'f1' (a nil value)
stack traceback:
	file1.lua:2: in main chunk
	[C]: in ?

If we move dofile towards the end of file1.lua we get

$ lua file1.lua
f1 called
lua: file1.lua:3: attempt to call global 'f2' (a nil value)
stack traceback:
	file1.lua:3: in function 'f1'
	file1.lua:7: in main chunk
	[C]: in ?

Summing it up, a global exists only when Lua has encountered it, whether within the same or another script file.

Let us explore one other characteristic of dofile with another example. This is file1.lua

dofile("file2.lua")
hello['world'] = 'hello!'
print(hello['world'])

function f1()
  print(hello['world'])
  f3()
end

dofile("file3.lua")

f1()

It requires a certain global table in file2.lua, which it updates before using. It also requires a certain function f3 in file3.lua. This is file2.lua

hello = {['hello']='world!'}

function f2()
  print("f2 called")
end

This is file3.lua

dofile('file2.lua')

function f3()
  print('f3 called')
  f2()
end

It needs function f2 in file2.lua. You shouldn’t need dofile because file1.lua has already loaded file2.lua, but whoever coded file3.lua probably doesn’t know that. Let’s execute file1.lua and see what happens

$ lua file1.lua
hello!
nil
f3 called
f2 called

By the time function f1 gets called, the value of key 'world' in the hello table ceases to exist. Why? Because, right before f1 is called, when we dofile file3.lua it will dofile file2.lua. Since file2.lua gets interpreted again, the global hello is replaced by a new table.

Summing it up, Lua will load and execute the same file again when it encounters dofile, redefining all globals in it.

That is why, for reusing code in other script files, use require. Lua will not reinterpret a script file that has already been encountered before. Modifying the example scripts above is straightforward. Replace all dofile with require and drop the lua extension. Thus dofile('file2.lua') will become require('file2'). Execute file1.lua thus

$ export LUA_PATH=$PWD/?.lua
$ lua file1.lua
hello!
hello!
f3 called
f2 called

Globals now work without side-effects! Note the use of LUA_PATH environment variable to specify the search path for Lua scripts. You can also set search path inside a Lua script by modifying package.path.

What if you have already invested in dofile and don’t want to change things for now? In the example above, modifying file2.lua thus, eliminates our problem

if hello == nil then hello = { } end
hello['hello']='world!'

function f2()
  print("f2 called")
end

File virtualization in Windows


Windows versions since Vista have a feature in which files with administrative privileges in “Program Files” and other folders, may be masked by a version of the file in user’s Virtual Store. The Virtual Store is located at C:\Users\User_name\AppData\Local\VirtualStore.

If you have changed a file under Program Files using administrative privileges, but find the changes mysteriously fail to have any effect, the Virtual Store may be to blame. I noticed this when editing Wireshark’s init.lua file, but the changes would have no effect. I was able to fix the problem by editing the file stored at the Virtual Store location mentioned above. Certain editors are aware of this Windows feature, when opening and saving a privileged file they use the Virtual Store without informing the user.