• Binkp dissector for Wireshark

    From Dmitry Protasoff@2:5001/100.1 to All on Sat Jun 28 22:10:39 2025
    Hello, All!

    �᫨ ����-� ��ᯨ稫�, ��� ���, 㤮��� ᬮ���� �� ��䨪 � wireshark, � ��� lua �ਯ�:

    -+-

    -- Binkp Protocol Dissector for Wireshark
    -- Version: 2025-06-28

    -- ====== Command/Option Tables ======
    local binkp_commands = {
    [0x00] = "M_NUL", [0x01] = "M_ADR", [0x02] = "M_PWD", [0x03] = "M_FILE",
    [0x04] = "M_OK", [0x05] = "M_EOB", [0x06] = "M_GOT", [0x07] = "M_ERR",
    [0x08] = "M_BSY", [0x09] = "M_GET", [0x0A] = "M_SKIP", [0x0B] = "M_CHAT",
    [0x0C] = "M_OPM", [0x0D] = "M_OPT", [0x0E] = "M_VER", [0x0F] = "M_EXTCMD"
    }
    local binkp_options = {
    ["CRAM-MD5"] = "CRAM-MD5 authentication", ["CRYPT"] = "Encryption support",
    ["ND"] = "No dupes mode", ["NR"] = "Non-reliable mode", ["CHAT"] = "Chat capability",
    ["ZIPPER"] = "On-the-fly compression", ["ZLIB"] = "ZLIB compression",
    ["BZP2"] = "BZIP2 compression", ["GZ"] = "GZIP compression", ["NDA"] = "No dupes asymmetric",
    ["EXTCMD"] = "Extended commands support", ["CHUNKING"] = "File chunking support",
    ["CRAM-SHA1"] = "CRAM-SHA1 authentication", ["CRAM-SHA256"] = "CRAM-SHA256 authentication"
    }

    -- ====== Protocol Registration ======
    local binkp_proto = Proto("BINKP", "BinkP Protocol")
    local fields = binkp_proto.fields
    fields.header = ProtoField.uint16("binkp.header", "Header", base.HEX) fields.command_flag = ProtoField.bool("binkp.command", "Command Flag", 16, nil, 0x8000)
    fields.length = ProtoField.uint16("binkp.length", "Length", base.DEC, nil, 0x7FFF)
    fields.command = ProtoField.uint8("binkp.cmd", "Command", base.HEX) fields.arguments = ProtoField.string("binkp.args", "Arguments")
    fields.data = ProtoField.bytes("binkp.data", "Data")

    -- ====== Utility Functions ======
    local function bit_and(a, b)
    if bit32 then return bit32.band(a, b)
    elseif bit then return bit.band(a, b)
    else return a & b
    end
    end
    local function safe_buffer_read(buffer, offset, length)
    if offset < 0 or length < 0 or offset + length > buffer:len() then return nil end
    return buffer(offset, length)
    end

    -- ====== Argument Parsing ======
    local function format_command_args(cmd, args)
    if not args or args == "" then return "" end
    if cmd == 0x01 then -- M_ADR
    return "Addresses: " .. args
    elseif cmd == 0x03 then -- M_FILE
    return "File: " .. args
    elseif cmd == 0x0D then -- M_OPT
    local opts, descs = {}, {}
    for opt in args:gmatch("%S+") do
    table.insert(opts, opt)
    table.insert(descs, opt .. " (" .. (binkp_options[opt] or "Unknown") .. ")")
    end
    return "Options: " .. table.concat(descs, ", ")
    elseif cmd == 0x0E then -- M_VER
    return "Version: " .. args
    else
    return args
    end
    end

    -- ====== Main Dissector ======
    function binkp_proto.dissector(buffer, pinfo, tree)
    if buffer:len() == 0 then return end
    pinfo.cols.protocol = "Binkp"
    local subtree = tree:add(binkp_proto, buffer(), "Binkp Protocol Data")
    local offset = 0
    local count = 0

    while offset + 2 <= buffer:len() do
    local hdrbuf = safe_buffer_read(buffer, offset, 2)
    if not hdrbuf then break end
    local header = hdrbuf:uint()
    local is_command = bit_and(header, 0x8000) ~= 0
    local packet_length = bit_and(header, 0x7FFF)

    if offset + 2 + packet_length > buffer:len() then
    -- Not enough data for full packet; add as raw data and stop
    subtree:add(fields.data, buffer(offset, buffer:len()-offset))
    break
    end

    local packet_tree = subtree:add(buffer(offset, 2 + packet_length), string.format(
    "Binkp %s (Length: %d)", is_command and "Command" or "Data", packet_length))

    packet_tree:add(fields.header, buffer(offset, 2))
    packet_tree:add(fields.command_flag, buffer(offset, 2))
    packet_tree:add(fields.length, buffer(offset, 2))
    offset = offset + 2

    if is_command and packet_length > 0 then
    local cmdbuf = safe_buffer_read(buffer, offset, 1)
    local cmd = cmdbuf and cmdbuf:uint() or 0
    local cmd_name = binkp_commands[cmd] or string.format("Unknown (0x%02X)", cmd)
    packet_tree:add(fields.command, buffer(offset, 1)):append_text(" (" .. cmd_name .. ")")

    if packet_length > 1 then
    local argsbuf = safe_buffer_read(buffer, offset + 1, packet_length - 1)
    local args = argsbuf and argsbuf:string() or ""
    packet_tree:add(fields.arguments, buffer(offset + 1, packet_length - 1)):set_text(format_command_args(cmd, args))
    if count == 0 then
    pinfo.cols.info = string.format("Command: %s (%s)", cmd_name, args)
    end
    else
    if count == 0 then
    pinfo.cols.info = string.format("Command: %s", cmd_name)
    end
    end
    elseif not is_command and packet_length > 0 then
    packet_tree:add(fields.data, buffer(offset, packet_length))
    if count == 0 then
    pinfo.cols.info = string.format("Data (%d bytes)", packet_length)
    end
    end
    offset = offset + packet_length
    count = count + 1
    if count > 100 then break end
    end
    end

    -- ====== Heuristic Registration ======
    local function heuristic_checker(buffer, pinfo, tree)
    if pinfo.dst_port == 24554 or pinfo.src_port == 24554 then
    return false -- let static registration handle
    end
    if buffer:len() >= 3 then
    local header = buffer(0, 2):uint()
    local is_command = bit_and(header, 0x8000) ~= 0
    local length = bit_and(header, 0x7FFF)
    if length <= buffer:len() - 2 and length < 32768 then
    if is_command and length > 0 then
    local cmd = buffer(2, 1):uint()
    if binkp_commands[cmd] then
    binkp_proto.dissector(buffer, pinfo, tree)
    return true
    end
    elseif not is_command then
    binkp_proto.dissector(buffer, pinfo, tree)
    return true
    end
    end
    end
    return false
    end

    -- ====== Registration ======
    local tcp_port = DissectorTable.get("tcp.port")
    tcp_port:add(24554, binkp_proto) -- Only static registration for standard port binkp_proto:register_heuristic("tcp", heuristic_checker) tcp_port:add_for_decode_as(binkp_proto)


    Best regards,
    dp.

    --- GoldED+/OSX 1.1.5-b20250409
    * Origin: All is good in St. John's Wood (2:5001/100.1)
  • From Valentin Kuznetsov@2:5053/51.51 to Dmitry Protasoff on Sun Jun 29 10:08:47 2025
    [�] �ਢ��, ��� �����, Dmitry ?

    28 ��� 2025 ���� �� ��ᠫ(�) � All:

    �᫨ ����-� ��ᯨ稫�, ��� ���, 㤮��� ᬮ���� �� ��䨪 �
    wireshark, � ��� lua �ਯ�:

    -+-

    -- Binkp Protocol Dissector for Wireshark
    -- Version: 2025-06-28

    ����᭠� ��㪠!

    [�] ����, Dmitry, ���⫨���� ⥡� ������� ! ...
    --- GoldED+/W32 1.1.4.5, FastFTN v1.55
    * Origin: �㤠 ���堫 .pkt - ����让 ����让 ᥪp��! (2:5053/51.51)
  • From Nil A@2:5015/46 to Valentin Kuznetsov on Sun Jun 29 10:18:26 2025
    Hello, Valentin!

    Sunday June 29 2025 10:08, from Valentin Kuznetsov -> Dmitry Protasoff:

    �᫨ ����-� ��ᯨ稫�, ��� ���, 㤮��� ᬮ���� �� ��䨪 �
    wireshark, � ��� lua �ਯ�:
    ����᭠� ��㪠!

    1. DP ᯠ���, �� ��� ���頥� ���騩 䨤����. � �� ��ᠢ�, �� ����� ��࠭�� 2. ����� �㪨 �१ ��⮢� �ய�����, �� �� �⪮�ॢ��, �� � �� ���� १���� �஢����, ��� �� ����� ������.

    Best Regards, Nil
    --- GoldED+/LNX 1.1.5-b20240306
    * Origin: ChatGPT can make mistakes. Check important info. (2:5015/46)
  • From Valentin Kuznetsov@2:5053/51.51 to Nil A on Sun Jun 29 12:33:22 2025
    [�] �ਢ��, ��� �����, Nil ?

    29 ��� 2025 ���� �� ��ᠫ(�) � ���:

    �᫨ ����-� ��ᯨ稫�, ��� ���, 㤮��� ᬮ���� �� ��䨪 �
    wireshark, � ��� lua �ਯ�:
    ����᭠� ��㪠!

    1. DP ᯠ���, �� ��� ���頥� ���騩 䨤����. H� �� ��ᠢ�, ��
    ����� ��࠭�� 2. ����� �㪨 �१ ��⮢� �ய�����, �� �� �⪮�ॢ��, �� � �� ���� १���� �஢����, ��� �� ����� ������.

    ������...

    ��⮢ ����� ᪠���� ����᭮, �ᮡ� �᫨ ��᪮�쪮 ࠧ ����� �+)

    [�] ����, Nil, ���⫨���� ⥡� ������� ! ...
    --- GoldED+/W32 1.1.4.5, FastFTN v1.55
    * Origin: H� ����ᨯ��� �㤠 �� ��� - � ��p� � �p�⨢ ���p�! (2:5053/51.51)