一、平台

操作系统:windows 7

wireshark:1.10.3

lua:5.1

二、准备

lua 语言基本语法,特别是关于表操作和循环

wireshark 文档,包括用户使用文档和开发者文档,这些在 wireshark 官方网站都能找到

三、开始

我们首先定义一个简单的协议,我们使用 C 语言的语法描述,

1 struct foo
2 {
3     char protocol_type[16];     /* request response notify */
4     char service_type[16];      /* 我们定义的各种服务类型 */
5     unsigned int msg_len;       /* 消息体的长度 */
6     char msg_content[0];        /* 消息体的内容,由于是变长的所以采用此方法定义 */
7 };

现在可以让我们使用 lua 定义一个最基本的框架

 1 do
 2     --[[
 3         创建一个新的协议结构 foo_proto
 4         第一个参数是协议名称会体现在过滤器中
 5         第二个参数是协议的描述信息,无关紧要
 6     --]]
 7     local foo_proto = Proto("foo", "Foo Protolcol")
 8
 9     --[[
10         下面定义字段
11     --]]
12     local foo_protocol_type = ProtoField.string("foo.prototype", "Protocol Type", base.NONE)
13     local foo_service_type = ProtoField.string("foo.servicetype", "Service Type", base.NONE)
14     local foo_msg_len = ProtoField.uint32("foo.msglen", "Message Length", base.DEC)
15     local foo_msg_content = ProtoField.string("foo.msgcontent", "Message Content", base.NONE)
16
17     -- 将字段添加都协议中
18     foo_proto.fields = {
19         foo_protocol_type,
20         foo_service_type,
21         foo_msg_len,
22         foo_msg_content
23     }
24
25     --[[
26         下面定义 foo 解析器的主函数,这个函数由 wireshark调用
27         第一个参数是 Tvb 类型,表示的是需要此解析器解析的数据
28         第二个参数是 Pinfo 类型,是协议解析树上的信息,包括 UI 上的显示
29         第三个参数是 TreeItem 类型,表示上一级解析树
30     --]]
31     function foo_proto.dissector(tvb, pinfo, treeitem)
32
33         -- 设置一些 UI 上面的信息
34         pinfo.cols.protocol:set("FOO")
35         pinfo.cols.info:set("Foo Protocol")
36
37         local offset = 0
38         local tvb_len = tvb:len()
39
40         -- 在上一级解析树上创建 foo 的根节点
41         local foo_tree = treeitem:add(foo_proto, tvb:range(offset))
42
43         -- 下面是想该根节点上添加子节点,也就是自定义协议的各个字段
44         -- 注意 range 这个方法的两个参数的意义,第一个表示此时的偏移量
45         -- 第二个参数代表的是字段占用数据的长度
46         foo_tree:add(foo_protocol_type, tvb:range(offset, 16))
47         offset = offset+16
48         foo_tree:add(foo_service_type, tvb:range(offset, 16))
49         offset = offset+16
50         foo_tree:add(foo_msg_len, tvb:range(offset, 4))
51         offset = offset+4
52
53         -- 计算消息内容的长度
54         local foo_content_len = tvb_len-offset
55         foo_tree:add(foo_msg_content, tvb:range(offset, foo_content_len))
56         offset = offset+foo_content_len
57
58     end
59
60     -- 向 wireshark 注册协议插件被调用的条件
61     local tcp_port_table = DissectorTable.get("tcp.port")
62     tcp_port_table:add(12345, foo_proto)
63 end

四、扩展

(1)单 TCP 分节多应用 PDU

这种情况可以在我们的协议解析函数中使用循环解决,但是应用层 PDU 一般都需要有我们自定义的分割标识符,不然无法区分,这里我们使用协议尾端标记的方式,采用0xFF分割,这里我们假设我们的协议体中不会出现这个值,也就是我们的消息体长度字段的值不会出现这个值。

(2)单应用 PDU 多 TCP 分节

这种情况就需要 wireshark 为我们重新拼接被 TCP 协议栈拆分的数据,不过这已经有接口可用了,下面是处理两种情况的框架

 1 do
 2     -- 这里便于运算需要将数据类型进行转换
 3     local tvbrange = tvb:range(0)
 4     local bytearray = tvbrange:bytes()
 5     local offset = pinfo.desegment_offset or 0
 6
 7     while true do
 8         local pdu_flg = false
 9         local pdu_end_index = 0
10
11         -- ByteArray 类型的索引与 C 类似
12         -- 这与 lua 本身处理表的方式有所区别
13         for i = offset, tvb_len do
14             if 0xFF == bytearray:get_index(i) then
15                 pdu_flg = true
16                 pdu_end_index = i
17             end
18         end
19
20         -- 如果没有找到 PDU 的结束符,进行合包延迟解析
21         if false == frame_end_flg then
22             -- 如果明确知道这个应用协议还需要多少字节
23             -- 可以明确地将需要的值填上,而不是使用下面的值
24             -- 只是表示需要更多的分节
25             pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
26             return
27         end
28
29         -- 下面是正常的处理流程,在上面的代码中已经有体现了
30         -- 不过此时协议最大边界为 pdu_end_index
31
32     end
33 end

五、完善

(1)谈到网络协议,如果涉及到整数必然会有字节序的问题,如果 wireshark 默认使用的是大端字节序,如果协议中的整数采用的是小端字节序,那么请考虑使用 TreeItem 类型的 le_add() 方法替代 add() 方法。

(2)在 add 和 le_add 方法中,我们可以显式设定我们自己的值,可以给 add 方法传递第三个值,例如,

1         local protocol_type = tvb:range(offset, 16):string()
2         foo_tree:add(foo_protocol_type, tvb:range(offset, 4), protocol_type)

这样显示的就是 protocol_type 的内容,另外这里的 protocol_type 类型一定要与上面定义 foo_protocol_type 让 wireshark 解析的一致,不然这个值是无效的,也就是说这个地方 protocol_type 如果是整数,就是无效,反过来也是一样。

(3)在协议解析树上增加节点不一定要提前定义字段,也就是字段的定义不是必须的,例如,

1 local protocol_type = tvb:range(offset, 16):string()
2 foo_tree:add(tvb:range(offset, 16), "Protocol Type: " .. protocol_type)

效果是一样的,但是在过滤器中无法使用此字段。

(4)pinfo.cols.info:set 方法可以延迟调用,也就说可以在确定了消息的各种属性之后在调用,这样可以更清晰的显示协议的摘要。

六、参考

(1)wireshark 用户手册,在 wireshark 的安装目录下有 chm 的版本,最值得参考的是第11章的数据类型和各种方法的解释。

(2)重组被拆分的 TCP 分节,http://stackoverflow.com/questions/13138088/how-do-i-reassemble-tcp-packet-in-lua-dissector

(3)处理一个分节多应用 PDU,http://stackoverflow.com/questions/14387426/reassembling-packets-in-a-lua-wireshark-dissector

(4)调用子协议的方法,http://blog.csdn.net/phunxm/article/details/5972904

转载于:https://www.cnblogs.com/wendellyi/p/3475461.html

使用 lua 编写 wireshark 协议解析插件相关推荐

  1. wireshark协议解析器原理与插件编写

    工作原理 每个解析器解码自己的协议部分, 然后把封装协议的解码传递给后续协议. 因此它可能总是从一个Frame解析器开始, Frame解析器解析捕获文件自己的数据包细节(如:时间戳), 将数据交给一个 ...

  2. wireshark协议解析器 源码分析 封装调用

    源码分析 Wireshark启动时,所有解析器进行初始化和注册.要注册的信息包括协议名称.各个字段的信息.过滤用的关键字.要关联的下层协议与端口(handoff)等.在解析过程,每个解析器负责解析自己 ...

  3. 串口调试助手源代码 qt编写 带协议解析 帧判断 通信数据保存等功能

    串口调试助手源代码 qt编写 带协议解析 帧判断 通信数据保存等功能 使用说明介绍 1.功能介绍: 采用Qt编写的串口调试助手工具,功能齐全,除了具备十六进制收发及文件保存等基本功能外,还具有以下功能 ...

  4. 修改wireshark协议解析规则

    不同的协议有不同的解码器,wireshark尝试为每个包尝试找到正确的解码器,特定的情况有可能会选择错误的解码器. 1.使用了其它协议的标准端口,被错误解码,使用udp的80端口发送数据被当作QUIC ...

  5. wireshark协议解析错误解决方法

    起因: 由于wireshark能解析的协议太多,某些数据包会被错误的解析成别的协议 解决: 在被错误解析的分组上右键,选择协议首选项,disable 错误的协议,直至以正确的协议进行解析. 也要到上面 ...

  6. 调用wireshark(二):调用协议解析器

    上文[调用wireshark(一):初次尝试 http://www.cnblogs.com/zzqcn/archive/2013/05/11/3072362.html ]已经介绍了调用wireshar ...

  7. 用Lua语言编写Wireshark dissector插件

    from: http://yoursunny.com/t/2008/Wireshark-Lua-dissector/ Wireshark是一款著名的网络协议分析工具,基于GPLv2协议开源,支持Lin ...

  8. wireshark添加h264解析插件

    1.下载h264解析插件rtp_h264_extractor.lua https://github.com/volvet/h264extractor 2.将插件rtp_h264_extractor.l ...

  9. 使用Lua编写whireshark插件

    whireshark支持Lua.C.C++编写的插件 在这里,我简单介绍如何使用Lua编写whireshark插件. 一.插件的存放位置 whireshark插件分为个人插件和全局插件,在window ...

最新文章

  1. Web App、Hybrid App与Native App的设计差异
  2. 干货|深度!“人工智能+制造”产业发展研究报告
  3. POJ 3761:Bubble Sort——组合数学
  4. 有关oracle数据库中的日期显示问题
  5. 《笨办法学python》6_笨办法学Python 习题 25: 更多更多的练习
  6. 吕述望 计算机网络专家,特稿: 中科院吕述望教授:互联网名不符实
  7. MyBatis查询,返回值Map或ListMap
  8. 有关Oracle最大连接数的问题
  9. 如何用 Visual Studio 2017 开发 Arduino 应用程序
  10. [BZOJ2339][HNOI2011]卡农
  11. 基于ELMO Composer的MAXON RE40电机增益调节
  12. Pspice的文本输入方法
  13. 计算机主机hdmi接口是什么意思,什么是hdmi接口?
  14. python xy 3_python(3):文件操作/os库
  15. 网页加速器1.0.5.6 免费版
  16. linux定时任务生效_Linux 定时任务不生效的问题
  17. Codeforces 949A Zebras(构造)
  18. 永久短网址生成 可以永久使用的短链接推荐
  19. 查找数字的下标--二分法
  20. map和multimap的用法详解

热门文章

  1. html任务管理,六款必备的工作任务管理工具推荐
  2. 关于vray 5.2的使用(自研笔记)(二)
  3. 关于嵌入式系统的启动(装载)
  4. 永中office的秘密
  5. Altium Designer绘制PCB电路板一般流程
  6. ios学习--代码集锦
  7. linux ssdb 安装 乱码,SSDB 命令行工具 ssdb-cli
  8. TCP BBR 短评
  9. PS2024后期调色滤镜插件Alien Skin Exposure7
  10. 优秀的程序员热爱偷懒