您的位置:首页 > 理论基础 > 计算机网络

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

2010-04-25 00:15 656 查看
一、问题:

用Wireshark抓包查看HTTP POST消息,Content-Type为application/x-www-form-urlencoded(对应HTML为<form method="POST">那种提交后的网络包)时不太方便,因为抓包只显示了原始的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 (qiangxiong.huang@gmail.com)
-- 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 (qiangxiong.huang@gmail.com)
-- 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐