zeerd's blog         Search     Categories     Tags     Feed

闲来生雅趣,无事乐逍遥。对窗相望雪,一盏茶香飘。

给Wireshark添加基于Lua的SOME/IP解析插件

#SOME/IP #WireShark @Ethernet


Contents:

下面是一个简单的示例,仅支持最简单的SOME/IP数据解析。

并没有完全实现解析,也没有全面考虑SD中存在多Entry和多Option时的偏移计算问题。

示例

-- SOME/IP Protocol

-- declare our protocol
someip_proto = Proto("someip","SOME/IP Protocol")

serviceId        = ProtoField.uint16(
                                      "someip.service",
                                      "Service Id",
                                      base.HEX)
methodId         = ProtoField.uint16(
                                      "someip.method",
                                      "Method Id",
                                      base.HEX)
length           = ProtoField.uint32(
                                      "someip.length",
                                      "Length",
                                      base.DEC)
clientId         = ProtoField.uint16(
                                      "someip.client",
                                      "Client Id",
                                      base.HEX)
sessionId        = ProtoField.uint16(
                                      "someip.session",
                                      "Session Id",
                                      base.HEX)
protocolVersion  = ProtoField.uint8(
                                      "someip.protocol",
                                      "Protocol Version",
                                      base.DEC)
interfaceVersion = ProtoField.uint8(
                                      "someip.interface",
                                      "Interface Version",
                                      base.DEC)
messageType      = ProtoField.uint8(
                                      "someip.messagetype",
                                      "Message Type",
                                      base.HEX)
returnCode       = ProtoField.uint8(
                                      "someip.returncode",
                                      "Return Code",
                                      base.HEX)
entriesLength    = ProtoField.uint32(
                                      "someip.entrieslength",
                                      "Length of Entries Array",
                                      base.DEC)
optionsLength    = ProtoField.uint32(
                                      "someip.optionslength",
                                      "Length of Options Array",
                                      base.DEC)
portNumber       = ProtoField.uint32(
                                      "someip.portnumber",
                                      "Port Number",
                                      base.DEC)

ipv4             = ProtoField.new(
                                      "IPv4-Address",
                                      "someip.ipv4",
                                      ftypes.IPv4)

someip_proto.fields = {
    serviceId,
    methodId,
    length,
    clientId,
    sessionId,
    protocolVersion,
    interfaceVersion,
    messageType,
    returnCode,
    entriesLength,
    optionsLength,
    portNumber,
    ipv4
}

-- create a function to dissect it
function someip_proto.dissector(buffer,pinfo,tree)
    pinfo.cols.protocol = "SOME/IP"
    local subtree = tree:add(someip_proto,buffer(),"SOME/IP Protocol Data")
    subtree:add(serviceId, buffer(0,2))
    subtree:add(methodId, buffer(2,2))
    subtree:add(length, buffer(4,4))
    subtree:add(clientId, buffer(8,2))
    subtree:add(sessionId, buffer(10,2))
    subtree:add(protocolVersion, buffer(12,1))
    subtree:add(interfaceVersion, buffer(13,1))
    subtree:add(messageType, buffer(14,1))
    subtree:add(returnCode, buffer(15,1))

    if buffer(0,2):uint() == 0xffff and buffer(2,2):uint() == 0x8100 then
        subtree = subtree:add(buffer(16), "SD Payload: " .. buffer(16))
        subtree:add(buffer(16,1), "Flags: " .. buffer(16,1))
        subtree:add(entriesLength, buffer(20,4))
        if buffer(24,1):uint() == 0x01 then
            local offset1e = 24;
            subtree1e = subtree:add(buffer(offset1e,16), "1st Entry: ")
            subtree1e:add(buffer(offset1e,1),
                          "Type: Offer Service: "
                          .. buffer((offset1e),1))
            subtree1e:add(buffer((offset1e + 1),1),
                          "Index 1st options: "
                          .. buffer((offset1e + 1),1))
            subtree1e:add(buffer((offset1e + 2),1),
                          "Index 2nd options: "
                          .. buffer((offset1e + 2),1))
            subtree1e:add(buffer((offset1e + 3),1),
                          "# of opt 1 & 2: "
                          .. buffer((offset1e + 3),1))
            subtree1e:add(buffer((offset1e + 4),2),
                          "Service ID: "
                          .. buffer((offset1e + 4),2))
            subtree1e:add(buffer((offset1e + 6),2),
                          "Instance ID: "
                          .. buffer((offset1e + 6),2))
            subtree1e:add(buffer((offset1e + 8),1),
                          "Major Version: "
                          .. buffer((offset1e + 8),1))
            subtree1e:add(buffer((offset1e + 9),3),
                          "TTL: "
                          .. buffer((offset1e + 9),3))
            subtree1e:add(buffer((offset1e + 12),4),
                          "Minor Version: "
                          .. buffer((offset1e + 12),4))
        end
        if buffer(20,4):uint() > 16 then
            subtree2e = subtree:add(buffer(40,16),
                                    "2nd Entry: "
                                    .. buffer(40,16))
        end
        if buffer(4,4):uint() > (12 + 4 + buffer(20,4):uint()) then
            local offset1o = 24 + buffer(20,4):uint();
            subtree:add(optionsLength, buffer(offset1o,4))
            subtree1o = subtree:add(buffer((offset1o + 4),12), "1st Option: ")

            subtree1o:add(buffer((offset1o + 4),2),
                          "Length: "
                          .. buffer((offset1o + 4),2))
            subtree1o:add(buffer((offset1o + 6),1),
                          "Type: "
                          .. buffer((offset1o + 6),1))
            subtree1o:add(ipv4,
                          buffer((offset1o + 8),4))
            subtree1o:add(buffer((offset1o + 13),1),
                          "L4-Proto: "
                          .. buffer((offset1o + 13),1))
            subtree1o:add(portNumber, buffer((offset1o + 14),2))
            if buffer(offset1o,4):uint() > 12 then
                subtree2o = subtree:add(buffer(offset1o+16,12),
                                        "2nd Option: "
                                        .. buffer(offset1o+16,12))
            end
        end
    else
        subtree:add(buffer(16), "Payload: " .. buffer(16))
    end
end

-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
tcp_table = DissectorTable.get("tcp.port")
-- register our protocol to handle udp port 7777
udp_table:add(30490,someip_proto)
udp_table:add(31000,someip_proto)
tcp_table:add(31000,someip_proto)

安装

理论上来说,Plugin要安装到Wireshark的路径下。但是,每个不同的系统可能安装路径都不同,所以最简单的办法是全局搜索一下wireshark的路径。

user@ubuntu:~$ find /usr/ | grep -i wireshark | grep -i plugins
/usr/lib/x86_64-linux-gnu/wireshark/plugins
/usr/lib/x86_64-linux-gnu/wireshark/plugins/2.6
/usr/lib/x86_64-linux-gnu/wireshark/plugins/2.6/codecs
/usr/lib/x86_64-linux-gnu/wireshark/plugins/2.6/codecs/l16mono.so
...
user@ubuntu:~$ sudo vim /usr/lib/x86_64-linux-gnu/wireshark/plugins/2.6/someip.lua

参照

Lua/Dissectors Creating a Wireshark dissector in Lua - part 1 (the basics) ProtoField ProtoField.uint32