How to find out the length of the HTTP packet header?

I know how to do this manually (looking at a hex dump). How can I get the same automatically? Do I need to use the API? I have a wired monitor and a Microsoft network monitor.

+7
source share
4 answers

This can be achieved simply with the help of the Lua dissector , which adds an HTTP header field to the package tree, allowing you to filter it, as shown in this screenshot:

enter image description here

Copy this Lua script to your plugins directory (for example, ${WIRESHARK_HOME}/plugins/1.4.6/http_extra.lua ) and restart Wireshark (if it is 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 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 
+8
source

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

There are some good resources for creating Wireshark plugins, for example:

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 is a video describing how to add a field that is detected by the protocol decoder as a custom column:

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

The fact is that you do not want to reimplement the HTTP protocol decoder.

What I would do is find the source code of the embedded HTTP decoder and look at adding a new field, such as http.header_length , like the existing http.content_length :

img

I did not look at the code, but I would suggest that it is quite easy to add. If you send the patch to the Wireshark team, they will probably also include your new field in the next version.

+2
source

The code published by user568493 did not work for me at all, so he changed it to a post-dissector, and also did not read the number of bytes correctly. It also took into account IP and Ethernet bytes.

This is my version that 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) 
+2
source

I found that this way of calling the previous dissector in the chain somehow interferes with the reassembly of the HTTP packet made to encode the "chunked" transmission. That is, if your response has the title "Transfer-Encoding: chunked", the original HTTP analyzer tries to collect data, and if you connect it using such http_wrapper, then the reassembly will fail.

For example, this causes HTTP statistics to fail. Statistics / HTTP / Packet Counter will give you, say, 6 requests and 4 responses, which is not so: =)

It is better to set up such varieties of "added values" by calling the "register_postdissector" API or a test to reassemble the logic.

0
source

All Articles