Last active
September 7, 2020 11:40
-
-
Save Xitsa/03a091bfc0ae480b00d424ba1d137abf to your computer and use it in GitHub Desktop.
Плагин для Wireshark, который расшифровывает мандатные метки согласно ГОСТ Р 58256-2018 (а-ля астралинукс)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
--Для установки надо открыть в wireshark’е меню Help/About | |
--Там найти вкладку Folders, скопировать путь к ‘Personal Lua Plugins’ | |
--Создать этот каталог, если надо | |
--Скопировать туда этот файл и перезапустить wireshark | |
--]] | |
local function pack_byte(mask, byte, offset) | |
local limited_byte = bit32.band(byte, 0xFF) | |
local low_pos = 8 - math.floor(offset / 8) | |
local high_pos = low_pos - 1 | |
local bit_offset = math.fmod(offset, 8) | |
local low_value = bit32.band(bit32.lshift(byte, bit_offset), 0xFF) | |
local high_value = bit32.rshift(bit32.band(bit32.lshift(byte, bit_offset), 0xFF00), 8) | |
if low_pos > 0 then | |
mask[low_pos] = bit32.bor(mask[low_pos], low_value) | |
end | |
if high_pos > 0 then | |
mask[high_pos] = bit32.bor(mask[high_pos], high_value) | |
end | |
end | |
local function decode_mandate_labels(option_bytes) | |
if not option_bytes then return nil end | |
if #option_bytes < 3 then return nil end | |
if option_bytes[1] ~= 130 then return nil end | |
if option_bytes[2] ~= #option_bytes then return nil end | |
if option_bytes[3] ~= 171 then return nil end | |
table.remove(option_bytes, 3) | |
table.remove(option_bytes, 2) | |
table.remove(option_bytes, 1) | |
local level = 0 | |
local mask = {0, 0, 0, 0, 0, 0, 0, 0} | |
local offset = 0 | |
if (#option_bytes == 0) then return { level = level, mask = mask } end | |
local state = "BUILD_LEVEL" | |
for f = 1, #option_bytes do | |
local byte = option_bytes[f] | |
if (bit32.band(byte, 1) == 1) and (f == #option_bytes) then | |
-- Последний байт имеет продолжение | |
return nil | |
end | |
if (bit32.band(byte, 1) == 0) and (f ~= #option_bytes) then | |
-- Не последний байт указал, что он последний | |
return nil | |
end | |
if state == "BUILD_LEVEL" then | |
level = bit32.rshift(byte, 1) | |
state = "BUILD_HIGH_LEVEL_AND_MASK" | |
elseif state == "BUILD_HIGH_LEVEL_AND_MASK" then | |
level = bit32.bor(level, bit32.lshift(bit32.band(byte, 2), 6)) | |
pack_byte(mask, bit32.rshift(bit32.band(byte, 0xFC), 2), 0) | |
offset = 6 | |
state = "BUILD_MASK" | |
elseif state == "BUILD_MASK" then | |
pack_byte(mask, bit32.rshift(bit32.band(byte, 0xFE), 1), offset) | |
offset = offset + 7 | |
else | |
return nil | |
end | |
end | |
return { level = level, mask = mask } | |
end | |
function strip_leading_zeroes(str) | |
local without_all_leading_zeroes = str:gsub("^0*", "") | |
if without_all_leading_zeroes == "" then | |
return "0" | |
end | |
return without_all_leading_zeroes | |
end | |
local function array_to_bytes(array) | |
local hexes = {} | |
for k, v in ipairs(array) do | |
table.insert(hexes, string.format("%02x", v)) | |
end | |
return table.concat(hexes, "") | |
end | |
local ip_sec = Proto("IP_OPT_SEC", "IP option SEC (GOST R 58256-2018)") | |
local ip_opt_f = Field.new("ip.options.security") | |
local level_F = ProtoField.uint8("ip_opt_sec.level", "Security level") | |
local mask_F = ProtoField.string("ip_opt_sec.mask", "Categories mask") | |
ip_sec.fields = {level_F, mask_F, debug_F} | |
-- create a function to "postdissect" each frame | |
function ip_sec.dissector(buffer,pinfo,tree) | |
-- obtain the current values the protocol fields | |
local ip_opt = ip_opt_f() | |
if ip_opt then | |
local subtree = tree:add(ip_sec,"IP option SEC (GOST R 58256-2018) data") | |
local options = tostring(ip_opt) | |
local tvb_range = ip_opt.range | |
local bytes_array, bytes_len = tvb_range:bytes() | |
local x = {} | |
for f = 1, bytes_len do | |
table.insert(x, bytes_array:get_index(f - 1)) | |
end | |
local mandate_labels = decode_mandate_labels(x) | |
if mandate_labels then | |
subtree:add(level_F, mandate_labels.level) | |
subtree:add(mask_F, strip_leading_zeroes(array_to_bytes(mandate_labels.mask))) | |
end | |
end | |
end | |
-- register our protocol as a postdissector | |
register_postdissector(ip_sec) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment