Lua解剖器导致Wireshark消耗所有可用内存

时间:2015-04-02 11:29:50

标签: lua wireshark-dissector

我的协议非常繁琐,有效载荷相当大。我试图让我的Lua解剖器利用Wireshark的TCP重组,然后解析字节。如果我在.pcap文件中只有几个数据包,我的解剖器运行良好 - 重组正在工作,并且一旦到达最后一个PDU,字节就像预期的那样。帧数越多,Wireshark的内存消耗就越快(也越大)(直到它耗尽并对我失败)。但是,要达到这一点并不需要很多帧。非常感谢您的协助。

SOMETHING_TCP_PORT = 30003
SOMETHING = Proto("SOMETHING","SOMETHING")

function SOMETHING.init()
end

function SOMETHING.dissector(buffer, pinfo, tree)
if buffer:len() > 3 then
if string.upper(tostring(buffer(0, 4))) == "0401F0CE" then
    tvbLength = 20728
elseif string.upper(tostring(buffer(0, 4))) == "0501F0CE" then
    tvbLength = 12024
elseif string.upper(tostring(buffer(0, 4))) == "2201F0CE" then
    tvbLength = 7028
elseif string.upper(tostring(buffer(0, 4))) == "2B01F0CE" then
    tvbLength = 7028
else
    tvbLength = buffer:len()
end
end

pinfo.cols.info = "SOMETHING "
pinfo.cols.protocol = "SOMETHING"

local n = pinfo.desegment_offset or 0
while true do
local nextPDU = n + tvbLength

if nextPDU > buffer:len() then
    pinfo.desegment_len = nextPDU - buffer:len()
    pinfo.desegment_offset = n
    return
end

if string.upper(tostring(buffer(n, 4))) == "2201F0CE" or string.upper(tostring(buffer(n, 4))) == "2B01F0CE" then
    if string.upper(tostring(buffer(n, 4))) == "2201F0CE" then
        pinfo.cols.info:append("- Some Message ")

        subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")

        subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
        n = n + 4
    elseif string.upper(tostring(buffer(n, 4))) == "2B01F0CE" then
        pinfo.cols.info:append("- Some Other Message ")

        subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")

        subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
        n = n + 4
    else
        return
    end

    subtree:add(buffer(n, 4), "  Message size = " .. buffer(n, 4):le_uint() .. " bytes")
    if buffer(n, 4):le_uint() ~= 7028 then
        subtree:add(buffer(n, 4), "  Message size is incorrect!")
    end
    n = n + 4

    -- DECODE HERE

    n = nextPDU
    if nextPDU == buffer:len() then
        return
    end
end

if string.upper(tostring(buffer(n, 4))) == "0401F0CE" then
    pinfo.cols.info:append("- Some Message ")

    subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")

    subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
    n = n + 4

    subtree:add(buffer(n, 4), "  Message size = " .. buffer(n, 4):le_uint() .. " bytes")
    if buffer(n, 4):le_uint() ~= 20728 then
        subtree:add(buffer(n, 4), "  Message size is incorrect!")
    end
    n = n + 4

    -- DECODE HERE

    n = nextPDU
    if nextPDU == buffer:len() then
        return
    end
end

if string.upper(tostring(buffer(n, 4))) == "0501F0CE" then
    pinfo.cols.info:append("- Some Message ")

    subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")

    subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
    n = n + 4

    subtree:add(buffer(n, 4), "  Message size = " .. buffer(n, 4):le_uint() .. " bytes")
    if buffer(n, 4):le_uint() ~= 12024 then
        subtree:add(buffer(n, 4), "  Message size is incorrect!")
    end
    n = n + 4

    -- DECODE HERE

    n = nextPDU
    if nextPDU == buffer:len() then
        return
    end
end
end
end

tcp_table = DissectorTable.get("tcp.port")

tcp_table:add(SOMETHING_TCP_PORT,SOMETHING)

1 个答案:

答案 0 :(得分:1)

我相信发生的事情是wireshark卡在你的while循环中,并且永远不会从它返回。这可能发生,因为在某些情况下,您的代码永远不会nextPDU大于buffer:len()。例如,如果解剖器看到一个TCP段,其前4个字节匹配您希望看到的十六进制字符串之一,那么它将设置tvbLength = buffer:len(),进入while循环变量n等于0,因此nextPDU等于buffer:len() ...但等于,而不是大于,因此while循环不会返回...... 永远。由于while循环中的if-then语句分配内存(通过创建多个TvbRange s),内存使用量将不断增长和增长。

因此,您必须更改代码逻辑,以防止陷入永久循环。例如,验证每个循环上的nextPDU值更改或其他内容。

此外,您的代码效率相当低 - 它会多次创建一堆TvbRange个对象和Lua字符串,而不是一次。

例如,在解剖器功能的顶部:

if buffer:len() > 3 then
    if string.upper(tostring(buffer(0, 4))) == "0401F0CE" then
        tvbLength = 20728
    elseif string.upper(tostring(buffer(0, 4))) == "0501F0CE" then
        tvbLength = 12024
    elseif string.upper(tostring(buffer(0, 4))) == "2201F0CE" then
        tvbLength = 7028
    elseif string.upper(tostring(buffer(0, 4))) == "2B01F0CE" then
        tvbLength = 7028
    else
        tvbLength = buffer:len()
    end
end

if-then块中有三个导致内存分配的东西:

  1. buffer(0,4)在C代码和Lua中创建一个TvbRange对象。
  2. tostring() TvbRange在Lua中创建了一个字符串。
  3. string.upper()在Lua中创建另一个字符串。
  4. 你可以在上面的if-then块中将这三样东西调用四次,具体取决于elseif子句是否被执行。对于上面的数字2和3,它们将仅在Lua中为所有四个if / elseif子句创建一个字符串,因为它们产生相同的字符串,而Lua内部仅存储给定字符串的一个副本;但仍然需要额外的处理。相反,你应该这样做:

    if buffer:len() > 3 then
        local msgType = string.upper(tostring(buffer(0, 4)))
        if msgType == "0401F0CE" then
            tvbLength = 20728
        elseif msgType == "0501F0CE" then
            tvbLength = 12024
        elseif msgType == "2201F0CE" then
            tvbLength = 7028
        elseif msgType == "2B01F0CE" then
            tvbLength = 7028
        else
            tvbLength = buffer:len()
        end
    end
    

    这两者都减少了分配的内存,并提高了性能。

    顺便说一句,如果buffer:len() 大于3,该怎么办?然后tvbLength未设置为任何内容。

    接下来你有这个:

        if string.upper(tostring(buffer(n, 4))) == "2201F0CE" or string.upper(tostring(buffer(n, 4))) == "2B01F0CE" then
            if string.upper(tostring(buffer(n, 4))) == "2201F0CE" then
                pinfo.cols.info:append("- Some Message ")
    
                subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")
    
                subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
                n = n + 4
            elseif string.upper(tostring(buffer(n, 4))) == "2B01F0CE" then
                pinfo.cols.info:append("- Some Other Message ")
    
                subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")
    
                subtree:add(buffer(n, 4), "Found - " .. string.upper(tostring(buffer(n, 4))))
                n = n + 4
            else
                return
            end
    
            subtree:add(buffer(n, 4), "  Message size = " .. buffer(n, 4):le_uint() .. " bytes")
            if buffer(n, 4):le_uint() ~= 7028 then
                subtree:add(buffer(n, 4), "  Message size is incorrect!")
            end
            n = n + 4
    
            -- DECODE HERE
    
            n = nextPDU
            if nextPDU == buffer:len() then
                return
            end
        end
    

    同样,您为他们创建了多个TvbRange对象和字符串,依此类推,即使它们相同。所以请这样做:

        local msgTypeBuf = buffer(n, 4)
        local msgType = string.upper(tostring(msgTypeBuf))
        if msgType == "2201F0CE" or msgType == "2B01F0CE" then
            if msgType == "2201F0CE" then
                pinfo.cols.info:append("- Some Message ")
    
                subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")
    
                subtree:add(msgTypeBuf, "Found - " .. msgType)
                n = n + 4
            elseif msgType == "2B01F0CE" then
                pinfo.cols.info:append("- Some Other Message ")
    
                subtree = tree:add(SOMETHING, buffer(), "SOMETHING - Some Message")
    
                subtree:add(msgTypeBuf, "Found - " .. msgType)
                n = n + 4
            else
                return
            end
    
            local msgLengthBuf = buffer(n, 4)
            local msgLength = msgLengthBuf:le_uint()
            subtree:add(msgLengthBuf, "  Message size = " .. msgLength .. " bytes")
            if msgLength ~= 7028 then
                subtree:add(msgLengthBuf, "  Message size is incorrect!")
            end
            n = n + 4
    
            -- DECODE HERE
    
            n = nextPDU
            if nextPDU == buflen then
                return
            end
        end
    

    同样在后来的if-then语句中。