Thursday, May 5, 2011

GUIDE: LUA unit testing and TDD

I've just uncovered this subject, here is my insights:

Fast start
  1. Open LUA
  2. Start a new test file (let's call it 'my_code.tests.lua').
  3. Edit 'my_code.tests.lua' (example template below)


--- my_code.tests.lua Code --------------------------------------------

-- Some super function to test
function my_super_function( arg1, arg2 ) return arg1 + arg2 end

-- Unit testing starts
require('luaunit')

TestMyStuff = {} --class
    function TestMyStuff:testWithNumbers()
        a = 1
        b = 2
        result = my_super_function( a, b )
        assertEquals( type(result), 'number' )
        assertEquals( result, 3 )
    end

    function TestMyStuff:testWithRealNumbers()
        a = 1.1
        b = 2.2
        result = my_super_function( a, b )
        assertEquals( type(result), 'number' )
        -- I would like the result to be always rounded to an integer
        -- but it won't work with my simple implementation
        -- thus, the test will fail
        assertEquals( result, 3 )
    end

-- class TestMyStuff

luaUnit:run()


--- Code End -----------------------------------------------------------------------
  1. Execute the test code.
  2. Add your tests and assumption checking.
  3. Fix what's broken.
Understand more

Monday, May 2, 2011

GUIDE: Creating your own fast Wireshark plugin / dissector using LUA.

After hitting my head agains the keyboard to create my own LUA protocol, I've desided that none shall suffer anymore.

Some background to understand stuff

  • Wireshark reads PCAP file format for captured files.
  • Wireshark can be extended using C code or, for fast development you can use LUA code (I'll explain later...).



Creating LUA based plugin / dissector

  1. Download and install Wireshark.
  2. Create LUA dissector (let's save it as 'trivial.lua')

-- trivial protocol example
-- declare our protocol
trivial_proto = Proto("trivial","Trivial Protocol")
-- create a function to dissect it
function trivial_proto.dissector(buffer,pinfo,tree)
    pinfo.cols.protocol = "TRIVIAL"
    local subtree = tree:add(trivial_proto,buffer(),"Trivial Protocol Data")
    subtree:add(buffer(0,2),"The first two bytes: " .. buffer(0,2):uint())
    subtree = subtree:add(buffer(2,2),"The next two bytes")
    subtree:add(buffer(2,1),"The 3rd byte: " .. buffer(2,1):uint())
    subtree:add(buffer(3,1),"The 4th byte: " .. buffer(3,1):uint())
end
-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
-- register our protocol to handle udp port 7777
udp_table:add(7777,trivial_proto)

  1. Edit  ...\Wireshark\init.lua file as follows
    1. disable_lua = false
    2. At the end of the file: dofile("trivial.lua"
      1. You can read more here - http://simplestcodings.com/2011/01/09/how-to-use-lua-to-create-wireshark-dissector/
  2. Open Wireshark
    1. Menu >> Edit >> Preferences >> Protocols >> DLT_USER >> Edit >> New:
      1. DLT: User 0 (147)
      2. Payload protocol: MyProtocolName
      3. Header size 0
      4. Trailer size: 0
      5. Press OK
  3. Create PCAP dumps for analyze.
    1. Using HEX-Editor (see below for nice hex-editor recomendations).
    2. If you can - ask the protocol team to provide their dumps. 
  4. Open the PCAP dump for editing (binary mode).
    1. Change the dump's 'Global Header' section / 'data link type' (network) to 147 (LINKTYPE_USER0)
      1. Read more here - http://www.tcpdump.org/linktypes.html
    2. save it.
  5. Load the dump to Wireshark for analyses.
  6. Start changing the trivial.lua code to parse your protocol.
Hope this will bring you to a working point fast. In the process read related stuff to understand more, you can upgrade this solution to create better and better protocol sniffer using Wireshark.



More nice stuff that can help

GUIDE: dotNetInstaller - Free fast and easy installer for windows

In a nutshell
  1. Download dotNetInstaller: setup bootstrapper for Windows
    1. Great tutorials:
      1. http://www.codeproject.com/KB/install/dotNetInstaller.aspx
      2. http://code.dblock.org/ShowPost.aspx?Id=118
  2. Read this article if you're using 'Setup project using the Windows Installer'.
    1. http://www.simple-talk.com/dotnet/visual-studio/updates-to-setup-projects/
  3. Read this article if you'r using 'Install shield limited edition'.
    1. http://blogs.msdn.com/b/somasegar/archive/2009/12/14/building-setup-and-deployment-packages-in-vs-2010.aspx
  4. If using MSI file...
    1. http://codefornothing.wordpress.com/2007/11/27/short-msi-tutorial/
    2. http://technet.microsoft.com/en-us/library/cc759262(WS.10).aspx
    3. http://www.advancedinstaller.com/user-guide/msiexec.html
    4. http://www.robvanderwoude.com/msiexec.php

Command line utilities for the job




REM Option Explicit

Dim exitcode : exitcode = 0

REM --- Functions ------------------------------------------------------------------


function readFromRegistry (strRegistryKey, strDefault )
    Dim value
 Dim objFSO, WSHShell

    On Error Resume Next
 Set objFSO   = CreateObject("Scripting.FileSystemObject")      
 Set WSHShell = CreateObject("Wscript.Shell")
    value = WSHShell.RegRead( strRegistryKey )

    if err.number <> 0 then
        readFromRegistry= strDefault
    else
        readFromRegistry=value
    end if

    set WSHShell = nothing
end function


function readDataFromMsiFile(file_path)
 Set objInstaller = CreateObject("WindowsInstaller.Installer")
 Set objProduct = objInstaller.SummaryInformation(file_path)
 Wscript.Echo "Code page: " &objProduct.Property(1)
 Wscript.Echo "Title: " & objProduct.Property(2)
 Wscript.Echo "Subject: " & objProduct.Property(3)
 Wscript.Echo "Author: " & objProduct.Property(4)
 Wscript.Echo "Keywords: " & objProduct.Property(5)
 Wscript.Echo "Comment: " & objProduct.Property(6)
 Wscript.Echo "Template: " & objProduct.Property(7)
 Wscript.Echo "Last Author: " & objProduct.Property(8)
 Wscript.Echo "Revision number: " & objProduct.Property(9)
 Wscript.Echo "Edit Time: " & objProduct.Property(10)
 Wscript.Echo "Last Printed: " & objProduct.Property(11)
 Wscript.Echo "Creation Date: " & objProduct.Property(12)
 Wscript.Echo "Last Saved: " & objProduct.Property(13)
 Wscript.Echo "Page Count: " & objProduct.Property(14)
 Wscript.Echo "Word Count: " & objProduct.Property(15)
 Wscript.Echo "Character Count: " & objProduct.Property(16)
 Wscript.Echo "Application Name: " & objProduct.Property(18)
 Wscript.Echo "Security: " & objProduct.Property(19)

 Set objProduct = Nothing
 Set objInstaller = Nothing

end function

function ProductVersion()
 ' SOURCE: http://stackoverflow.com/questions/815744/retrieving-version-of-an-msi-file-built-with-wix
 Dim installer, database, view, result

 Set installer = CreateObject("WindowsInstaller.Installer")
 Set database = installer.OpenDatabase (".\installer.msi", 0)

 Dim sumInfo  : Set sumInfo = installer.SummaryInformation(".\installer.msi", 0)
 sPackageCode =  sumInfo.Property(9) ' PID_REVNUMBER = 9, contains the package code.

 Set view = database.OpenView ("SELECT Value FROM Property WHERE Property='ProductVersion'")
    view.Execute
    Set result = view.Fetch
 
    ProductVersion = result.StringData(1)
end function
REM --- Code -------------------------------------------------------------------
new_version = ProductVersion()
installed_version = readFromRegistry ("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{12345678-D8EF-4EE9-8DC4-FF5911256E0D}\DisplayVersion", "0.0.0" )
uninstall_user_result = MsgBox("About to install " + new_version + " instead of " + installed_version + ", continue?",3,"Please answer")


Select Case uninstall_user_result
 Case 6 ' Yes
  exitcode = 0
  
 Case Else
  exitcode = 1 
End Select

WScript.Quit exitcode  REM return results

Executing VBScripts from command line
Hope it helps.