Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env lua
- --[[
- Author: DiabloHorn http://diablohorn.wordpress.com
- DnsCat traffic decoder, can be easily converted to a wireshark dissector :)
- This could be written a lot more efficient, but hey it's one of my first serious LUA scripts.
- ]]--
- -- testdata
- local testdata = {"dnscat.21.fgnlglmh.7718fc12.0.dgqt.directdns","dnscat.31.hihuznqd.2cedf05e.1.636174202f6574632f69737375650a.tvtm.directdns", "dnscat.29.gnwbuhls.699c9c36.3.sryi.directdns", "dnscat.21.gnwbuhls.699c9c2f.1.ffgchfgohehfcadbdacodadecodbcaemfefdcafmgocafmgmakak.rypw.directdns"}
- -- requires the bitopt library to be installed
- local bit = require("bit")
- -- start base parser
- -- split the request into an array of subdomain
- function getsubs(data)
- -- empty table to hold the subs
- local subs = {}
- for sub in data:gmatch("[^%.]+") do
- table.insert(subs,sub)
- end
- return subs
- end
- -- decode the flags to human readable strings
- function decodeflags(data)
- -- protocol flags
- local FLAG_STREAM = 0x00000001
- -- deprecated
- local FLAG_SYN = 0x00000002
- local FLAG_ACK = 0x00000004
- -- end of deprecated
- local FLAG_RST = 0x00000008
- local FLAG_HEX = 0x00000010
- local FLAG_SESSION = 0x00000020
- local FLAG_IDENTIFIER = 0x00000040
- -- convert string to number
- local hFlags = tonumber(data,16)
- --setup the flags table
- local Flags = {} -- st=nil,sy=nil,ac=nil,rs=nil,he=nil,se=nil,id=nil
- -- let's see which are set
- if bit.band(hFlags,FLAG_STREAM) ~= 0 then
- table.insert(Flags,"stream")
- end
- -- deprecated
- if bit.band(hFlags,FLAG_SYN) ~= 0 then
- table.insert(Flags,"syn")
- end
- if bit.band(hFlags,FLAG_ACK) ~= 0 then
- table.insert(Flags,"ack")
- end
- -- end of deprecated
- if bit.band(hFlags,FLAG_RST) ~= 0 then
- table.insert(Flags,"rst")
- end
- if bit.band(hFlags,FLAG_HEX) ~= 0 then
- table.insert(Flags,"hex")
- end
- if bit.band(hFlags,FLAG_SESSION) ~= 0 then
- table.insert(Flags,"session")
- end
- if bit.band(hFlags,FLAG_IDENTIFIER) ~= 0 then
- table.insert(Flags,"identifier")
- end
- return Flags
- end
- -- decode the error code to something human readable
- -- overcomplicated...but hey I wanted to use the bitopt lib again
- function decoderr(data)
- local ERR_SUCCESS = 0x00000000
- local ERR_BUSY = 0x00000001
- local ERR_INVSTATE = 0x00000002
- local ERR_FIN = 0x00000003
- local ERR_BADSEQ = 0x00000004
- local ERR_NOTIMPLEMENTED = 0x00000005
- local ERR_TEST = 0xFFFFFFFF
- local err = {}
- local herr = tonumber(data,16)
- if bit.tobit(ERR_SUCCESS) == bit.tobit(herr) then
- table.insert(err,"success")
- end
- if bit.tobit(ERR_BUSY) == bit.tobit(herr) then
- table.insert(err,"busy")
- end
- if bit.tobit(ERR_INVSTATE) == bit.tobit(herr) then
- table.insert(err,"invalidstate")
- end
- if bit.tobit(ERR_FIN) == bit.tobit(herr) then
- table.insert(err,"confin")
- end
- if bit.tobit(ERR_BADSEQ) == bit.tobit(herr) then
- table.insert(err,"badseqnum")
- end
- if bit.tobit(ERR_NOTIMPLEMENTED) == bit.tobit(herr) then
- table.insert(err,"notimplemented")
- end
- if bit.tobit(ERR_TEST) == bit.tobit(herr) then
- table.insert(err,"contest")
- end
- return err
- end
- -- decode netbios data to ascii
- function decodenetbios(data)
- local ldata = data:upper()
- local dec = ""
- for sub in ldata:gmatch("%u%u") do
- -- perform operation in decimal and convert final value from hex XX to decimal
- --local decnum = tonumber(((sub:byte(1)-65) .. (sub:byte(2)-65)),16)
- -- Thanks to Animal for making me realize the concat has to be with hexnumbers
- local decnum = tonumber((bit.tohex(sub:byte(1)-65,1) .. bit.tohex(sub:byte(2)-65,1)),16)
- print(bit.tohex(sub:byte(1)-65,1))
- print(decnum,sub)
- if decnum > 31 and decnum < 127 then
- dec = dec .. string.char(decnum)
- else
- dec = dec .. "."
- end
- decnum = 0
- sub = ""
- end
- return dec
- end
- -- decode hex data to ascii
- function decodehex(data)
- local dec = ""
- for sub in data:gmatch("%x%x") do
- decnum = tonumber(sub,16)
- if decnum > 31 and decnum < 127 then
- dec = dec .. string.char(decnum)
- else
- dec = dec .. "."
- end
- end
- return dec
- end
- -- main flow implementation
- -- lacks implementation of syn/ack since it's deprecated
- function parseDC(data)
- local finalparsed = {}
- local x = getsubs(data)
- finalparsed["signature"] = x[1]
- table.remove(x,1)
- finalparsed["flags"] = table.concat(decodeflags(x[1]),",")
- table.remove(x,1)
- if finalparsed["flags"]:find("identifier") ~= nil then
- finalparsed["identifier"] = x[1]
- table.remove(x,1)
- if finalparsed["flags"]:find("session") ~= nil then
- finalparsed["session"] = x[1]
- table.remove(x,1)
- end
- elseif finalparsed["flags"]:find("session") ~= nil then
- finalparsed["session"] = x[1]
- table.remove(x,1)
- end
- if finalparsed["flags"]:find("stream") ~= nil then
- finalparsed["seqnum"] = x[1]
- table.remove(x,1)
- end
- if finalparsed["flags"]:find("rst") ~= nil then
- finalparsed["err"] = table.concat(decoderr(x[1]),",")
- table.remove(x,1)
- finalparsed["garbage"] = x[1]
- finalparsed["domain"] = x[2]
- else
- finalparsed["count"] = x[1]
- table.remove(x,1)
- -- if you wonder the character # == len()
- finalparsed["garbage"] = x[#x-1]
- finalparsed["domain"] = x[#x]
- table.remove(x,(#x))
- table.remove(x,(#x))
- -- so we either got data or we don't
- finalparsed["asciidata"] = ""
- while #x > 0 do
- if finalparsed["flags"]:find("hex") == nil then
- finalparsed["asciidata"] = finalparsed["asciidata"] .. decodenetbios(x[1])
- else
- finalparsed["asciidata"] = finalparsed["asciidata"] .. decodehex(x[1])
- end
- table.remove(x,1)
- end
- end -- end of rst check
- return finalparsed
- end -- end of parseDC function
- -- end of base parser
- for i,v in ipairs(testdata) do
- local fp = parseDC(v)
- print("TestData: " .. v)
- print("Signature: " .. tostring(fp.signature))
- print("Flags: " .. tostring(fp.flags))
- print("Identifier: " .. tostring(fp.identifier))
- print("Session: " .. tostring(fp.session))
- print("Seqnum: " .. tostring(fp.seqnum))
- print("Count: " .. tostring(fp.count))
- print("Error: " .. tostring(fp.err))
- print("Data: " .. tostring(fp.asciidata))
- print("Garbage: " .. tostring(fp.garbage))
- print("Domain: " .. tostring(fp.domain))
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement