How to find out the HTTP header length of a packet

2020-06-16 15:15发布

I know how to do it manually (by looking at the hex dump). How can I obtain the same automatically? Do I have to use the APIs? I have both wireshark and Microsoft network monitor.

4条回答
姐就是有狂的资本
2楼-- · 2020-06-16 15:49

I've found that this way of calling previous dissector in chain somehow interferre with HTTP packet reassembly done for 'chunked' transfer encoding. That is if your response has 'Transfer-Encoding: chunked' header, the original HTTP dissector tries to reassemble the data and if you hook it over with such http_wrapper, then reassembling fails.

For example, this makes http statistics fail too. Statistics/HTTP/Packet Counter would give you, say 6 requests and 4 responses, which is not the case =)

One should better install such kind of 'added value' dissectors with 'register_postdissector' API call or test for reassembling logic carefully.

查看更多
叛逆
3楼-- · 2020-06-16 15:50

This can be achieved simply with a Lua dissector that adds an HTTP header field to the packet tree, allowing you to filter for it, as shown in this screenshot:

enter image description here

Copy this Lua script into your plugins directory (e.g., ${WIRESHARK_HOME}/plugins/1.4.6/http_extra.lua), and restart Wireshark (if already running).

do
        local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
        http_wrapper_proto.fields.hdr_len = ProtoField.uint32("http.hdr_len", "Header length (bytes)")

        -- HTTP frames that contain a header usually include the HTTP
        -- request method or HTTP response code, so declare those here
        -- so we can check for them later in the dissector.
        local f_req_meth    = Field.new("http.request.method")
        local f_resp_code   = Field.new("http.response.code")

        local original_http_dissector
        function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
                -- We've replaced the original http dissector in the dissector table,
                -- but we still want the original to run, especially because we need 
                -- to read its data. Let's wrap the call in a pcall in order to catch
                -- any unhandled exceptions. We'll ignore those errors.
                pcall(
                    function()
                        original_http_dissector:call(tvbuffer, pinfo, treeitem)
                    end
                )

                -- if the request method or response code is present,
                -- the header must be in this frame
                if f_req_meth() or f_resp_code() then

                        -- find the position of the header terminator (two new lines),
                        -- which indicates the length of the HTTP header, and then add
                        -- the field to the tree (allowing us to filter for it)
                        local hdr_str = tvbuffer():string()
                        local hdr_len = string.find(hdr_str, "\r\n\r\n") or string.find(hdr_str, "\n\n\n\n")
                        if hdr_len ~= nil then
                            treeitem:add(http_wrapper_proto.fields.hdr_len, hdr_len):set_generated()
                        end
                end
        end

        local tcp_dissector_table = DissectorTable.get("tcp.port")
        original_http_dissector = tcp_dissector_table:get_dissector(80) -- save the original dissector so we can still get to it
        tcp_dissector_table:add(80, http_wrapper_proto)                 -- and take its place in the dissector table
end
查看更多
太酷不给撩
4楼-- · 2020-06-16 16:07

Unfortunately, although you can create custom columns, the data you want in that column is not currently generated by the HTTP protocol decoder. Of course, there may be other tools that I'm not familiar with which can do this today, but as far as Wireshark is concerned you would have to add that functionality.

There are some good resources on creating Wireshark plugins, e.g.:

http://simeonpilgrim.com/blog/2008/04/29/how-to-build-a-wireshark-plug-in/

http://www.wireshark.org/docs/wsdg_html_chunked/ChDissectAdd.html

http://www.codeproject.com/KB/IP/custom_dissector.aspx

And here's a video describing how to add a field that's exposed by a protocol decoder as a custom column:

http://www.youtube.com/watch?v=XpUNXDkfkQg

The thing is, you don't want to re-implement the HTTP protocol decoder.

What I would do is find the source code for the built-in HTTP decoder and look at adding a new field such as http.header_length just like the existing http.content_length:

img

I haven't looked at the code, but I would guess that this is a pretty easy thing to add. If you submit a patch to the Wireshark team they will probably also include your new field in the next release.

查看更多
霸刀☆藐视天下
5楼-- · 2020-06-16 16:11

The Code posted by user568493 didn't work for me at all, So iv'e changed it to a post dissector, and also it was not counting the number of bytes correctly. It was also counting IP and Ethernet bytes.

This is my version, which works on 1.8.2:

local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
http_wrapper_proto.fields.hdr_len = ProtoField.uint32("http.hdr_len", "HTTP Header length (bytes)")

-- HTTP frames that contain a header usually include the HTTP
-- request method or HTTP response code, so declare those here
-- so we can check for them later in the dissector.
local f_req_meth    = Field.new("http.request.method")
local f_resp_code   = Field.new("http.response.code")

local original_http_dissector
function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
        -- if the request method or response code is present,
        -- the header must be in this frame
        if f_req_meth() or f_resp_code() then
                local start_offset = 0
                local end_offset = 0
                -- find the position of the header terminator (two new lines),
                -- which indicates the length of the HTTP header, and then add
                -- the field to the tree (allowing us to filter for it)
                local hdr_str = tvbuffer():string()
                if f_req_meth() then
                    start_offset = string.find(hdr_str, "GET")
                    end_offset = string.find(hdr_str, "\r\n\r\n")
                end
                if f_resp_code() then
                    start_offset = string.find(hdr_str, "HTTP")
                    end_offset = string.find(hdr_str, "\r\n\r\n")
                end
                local hdr_len = end_offset - start_offset + 4
                -- 4 Bytes because the \r\n\r\n are not part of the HTTP Payload, hence should be counted in the header length.
                if hdr_len ~= nil then
                    treeitem:add(http_wrapper_proto.fields.hdr_len, hdr_len):set_generated()
                end
        end
end

register_postdissector(http_wrapper_proto)
查看更多
登录 后发表回答