wireshark dissector
This commit is contained in:
parent
f438935954
commit
ecd92d0e18
|
@ -0,0 +1,901 @@
|
|||
--
|
||||
-- lua-MessagePack : <https://fperrad.frama.io/lua-MessagePack/>
|
||||
--
|
||||
|
||||
local r, jit = pcall(require, 'jit')
|
||||
if not r then
|
||||
jit = nil
|
||||
end
|
||||
|
||||
local SIZEOF_NUMBER = string.pack and #string.pack('n', 0.0) or 8
|
||||
local maxinteger
|
||||
local mininteger
|
||||
if not jit and _VERSION < 'Lua 5.3' then
|
||||
-- Lua 5.1 & 5.2
|
||||
local loadstring = loadstring or load
|
||||
local luac = string.dump(loadstring "a = 1")
|
||||
local header = { luac:byte(1, 12) }
|
||||
SIZEOF_NUMBER = header[11]
|
||||
end
|
||||
|
||||
local assert = assert
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local pcall = pcall
|
||||
local setmetatable = setmetatable
|
||||
local tostring = tostring
|
||||
local type = type
|
||||
local char = require'string'.char
|
||||
local format = require'string'.format
|
||||
local floor = require'math'.floor
|
||||
local tointeger = require'math'.tointeger or floor
|
||||
local frexp = require'math'.frexp or require'mathx'.frexp
|
||||
local ldexp = require'math'.ldexp or require'mathx'.ldexp
|
||||
local huge = require'math'.huge
|
||||
local tconcat = require'table'.concat
|
||||
|
||||
local _ENV = nil
|
||||
local m = {}
|
||||
|
||||
--[[ debug only
|
||||
local function hexadump (s)
|
||||
return (s:gsub('.', function (c) return format('%02X ', c:byte()) end))
|
||||
end
|
||||
m.hexadump = hexadump
|
||||
--]]
|
||||
|
||||
local function argerror (caller, narg, extramsg)
|
||||
error("bad argument #" .. tostring(narg) .. " to "
|
||||
.. caller .. " (" .. extramsg .. ")")
|
||||
end
|
||||
|
||||
local function typeerror (caller, narg, arg, tname)
|
||||
argerror(caller, narg, tname .. " expected, got " .. type(arg))
|
||||
end
|
||||
|
||||
local function checktype (caller, narg, arg, tname)
|
||||
if type(arg) ~= tname then
|
||||
typeerror(caller, narg, arg, tname)
|
||||
end
|
||||
end
|
||||
|
||||
local packers = setmetatable({}, {
|
||||
__index = function (t, k)
|
||||
if k == 1 then return end -- allows ipairs
|
||||
error("pack '" .. k .. "' is unimplemented")
|
||||
end
|
||||
})
|
||||
m.packers = packers
|
||||
|
||||
packers['nil'] = function (buffer)
|
||||
buffer[#buffer+1] = char(0xC0) -- nil
|
||||
end
|
||||
|
||||
packers['boolean'] = function (buffer, bool)
|
||||
if bool then
|
||||
buffer[#buffer+1] = char(0xC3) -- true
|
||||
else
|
||||
buffer[#buffer+1] = char(0xC2) -- false
|
||||
end
|
||||
end
|
||||
|
||||
packers['string_compat'] = function (buffer, str)
|
||||
local n = #str
|
||||
if n <= 0x1F then
|
||||
buffer[#buffer+1] = char(0xA0 + n) -- fixstr
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xDA, -- str16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xDB, -- str32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
error"overflow in pack 'string_compat'"
|
||||
end
|
||||
buffer[#buffer+1] = str
|
||||
end
|
||||
|
||||
packers['_string'] = function (buffer, str)
|
||||
local n = #str
|
||||
if n <= 0x1F then
|
||||
buffer[#buffer+1] = char(0xA0 + n) -- fixstr
|
||||
elseif n <= 0xFF then
|
||||
buffer[#buffer+1] = char(0xD9, -- str8
|
||||
n)
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xDA, -- str16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xDB, -- str32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
error"overflow in pack 'string'"
|
||||
end
|
||||
buffer[#buffer+1] = str
|
||||
end
|
||||
|
||||
packers['binary'] = function (buffer, str)
|
||||
local n = #str
|
||||
if n <= 0xFF then
|
||||
buffer[#buffer+1] = char(0xC4, -- bin8
|
||||
n)
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xC5, -- bin16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xC6, -- bin32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
error"overflow in pack 'binary'"
|
||||
end
|
||||
buffer[#buffer+1] = str
|
||||
end
|
||||
|
||||
local set_string = function (str)
|
||||
if str == 'string_compat' then
|
||||
packers['string'] = packers['string_compat']
|
||||
elseif str == 'string' then
|
||||
packers['string'] = packers['_string']
|
||||
elseif str == 'binary' then
|
||||
packers['string'] = packers['binary']
|
||||
else
|
||||
argerror('set_string', 1, "invalid option '" .. str .."'")
|
||||
end
|
||||
end
|
||||
m.set_string = set_string
|
||||
|
||||
packers['map'] = function (buffer, tbl, n)
|
||||
if n <= 0x0F then
|
||||
buffer[#buffer+1] = char(0x80 + n) -- fixmap
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xDE, -- map16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xDF, -- map32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
error"overflow in pack 'map'"
|
||||
end
|
||||
for k, v in pairs(tbl) do
|
||||
packers[type(k)](buffer, k)
|
||||
packers[type(v)](buffer, v)
|
||||
end
|
||||
end
|
||||
|
||||
packers['array'] = function (buffer, tbl, n)
|
||||
if n <= 0x0F then
|
||||
buffer[#buffer+1] = char(0x90 + n) -- fixarray
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xDC, -- array16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xDD, -- array32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
error"overflow in pack 'array'"
|
||||
end
|
||||
for i = 1, n do
|
||||
local v = tbl[i]
|
||||
packers[type(v)](buffer, v)
|
||||
end
|
||||
end
|
||||
|
||||
local set_array = function (array)
|
||||
if array == 'without_hole' then
|
||||
packers['_table'] = function (buffer, tbl)
|
||||
local is_map, n, max = false, 0, 0
|
||||
for k in pairs(tbl) do
|
||||
if type(k) == 'number' and k > 0 then
|
||||
if k > max then
|
||||
max = k
|
||||
end
|
||||
else
|
||||
is_map = true
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if max ~= n then -- there are holes
|
||||
is_map = true
|
||||
end
|
||||
if is_map then
|
||||
packers['map'](buffer, tbl, n)
|
||||
else
|
||||
packers['array'](buffer, tbl, n)
|
||||
end
|
||||
end
|
||||
elseif array == 'with_hole' then
|
||||
packers['_table'] = function (buffer, tbl)
|
||||
local is_map, n, max = false, 0, 0
|
||||
for k in pairs(tbl) do
|
||||
if type(k) == 'number' and k > 0 then
|
||||
if k > max then
|
||||
max = k
|
||||
end
|
||||
else
|
||||
is_map = true
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if is_map then
|
||||
packers['map'](buffer, tbl, n)
|
||||
else
|
||||
packers['array'](buffer, tbl, max)
|
||||
end
|
||||
end
|
||||
elseif array == 'always_as_map' then
|
||||
packers['_table'] = function(buffer, tbl)
|
||||
local n = 0
|
||||
for k in pairs(tbl) do
|
||||
n = n + 1
|
||||
end
|
||||
packers['map'](buffer, tbl, n)
|
||||
end
|
||||
else
|
||||
argerror('set_array', 1, "invalid option '" .. array .."'")
|
||||
end
|
||||
end
|
||||
m.set_array = set_array
|
||||
|
||||
packers['table'] = function (buffer, tbl)
|
||||
packers['_table'](buffer, tbl)
|
||||
end
|
||||
|
||||
packers['unsigned'] = function (buffer, n)
|
||||
if n >= 0 then
|
||||
if n <= 0x7F then
|
||||
buffer[#buffer+1] = char(n) -- fixnum_pos
|
||||
elseif n <= 0xFF then
|
||||
buffer[#buffer+1] = char(0xCC, -- uint8
|
||||
n)
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xCD, -- uint16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xCE, -- uint32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xCF, -- uint64
|
||||
0, -- only 53 bits from double
|
||||
floor(n / 0x1000000000000) % 0x100,
|
||||
floor(n / 0x10000000000) % 0x100,
|
||||
floor(n / 0x100000000) % 0x100,
|
||||
floor(n / 0x1000000) % 0x100,
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
end
|
||||
else
|
||||
if n >= -0x20 then
|
||||
buffer[#buffer+1] = char(0x100 + n) -- fixnum_neg
|
||||
elseif n >= -0x80 then
|
||||
buffer[#buffer+1] = char(0xD0, -- int8
|
||||
0x100 + n)
|
||||
elseif n >= -0x8000 then
|
||||
n = 0x10000 + n
|
||||
buffer[#buffer+1] = char(0xD1, -- int16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n >= -0x80000000 then
|
||||
n = 4294967296.0 + n
|
||||
buffer[#buffer+1] = char(0xD2, -- int32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xD3, -- int64
|
||||
0xFF, -- only 53 bits from double
|
||||
floor(n / 0x1000000000000) % 0x100,
|
||||
floor(n / 0x10000000000) % 0x100,
|
||||
floor(n / 0x100000000) % 0x100,
|
||||
floor(n / 0x1000000) % 0x100,
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
packers['signed'] = function (buffer, n)
|
||||
if n >= 0 then
|
||||
if n <= 0x7F then
|
||||
buffer[#buffer+1] = char(n) -- fixnum_pos
|
||||
elseif n <= 0x7FFF then
|
||||
buffer[#buffer+1] = char(0xD1, -- int16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n <= 0x7FFFFFFF then
|
||||
buffer[#buffer+1] = char(0xD2, -- int32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xD3, -- int64
|
||||
0, -- only 53 bits from double
|
||||
floor(n / 0x1000000000000) % 0x100,
|
||||
floor(n / 0x10000000000) % 0x100,
|
||||
floor(n / 0x100000000) % 0x100,
|
||||
floor(n / 0x1000000) % 0x100,
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
end
|
||||
else
|
||||
if n >= -0x20 then
|
||||
buffer[#buffer+1] = char(0xE0 + 0x20 + n) -- fixnum_neg
|
||||
elseif n >= -0x80 then
|
||||
buffer[#buffer+1] = char(0xD0, -- int8
|
||||
0x100 + n)
|
||||
elseif n >= -0x8000 then
|
||||
n = 0x10000 + n
|
||||
buffer[#buffer+1] = char(0xD1, -- int16
|
||||
floor(n / 0x100),
|
||||
n % 0x100)
|
||||
elseif n >= -0x80000000 then
|
||||
n = 4294967296.0 + n
|
||||
buffer[#buffer+1] = char(0xD2, -- int32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xD3, -- int64
|
||||
0xFF, -- only 53 bits from double
|
||||
floor(n / 0x1000000000000) % 0x100,
|
||||
floor(n / 0x10000000000) % 0x100,
|
||||
floor(n / 0x100000000) % 0x100,
|
||||
floor(n / 0x1000000) % 0x100,
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local set_integer = function (integer)
|
||||
if integer == 'unsigned' then
|
||||
packers['integer'] = packers['unsigned']
|
||||
elseif integer == 'signed' then
|
||||
packers['integer'] = packers['signed']
|
||||
else
|
||||
argerror('set_integer', 1, "invalid option '" .. integer .."'")
|
||||
end
|
||||
end
|
||||
m.set_integer = set_integer
|
||||
|
||||
packers['float'] = function (buffer, n)
|
||||
local sign = 0
|
||||
if n < 0.0 then
|
||||
sign = 0x80
|
||||
n = -n
|
||||
end
|
||||
local mant, expo = frexp(n)
|
||||
if mant ~= mant then
|
||||
buffer[#buffer+1] = char(0xCA, -- nan
|
||||
0xFF, 0x88, 0x00, 0x00)
|
||||
elseif mant == huge or expo > 0x80 then
|
||||
if sign == 0 then
|
||||
buffer[#buffer+1] = char(0xCA, -- inf
|
||||
0x7F, 0x80, 0x00, 0x00)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xCA, -- -inf
|
||||
0xFF, 0x80, 0x00, 0x00)
|
||||
end
|
||||
elseif (mant == 0.0 and expo == 0) or expo < -0x7E then
|
||||
buffer[#buffer+1] = char(0xCA, -- zero
|
||||
sign, 0x00, 0x00, 0x00)
|
||||
else
|
||||
expo = expo + 0x7E
|
||||
mant = floor((mant * 2.0 - 1.0) * ldexp(0.5, 24))
|
||||
buffer[#buffer+1] = char(0xCA,
|
||||
sign + floor(expo / 0x2),
|
||||
(expo % 0x2) * 0x80 + floor(mant / 0x10000),
|
||||
floor(mant / 0x100) % 0x100,
|
||||
mant % 0x100)
|
||||
end
|
||||
end
|
||||
|
||||
packers['double'] = function (buffer, n)
|
||||
local sign = 0
|
||||
if n < 0.0 then
|
||||
sign = 0x80
|
||||
n = -n
|
||||
end
|
||||
local mant, expo = frexp(n)
|
||||
if mant ~= mant then
|
||||
buffer[#buffer+1] = char(0xCB, -- nan
|
||||
0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
elseif mant == huge or expo > 0x400 then
|
||||
if sign == 0 then
|
||||
buffer[#buffer+1] = char(0xCB, -- inf
|
||||
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
else
|
||||
buffer[#buffer+1] = char(0xCB, -- -inf
|
||||
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
end
|
||||
elseif (mant == 0.0 and expo == 0) or expo < -0x3FE then
|
||||
buffer[#buffer+1] = char(0xCB, -- zero
|
||||
sign, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
else
|
||||
expo = expo + 0x3FE
|
||||
mant = floor((mant * 2.0 - 1.0) * ldexp(0.5, 53))
|
||||
buffer[#buffer+1] = char(0xCB,
|
||||
sign + floor(expo / 0x10),
|
||||
(expo % 0x10) * 0x10 + floor(mant / 0x1000000000000),
|
||||
floor(mant / 0x10000000000) % 0x100,
|
||||
floor(mant / 0x100000000) % 0x100,
|
||||
floor(mant / 0x1000000) % 0x100,
|
||||
floor(mant / 0x10000) % 0x100,
|
||||
floor(mant / 0x100) % 0x100,
|
||||
mant % 0x100)
|
||||
end
|
||||
end
|
||||
|
||||
local set_number = function (number)
|
||||
if number == 'float' then
|
||||
packers['number'] = function (buffer, n)
|
||||
if floor(n) == n and n < maxinteger and n > mininteger then
|
||||
packers['integer'](buffer, n)
|
||||
else
|
||||
packers['float'](buffer, n)
|
||||
end
|
||||
end
|
||||
elseif number == 'double' then
|
||||
packers['number'] = function (buffer, n)
|
||||
if floor(n) == n and n < maxinteger and n > mininteger then
|
||||
packers['integer'](buffer, n)
|
||||
else
|
||||
packers['double'](buffer, n)
|
||||
end
|
||||
end
|
||||
else
|
||||
argerror('set_number', 1, "invalid option '" .. number .."'")
|
||||
end
|
||||
end
|
||||
m.set_number = set_number
|
||||
|
||||
for k = 0, 4 do
|
||||
local n = tointeger(2^k)
|
||||
local fixext = 0xD4 + k
|
||||
packers['fixext' .. tostring(n)] = function (buffer, tag, data)
|
||||
assert(#data == n, "bad length for fixext" .. tostring(n))
|
||||
buffer[#buffer+1] = char(fixext,
|
||||
tag < 0 and tag + 0x100 or tag)
|
||||
buffer[#buffer+1] = data
|
||||
end
|
||||
end
|
||||
|
||||
packers['ext'] = function (buffer, tag, data)
|
||||
local n = #data
|
||||
if n <= 0xFF then
|
||||
buffer[#buffer+1] = char(0xC7, -- ext8
|
||||
n,
|
||||
tag < 0 and tag + 0x100 or tag)
|
||||
elseif n <= 0xFFFF then
|
||||
buffer[#buffer+1] = char(0xC8, -- ext16
|
||||
floor(n / 0x100),
|
||||
n % 0x100,
|
||||
tag < 0 and tag + 0x100 or tag)
|
||||
elseif n <= 4294967295.0 then
|
||||
buffer[#buffer+1] = char(0xC9, -- ext&32
|
||||
floor(n / 0x1000000),
|
||||
floor(n / 0x10000) % 0x100,
|
||||
floor(n / 0x100) % 0x100,
|
||||
n % 0x100,
|
||||
tag < 0 and tag + 0x100 or tag)
|
||||
else
|
||||
error"overflow in pack 'ext'"
|
||||
end
|
||||
buffer[#buffer+1] = data
|
||||
end
|
||||
|
||||
function m.pack (data)
|
||||
local buffer = {}
|
||||
packers[type(data)](buffer, data)
|
||||
return tconcat(buffer)
|
||||
end
|
||||
|
||||
|
||||
local unpackers -- forward declaration
|
||||
|
||||
local function unpack_cursor (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i > j then
|
||||
c:underflow(i)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local val = s:byte(i)
|
||||
c.i = i+1
|
||||
return unpackers[val](c, val)
|
||||
end
|
||||
m.unpack_cursor = unpack_cursor
|
||||
|
||||
local function unpack_str (c, n)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
local e = i+n-1
|
||||
if e > j or n < 0 then
|
||||
c:underflow(e)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
e = i+n-1
|
||||
end
|
||||
c.i = i+n
|
||||
return s:sub(i, e)
|
||||
end
|
||||
|
||||
local function unpack_array (c, n)
|
||||
local t = {}
|
||||
for i = 1, n do
|
||||
t[i] = unpack_cursor(c)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function unpack_map (c, n)
|
||||
local t = {}
|
||||
for i = 1, n do
|
||||
local k = unpack_cursor(c)
|
||||
local val = unpack_cursor(c)
|
||||
if k == nil or k ~= k then
|
||||
k = m.sentinel
|
||||
end
|
||||
if k ~= nil then
|
||||
t[k] = val
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function unpack_float (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+3 > j then
|
||||
c:underflow(i+3)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4 = s:byte(i, i+3)
|
||||
local sign = b1 > 0x7F
|
||||
local expo = (b1 % 0x80) * 0x2 + floor(b2 / 0x80)
|
||||
local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4
|
||||
if sign then
|
||||
sign = -1
|
||||
else
|
||||
sign = 1
|
||||
end
|
||||
local n
|
||||
if mant == 0 and expo == 0 then
|
||||
n = sign * 0.0
|
||||
elseif expo == 0xFF then
|
||||
if mant == 0 then
|
||||
n = sign * huge
|
||||
else
|
||||
n = 0.0/0.0
|
||||
end
|
||||
else
|
||||
n = sign * ldexp(1.0 + mant / 0x800000, expo - 0x7F)
|
||||
end
|
||||
c.i = i+4
|
||||
return n
|
||||
end
|
||||
|
||||
local function unpack_double (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+7 > j then
|
||||
c:underflow(i+7)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4, b5, b6, b7, b8 = s:byte(i, i+7)
|
||||
local sign = b1 > 0x7F
|
||||
local expo = (b1 % 0x80) * 0x10 + floor(b2 / 0x10)
|
||||
local mant = ((((((b2 % 0x10) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
||||
if sign then
|
||||
sign = -1
|
||||
else
|
||||
sign = 1
|
||||
end
|
||||
local n
|
||||
if mant == 0 and expo == 0 then
|
||||
n = sign * 0.0
|
||||
elseif expo == 0x7FF then
|
||||
if mant == 0 then
|
||||
n = sign * huge
|
||||
else
|
||||
n = 0.0/0.0
|
||||
end
|
||||
else
|
||||
n = sign * ldexp(1.0 + mant / 4503599627370496.0, expo - 0x3FF)
|
||||
end
|
||||
c.i = i+8
|
||||
return n
|
||||
end
|
||||
|
||||
local function unpack_uint8 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i > j then
|
||||
c:underflow(i)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1 = s:byte(i)
|
||||
c.i = i+1
|
||||
return b1
|
||||
end
|
||||
|
||||
local function unpack_uint16 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+1 > j then
|
||||
c:underflow(i+1)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2 = s:byte(i, i+1)
|
||||
c.i = i+2
|
||||
return b1 * 0x100 + b2
|
||||
end
|
||||
|
||||
local function unpack_uint32 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+3 > j then
|
||||
c:underflow(i+3)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4 = s:byte(i, i+3)
|
||||
c.i = i+4
|
||||
return ((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4
|
||||
end
|
||||
|
||||
local function unpack_uint64 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+7 > j then
|
||||
c:underflow(i+7)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4, b5, b6, b7, b8 = s:byte(i, i+7)
|
||||
c.i = i+8
|
||||
return ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
||||
end
|
||||
|
||||
local function unpack_int8 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i > j then
|
||||
c:underflow(i)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1 = s:byte(i)
|
||||
c.i = i+1
|
||||
if b1 < 0x80 then
|
||||
return b1
|
||||
else
|
||||
return b1 - 0x100
|
||||
end
|
||||
end
|
||||
|
||||
local function unpack_int16 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+1 > j then
|
||||
c:underflow(i+1)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2 = s:byte(i, i+1)
|
||||
c.i = i+2
|
||||
if b1 < 0x80 then
|
||||
return b1 * 0x100 + b2
|
||||
else
|
||||
return ((b1 - 0xFF) * 0x100 + (b2 - 0xFF)) - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function unpack_int32 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+3 > j then
|
||||
c:underflow(i+3)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4 = s:byte(i, i+3)
|
||||
c.i = i+4
|
||||
if b1 < 0x80 then
|
||||
return ((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4
|
||||
else
|
||||
return ((((b1 - 0xFF) * 0x100 + (b2 - 0xFF)) * 0x100 + (b3 - 0xFF)) * 0x100 + (b4 - 0xFF)) - 1
|
||||
end
|
||||
end
|
||||
|
||||
local function unpack_int64 (c)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
if i+7 > j then
|
||||
c:underflow(i+7)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
end
|
||||
local b1, b2, b3, b4, b5, b6, b7, b8 = s:byte(i, i+7)
|
||||
c.i = i+8
|
||||
if b1 < 0x80 then
|
||||
return ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
||||
else
|
||||
return ((((((((b1 - 0xFF) * 0x100 + (b2 - 0xFF)) * 0x100 + (b3 - 0xFF)) * 0x100 + (b4 - 0xFF)) * 0x100 + (b5 - 0xFF)) * 0x100 + (b6 - 0xFF)) * 0x100 + (b7 - 0xFF)) * 0x100 + (b8 - 0xFF)) - 1
|
||||
end
|
||||
end
|
||||
|
||||
function m.build_ext (tag, data)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function unpack_ext (c, n, tag)
|
||||
local s, i, j = c.s, c.i, c.j
|
||||
local e = i+n-1
|
||||
if e > j or n < 0 then
|
||||
c:underflow(e)
|
||||
s, i, j = c.s, c.i, c.j
|
||||
e = i+n-1
|
||||
end
|
||||
c.i = i+n
|
||||
return m.build_ext(tag, s:sub(i, e))
|
||||
end
|
||||
|
||||
unpackers = setmetatable({
|
||||
[0xC0] = function () return nil end,
|
||||
[0xC2] = function () return false end,
|
||||
[0xC3] = function () return true end,
|
||||
[0xC4] = function (c) return unpack_str(c, unpack_uint8(c)) end, -- bin8
|
||||
[0xC5] = function (c) return unpack_str(c, unpack_uint16(c)) end, -- bin16
|
||||
[0xC6] = function (c) return unpack_str(c, unpack_uint32(c)) end, -- bin32
|
||||
[0xC7] = function (c) return unpack_ext(c, unpack_uint8(c), unpack_int8(c)) end,
|
||||
[0xC8] = function (c) return unpack_ext(c, unpack_uint16(c), unpack_int8(c)) end,
|
||||
[0xC9] = function (c) return unpack_ext(c, unpack_uint32(c), unpack_int8(c)) end,
|
||||
[0xCA] = unpack_float,
|
||||
[0xCB] = unpack_double,
|
||||
[0xCC] = unpack_uint8,
|
||||
[0xCD] = unpack_uint16,
|
||||
[0xCE] = unpack_uint32,
|
||||
[0xCF] = unpack_uint64,
|
||||
[0xD0] = unpack_int8,
|
||||
[0xD1] = unpack_int16,
|
||||
[0xD2] = unpack_int32,
|
||||
[0xD3] = unpack_int64,
|
||||
[0xD4] = function (c) return unpack_ext(c, 1, unpack_int8(c)) end,
|
||||
[0xD5] = function (c) return unpack_ext(c, 2, unpack_int8(c)) end,
|
||||
[0xD6] = function (c) return unpack_ext(c, 4, unpack_int8(c)) end,
|
||||
[0xD7] = function (c) return unpack_ext(c, 8, unpack_int8(c)) end,
|
||||
[0xD8] = function (c) return unpack_ext(c, 16, unpack_int8(c)) end,
|
||||
[0xD9] = function (c) return unpack_str(c, unpack_uint8(c)) end,
|
||||
[0xDA] = function (c) return unpack_str(c, unpack_uint16(c)) end,
|
||||
[0xDB] = function (c) return unpack_str(c, unpack_uint32(c)) end,
|
||||
[0xDC] = function (c) return unpack_array(c, unpack_uint16(c)) end,
|
||||
[0xDD] = function (c) return unpack_array(c, unpack_uint32(c)) end,
|
||||
[0xDE] = function (c) return unpack_map(c, unpack_uint16(c)) end,
|
||||
[0xDF] = function (c) return unpack_map(c, unpack_uint32(c)) end,
|
||||
}, {
|
||||
__index = function (t, k)
|
||||
if k < 0xC0 then
|
||||
if k < 0x80 then
|
||||
return function (c, val) return val end
|
||||
elseif k < 0x90 then
|
||||
return function (c, val) return unpack_map(c, val % 0x10) end
|
||||
elseif k < 0xA0 then
|
||||
return function (c, val) return unpack_array(c, val % 0x10) end
|
||||
else
|
||||
return function (c, val) return unpack_str(c, val % 0x20) end
|
||||
end
|
||||
elseif k > 0xDF then
|
||||
return function (c, val) return val - 0x100 end
|
||||
else
|
||||
return function () error("unpack '" .. format('%#x', k) .. "' is unimplemented") end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
local function cursor_string (str)
|
||||
return {
|
||||
s = str,
|
||||
i = 1,
|
||||
j = #str,
|
||||
underflow = function ()
|
||||
error "missing bytes"
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local function cursor_loader (ld)
|
||||
return {
|
||||
s = '',
|
||||
i = 1,
|
||||
j = 0,
|
||||
underflow = function (self, e)
|
||||
self.s = self.s:sub(self.i)
|
||||
e = e - self.i + 1
|
||||
self.i = 1
|
||||
self.j = 0
|
||||
while e > self.j do
|
||||
local chunk = ld()
|
||||
if not chunk then
|
||||
error "missing bytes"
|
||||
end
|
||||
self.s = self.s .. chunk
|
||||
self.j = #self.s
|
||||
end
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function m.unpack (s)
|
||||
checktype('unpack', 1, s, 'string')
|
||||
local cursor = cursor_string(s)
|
||||
local data = unpack_cursor(cursor)
|
||||
if cursor.i <= cursor.j then
|
||||
error "extra bytes"
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
function m.unpacker (src)
|
||||
if type(src) == 'string' then
|
||||
local cursor = cursor_string(src)
|
||||
return function ()
|
||||
if cursor.i <= cursor.j then
|
||||
return cursor.i, unpack_cursor(cursor)
|
||||
end
|
||||
end
|
||||
elseif type(src) == 'function' then
|
||||
local cursor = cursor_loader(src)
|
||||
return function ()
|
||||
if cursor.i > cursor.j then
|
||||
pcall(cursor.underflow, cursor, cursor.i)
|
||||
end
|
||||
if cursor.i <= cursor.j then
|
||||
return true, unpack_cursor(cursor)
|
||||
end
|
||||
end
|
||||
else
|
||||
argerror('unpacker', 1, "string or function expected, got " .. type(src))
|
||||
end
|
||||
end
|
||||
|
||||
set_string'string_compat'
|
||||
set_integer'unsigned'
|
||||
if SIZEOF_NUMBER == 4 then
|
||||
maxinteger = 16777215
|
||||
mininteger = -maxinteger
|
||||
m.small_lua = true
|
||||
unpackers[0xCB] = nil -- double
|
||||
unpackers[0xCF] = nil -- uint64
|
||||
unpackers[0xD3] = nil -- int64
|
||||
set_number'float'
|
||||
else
|
||||
maxinteger = 9007199254740991
|
||||
mininteger = -maxinteger
|
||||
set_number'double'
|
||||
if SIZEOF_NUMBER > 8 then
|
||||
m.long_double = true
|
||||
end
|
||||
end
|
||||
set_array'without_hole'
|
||||
|
||||
m._VERSION = '0.5.2'
|
||||
m._DESCRIPTION = "lua-MessagePack : a pure Lua implementation"
|
||||
m._COPYRIGHT = "Copyright (c) 2012-2019 Francois Perrad"
|
||||
return m
|
||||
--
|
||||
-- This library is licensed under the terms of the MIT/X11 license,
|
||||
-- like Lua itself.
|
||||
--
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
msgpack=require("e3pf-mp")
|
||||
|
||||
epf_protocol = Proto("e3pf", "e3team Protocol Framework")
|
||||
|
||||
packet_length = ProtoField.uint64("e3pf.packet_length", "Packet Length", base.DEC)
|
||||
packet_id = ProtoField.uint8("e3pf.packet_id", "Packet ID", base.DEC)
|
||||
|
||||
-- Message: ClientHello
|
||||
ch_protocol_version = ProtoField.uint32("e3pf.client_hello.protocol_version", "Protocol Version", base.DEC)
|
||||
ch_client_random = ProtoField.string("e3pf.client_hello.client_random", "Client Random")
|
||||
-- Client certificate: is a subtree
|
||||
ch_client_x25519 = ProtoField.string("e3pf.client_hello.client_x25519", "Client X25519 Public Key")
|
||||
|
||||
-- Message: ServerHello
|
||||
sh_protocol_version = ProtoField.uint32("e3pf.server_hello.protocol_version", "Protocol Version", base.DEC)
|
||||
-- Server Certificate: is a subtree
|
||||
sh_server_random = ProtoField.string("e3pf.server_hello.server_random", "Server Random")
|
||||
sh_server_x25519 = ProtoField.string("e3pf.server_hello.server_x25519", "Server X25519 Public Key")
|
||||
|
||||
-- Struct: Certificate
|
||||
-- Details: is a subtree
|
||||
c_fingerprint = ProtoField.string("e3pf.certificate.fingerprint", "Fingerprint")
|
||||
c_signature = ProtoField.string("e3pf.certificate.signature", "Signature")
|
||||
|
||||
-- Struct: Certificate.Details
|
||||
c_d_name = ProtoField.string("e3pf.certificate.details.name", "Name")
|
||||
c_d_not_before = ProtoField.string("e3pf.certificate.details.not_before", "Not Before")
|
||||
c_d_not_after = ProtoField.string("e3pf.certificate.details.not_after", "Not After")
|
||||
c_d_public_key = ProtoField.string("e3pf.certificate.details.public_key", "Public Key")
|
||||
c_d_issuer_public_key = ProtoField.string("e3pf.certificate.details.issuer_public_key", "Issuer Public Key")
|
||||
-- TODO: Claims
|
||||
|
||||
epf_protocol.fields = { packet_length, packet_id, ch_protocol_version, ch_client_random, ch_client_x25519, c_fingerprint, c_signature, c_d_name, c_d_not_before, c_d_not_after, c_d_public_key, c_d_issuer_public_key, sh_protocol_version, sh_server_random, sh_server_x25519 }
|
||||
|
||||
function dump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k,v in pairs(o) do
|
||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
function id_to_name(id)
|
||||
if id == 1 then return "ClientHello"
|
||||
elseif id == 2 then return "ServerHello"
|
||||
elseif id == 3 then return "HandshakeFinished"
|
||||
elseif id == 4 then return "ApplicationData"
|
||||
end
|
||||
end
|
||||
|
||||
local function table_to_hex(ctable)
|
||||
local sb=''
|
||||
for _, value in pairs(ctable) do
|
||||
sb=sb .. string.format("%x", value)
|
||||
end
|
||||
return sb
|
||||
end
|
||||
|
||||
local function cert_to_tree(rtree, name, ctable, buffer)
|
||||
local rrtree = rtree:add(epf_protocol, buffer(), name)
|
||||
|
||||
local tree = rrtree:add(epf_protocol, buffer(), "Details")
|
||||
|
||||
local details = ctable[1]
|
||||
|
||||
tree:add(c_d_name, details[1])
|
||||
tree:add(c_d_not_before, tostring(details[2]))
|
||||
tree:add(c_d_not_after, tostring(details[3]))
|
||||
tree:add(c_d_public_key, table_to_hex(details[4]))
|
||||
tree:add(c_d_issuer_public_key, table_to_hex(details[5]))
|
||||
|
||||
rrtree:add(c_fingerprint, ctable[2])
|
||||
rrtree:add(c_signature, table_to_hex(ctable[3]))
|
||||
end
|
||||
|
||||
function epf_protocol.dissector(buffer, pinfo, tree)
|
||||
length = buffer:len()
|
||||
if length == 0 then return end
|
||||
|
||||
pinfo.cols.protocol = epf_protocol.name
|
||||
|
||||
local subtree = tree:add(epf_protocol, buffer(), "e3team Protocol Framework Data")
|
||||
local dtree = subtree:add(epf_protocol, buffer(), "Packet Data")
|
||||
|
||||
local packet_length_flag = tonumber(buffer(0,8):le_uint64())
|
||||
|
||||
subtree:add_le(packet_length, buffer(0, 8))
|
||||
|
||||
local data = buffer(8, packet_length_flag)
|
||||
|
||||
local msgpack_data=''
|
||||
local bytes_message = data:bytes()
|
||||
for i=0, (bytes_message:len()-1) do
|
||||
value=bytes_message:get_index(i)
|
||||
msgpack_data=msgpack_data .. string.char(value)
|
||||
end
|
||||
|
||||
local message_unpacked = msgpack.unpack(msgpack_data)
|
||||
|
||||
subtree:add(packet_id, message_unpacked[1]):append_text(" (" .. id_to_name(message_unpacked[1]) .. ")")
|
||||
|
||||
local packet_bytes = message_unpacked[2]
|
||||
local packet_data=''
|
||||
for _, value in pairs(packet_bytes) do
|
||||
packet_data=packet_data .. string.char(value)
|
||||
end
|
||||
|
||||
local packet = msgpack.unpack(packet_data)
|
||||
|
||||
if message_unpacked[1] == 1 then
|
||||
-- CLIENT HELLO
|
||||
dtree:add(ch_protocol_version, packet[1])
|
||||
dtree:add(ch_client_random, table_to_hex(packet[2]))
|
||||
dtree:add(ch_client_x25519, table_to_hex(packet[4]))
|
||||
elseif message_unpacked[1] == 2 then
|
||||
-- SERVER HELLO
|
||||
dtree:add(sh_protocol_version, packet[1])
|
||||
cert_to_tree(dtree, "Server Certificate", packet[2], buffer)
|
||||
dtree:add(sh_server_random, table_to_hex(packet[3]))
|
||||
dtree:add(sh_server_x25519, table_to_hex(packet[4]))
|
||||
end
|
||||
end
|
||||
|
||||
local function heuristic_checker(buffer, pinfo, tree)
|
||||
length = buffer:len()
|
||||
if length < 12 then return false end
|
||||
|
||||
local header_start_flag = buffer(8,1):uint()
|
||||
|
||||
if header_start_flag ~= 0x92 then return false end
|
||||
|
||||
local packet_length_flag = buffer(0,8):le_uint64()
|
||||
|
||||
local packet_length = length - 8
|
||||
|
||||
if tostring(packet_length) ~= tostring(packet_length_flag) then return false end
|
||||
|
||||
local packet_id = buffer(9,1):uint()
|
||||
|
||||
print("packet " .. packet_id)
|
||||
|
||||
if packet_id == 0x01 or packet_id == 0x02 or packet_id == 0x03 or packet_id == 0x04 then
|
||||
epf_protocol.dissector(buffer, pinfo, tree)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
epf_protocol:register_heuristic("tcp", heuristic_checker)
|
Loading…
Reference in New Issue