I made a dirty workaround on the code from this post: http://ask.wireshark.org/questions/4639/extracting-soap-xml-payload/4835 The modified code differs from the original one in the following:
- It sets the Listener's filter to tcp rather than http or xml
- It creates two separate Field extractors:
local xml_field = Field.new("xml")
local tcp_segment = Field.new("tcp.data")
It checks whether the analyzed packet contains any segemented PDU, and if so it will append the its contents in soap_message.
Every time it checks if the soap_message contains both beginning and closing tags. If yes, it flushes the soap_message before begin processing the next packet.
The problem with this work around, is that sometimes it produces incorrect reassembly where it appends PDU contents from other packets if it happens to arrive in between as far as the soap message was not complete :(
Here is the code:
-- tap uses filter for tcp and ignores retransmissions
local tap = Listener.new(nil, "tcp && !tcp.analysis.retransmission")
-- XML field extractor
local xml_field = Field.new("xml")
-- TCP segment data extractor
local tcp_segment = Field.new("tcp.data")
local file = nil
local soap_message = ''
– #######################################################################
– # If not already open, this opens a file for writing (append mode)
– #######################################################################
local function open_file()
if not file then
local path = "." .. "/temp.xml"
print("opening file:", path)
file = assert(io.open(path, "a"),
"Can't open file for writing")
end
end
local HTML_REQ = {
["HTTP"] = 1,
["GET "] = 1,
["PUT "] = 1,
["POST"] = 1,
}
– #######################################################################
– # Extracts the XML field from the buffer and writes the field to file
– #######################################################################
local function handle_xml(pinfo, tvb)
if not file then
print("no file…ignoring packet")
return
end
– extract xml data if contained in single packet
local data = ''
local fieldinfo = xml_field()
local segmentinfo = tcp_segment()
– Check for PDUs
if segmentinfo then
segmentdata = tvb(segmentinfo.offset):string()
data = segmentdata
elseif fieldinfo then
xmldata = tvb(fieldinfo.offset):string()
data = xmldata
end
local starts = data:sub(1,4)
– some of these packets start w/HTTP header…skip to XML
if HTML_REQ[starts] ~= nil then
– local pos = string.find(xmldata, "<%?xml version")
local pos = string.find(data, "<soap:Envelope")
if not pos then
return
end
data = data:sub(pos)
end
soap_message = soap_message .. data
print("\n\n-- #"..pinfo.number.." ---------------------------------------------------\n")
print(data)
local soap_begin = string.find(soap_message, "<soap:Envelope")
local soap_end = string.find(soap_message, "</soap:Envelope>")
– Check for a the completion of the soap meassage
if soap_begin and soap_end then
file:write("\n\n– #"..pinfo.number.." —————————————————\n")
file:write(soap_message)
soap_message = ''
end
end
– #######################################################################
– # tap.packet() is called to notify the Listener of a packet that
– # matches its filter rule ("xml" in this case). This can be called
– # multiple times before tap.draw().
– #######################################################################
– #######################################################################
– # tap.packet() is called to notify the Listener of a packet that
– # matches its filter rule ("xml" in this case). This can be called
– # multiple times before tap.draw().
– #######################################################################
function tap.packet(pinfo, tvb)
print("\ntap.packet", "#"..pinfo.number)
-- XXX: Compensate for no tap.reset() in tshark
if not gui_enabled() then open_file() end
-- wrap the handler in a pcall() in case an error occurs
local ok, msg = pcall( function()
handle_xml(pinfo,tvb)
end )
-- print any error and bow out
if not ok then
print("wtf!", msg)
end
end
– #######################################################################
– # tap.draw() is called to notify the Listener to "draw" its results
– # that were accumulated in tap.packet(). This is normally called after
– # tap.packet(), based on "Preferences > Statistics > Tap update interval".
– #######################################################################
function tap.draw()
print("tap.draw")
– flush toilet (NOTE: When $file is garbage collected, it's
– automatically flushed and closed…that doesn't mean we
– can't do it sooner to free resources.)
if file then
print("closing file")
file:close()
file = nil
end
end
– #######################################################################
– # tap.reset() is called to notify the Listener to reset any variables
– # or counters in preparation for a packet (passed to tap.packet()).
– # This can be called multiple times before a packet is even seen.
– #
– # XXX: tshark doesn't call this function, but Wireshark does. Bug?
– #######################################################################
function tap.reset()
print("tap.reset")
open_file()
end
answered 11 Feb ‘13, 11:33
masgad
5●1●1●4
accept rate: 0%
Please upload a sample capture on http://cloudshark.org, and post a link here. What version of tshark are you using?
Thank you helloworld for your reply. tshark version: 1.9.0 and there you go a sample pcap: http://cloudshark.org/captures/74a6deb7aa4e