用Wireshark lua编写的协议解析器查看Content-Type为application/x-www-form-urlencoded的HTTP抓包

一、问题:

用Wireshark抓包查看HTTP POST消息,Content-Type为application/x-www-form-urlencoded(对应HTML为

那种提交后的网络包)时不太方便,因为抓包只显示了原始的param1=value1¶m2=value2这样的数据,没有把参数提出出来,并对参数进行url decode,如下图所示:

 

二、问题解决过程及心得

Google上没有找到解决方法,最近发现wireshark可以用lua编写解析器,我就试着自己写了一个。过程中走了一些弯路总结一下:

1. 不能用postdissectors,因为HTTP请求有时候是会分几个TCP包的,这种情况下postdissectors只能得到每个包的数据,不能得到完整的application/x-www-form-urlencoded体部内容。

2. 不用自己重新写一个dissector去监听http的tcp端口,这样,你不仅还要调用原来http的dissector,还要自己判断tcp分包了没(reassembled)。

 

刚开始的几种方法都不太理想,最后,看了一下wireshark源码中http解析包的实现,发现只要写一个dissector注册到media_type的dissector table里就可以了。具体的分析请参考《如何在wireshark里用lua脚本编写dissector解析HTTP BODY (after TCP reassembled)》(http://blog.csdn.net/jasonhwang/archive/2010/04/25/5526383.aspx)。

 

 

 

三、如何搞定!!

好,上面的东西大家看不懂没关系只要照下面步骤来一下就搞定了:

1. 在wireshark安装目录(如C:/Program Files/Wireshark)下编写一个文本文件my_form_urlencoded.lua,文件内容如下:

 

 -- Decode param=value from "application/x-www-form-urlencoded" type http body -- Author: Huang Qiangxiong ([email protected]) -- change log: -- 2010-04-20 -- Just can play. -- 2010-04-24 -- Add option "Turn on/off debug tree item" to preference window. -- Add option "add_orig_item" to preference window. ------------------------------------------------------------------------------------------------ do local form_urlencoded_proto = Proto("my_form_urlencoded", "MIME Encapsulation [HQX's plugins]: application/x-www-form-urlencoded") --setup options that could be found in preferences->MY_FORM_URLENCODED local prefs = form_urlencoded_proto.prefs prefs.debug_flag = Pref.bool("Turn on debug (a [DEBUG Tree proto: my_form_urlencoded] item will appear in Package Details tree)", false, "If you turn of debug, (a [DEBUG Tree proto: my_form_urlencoded] item will appear in Package Details tree)") prefs.add_orig_item = Pref.bool("Show orignal wireshark's data-text-lines dissection item in Package Details tree", false, "Show orignal wireshark's data-text-lines dissection item in Package Details tree") -----------DEBUG Function ------------------------------------------------ --local debug_flag = true local dmap = {} function d(tree, msg) if prefs.debug_flag and tree then local dt = dmap[tree] if dt == nil then dt = tree:add("[DEBUG Tree for " .. form_urlencoded_proto.name .. "]") dmap[tree] = dt end dt:add("[DEBUG] " .. msg) end end --------------------------------------------------------------------------------- ---- url decode (from www.lua.org guide) function unescape (s) s = string.gsub(s, "+", " ") s = string.gsub(s, "%%(%x%x)", function (h) return string.char(tonumber(h, 16)) end) return s end ---- save old dissector local media_type_table = DissectorTable.get("media_type") local old_dissector = media_type_table:get_dissector("application/x-www-form-urlencoded") ---- my dissector function form_urlencoded_proto.dissector(tvb, pinfo, tree) d(tree, "pinfo.curr_proto=" .. pinfo.curr_proto) d(tree, "tvb:offset()=" .. tvb:offset()) d(tree, "tvb:len()=" .. tvb:len()) if prefs.add_orig_item then old_dissector:call(tvb, pinfo, tree) end -- begin build my tree local tvb_range = tvb() local content = tvb_range:string() -- add proto item to tree local subtree = tree:add(form_urlencoded_proto, tvb_range) -- add raw data to tree subtree:add(tvb_range, "[Raw Data] (" .. tvb_range:len() .. " bytes)"):add(tvb_range, content) -- add param value pair to tree local pairs_tree = subtree:add(tvb_range, "[Decoded Data]") local si = 1 local ei = 0 local count = 0 while ei do si = ei + 1 ei = string.find(content, "&", si) local xlen = (ei and (ei - si)) or (content:len() - si + 1) if xlen > 0 then pairs_tree:add(tvb(si-1, xlen), unescape(content:sub(si, si+xlen-1))) count = count + 1 end end pairs_tree:append_text(" (" .. count .. ")") end -- register this dissector media_type_table:add("application/x-www-form-urlencoded", form_urlencoded_proto) end

 

然后修改wireshark安装目录下的init.lua文件:

(1)把disable_lua = true; do return end;这行注释掉:在前面加“--”

(2)然后在init.lua文件最后面加一句:dofile("my_form_urlencoded.lua")

 

OK大功告成,重新打开抓包界面变为如下图:

 

可以看到,原来的Line-based Text...被替换成了行MIME Encapsulation ...。看该节点下[Raw Data]为原始数据,[Decoded Data]下为解开后的一个个参数(经过url decode)。

 

如果要显示原来的Line-based Text...行也可以,到preferences窗口里找到my_form_urlencoded协议,然后选上"Show orignal wireshark's data-text-lines dissection item in Package Details tree"选项即可。

 

 

 

实际上这种方法还可以解析其它媒体类型的HTTP Body,如何编写解析HTTP Body媒体数据的方法请参考《如何在wireshark里用lua脚本编写dissector解析HTTP BODY (after TCP reassembled)》(http://blog.csdn.net/jasonhwang/archive/2010/04/25/5526383.aspx)。

 

 

注:wireshark版本为1.2.7

 

 

2015年 更新:

-- Decode param=value from "application/x-www-form-urlencoded" type http body
-- Author: Huang Qiangxiong ([email protected])
-- change log:
--      2010-08-23
--          Place spaces before and after '=' between name and value ( convert '=' to ' = ').
--      2010-04-20
--          Just can play.
--      2010-04-24   
--          Add option "Turn on/off debug tree item" to preference window.
--          Add option "add_orig_item" to preference window.
------------------------------------------------------------------------------------------------
do
    local form_urlencoded_proto = Proto("my_form_urlencoded", "MIME Encapsulation [HQX's plugins]: application/x-www-form-urlencoded")

    --setup options that could be found in preferences->MY_FORM_URLENCODED
    local prefs = form_urlencoded_proto.prefs
    prefs.debug_flag = Pref.bool("Turn on debug (a [DEBUG Tree proto: my_form_urlencoded] item will appear in Package Details tree)", 
                                 false, 
                                 "If you turn of debug, (a [DEBUG Tree proto: my_form_urlencoded] item will appear in Package Details tree)")
    prefs.add_orig_item = Pref.bool("Show orignal wireshark's data-text-lines dissection item in Package Details tree", 
                                    false, 
                                    "Show orignal wireshark's data-text-lines dissection item in Package Details tree")
    -----------DEBUG Function ------------------------------------------------
    --local debug_flag = true
    local dmap = {}
    function d(tree, msg)
        if prefs.debug_flag and tree then
            local dt = dmap[tree]
            if dt == nil then 
                dt = tree:add("[DEBUG Tree for " .. form_urlencoded_proto.name .. "]")
                dmap[tree] = dt
            end
            dt:add("[DEBUG] " .. msg) 
        end
    end
    ---------------------------------------------------------------------------------
    
    ---- url decode (from www.lua.org guide)
    function unescape (s)
        s = string.gsub(s, "+", " ")
        s = string.gsub(s, "%%(%x%x)", function (h)
            return string.char(tonumber(h, 16))
        end)
        return s
    end
   
    ---- save old dissector
    local media_type_table = DissectorTable.get("media_type")
    local old_dissector = media_type_table:get_dissector("application/x-www-form-urlencoded")

    ---- my dissector
    function form_urlencoded_proto.dissector(tvb, pinfo, tree)
        d(tree, "pinfo.curr_proto=" .. pinfo.curr_proto)
        d(tree, "tvb:offset()=" .. tvb:offset()) 
        d(tree, "tvb:len()=" .. tvb:len()) 
        
        if prefs.add_orig_item then
            old_dissector:call(tvb, pinfo, tree)
        end
        
        -- begin build my tree
        local tvb_range = tvb()
        local content = tvb_range:string()
        
        -- add proto item to tree
        local subtree = tree:add(form_urlencoded_proto, tvb_range)
        
        -- add raw data to tree
        subtree:add(tvb_range, "[Raw Data] (" .. tvb_range:len() .. " bytes)"):add(tvb_range, content)

        -- add param value pair to tree
        local pairs_tree = subtree:add(tvb_range, "[Decoded Data]")
        local si = 1
        local ei = 0
        local count = 0
        while ei do
            si = ei + 1
            ei = string.find(content, "&", si)
            local xlen = (ei and (ei - si)) or (content:len() - si + 1)
            if xlen > 0 then
                -- pairs_tree:add(tvb(si-1, xlen), unescape(content:sub(si, si+xlen-1)))
                pairs_tree:add(tvb(si-1, xlen), unescape(content:sub(si, si+xlen-1):gsub("=", " = ", 1)))
                count = count + 1
            end
        end
        pairs_tree:append_text(" (" .. count .. ")")
        
    end

    -- register this dissector
    media_type_table:add("application/x-www-form-urlencoded", form_urlencoded_proto)

end

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Wireshark,Web)