wireshark protobuf插件开发(ubuntu)

前言

protobuf是google团队开发的用于高效存储和读取结构化数据的工具。相比于json和xml,protobuf会把数据压缩得更小,大约是json格式的1/10,xml格式的1/20。正因如此,protobuf编码后的数据,不能像json、xml那样直观地呈现数据。本文将介绍如何解析利用wireshark自定义插件,解析protobuf数据包。

概要

wireshark的插件可以使用c或是lua脚本进行开发,考虑到灵活性,推荐使用lua脚本。

我理解wireshark插件的执行过程就是用插件去解析每一个数据包,解析过程中如果出错,则继续由其他插件尝试解析;如果解析正确,则表示由该协议解析并显示结果。

值得注意的是,当插件只处理了部分数据时,未处理部分的数据切片要继续交由其他插件尝试解析。例如一个基于TCP协议的RTSP数据包依次由Ethernet、Internet、TCP、RTSP插件解析,Ethernet协议解析该数据包的0 - 13byte,Internet协议解析该数据包的14 - 33byte,TCP协议解析了34 - 65byte,RTSP协议解析剩余的274 byte,至此数据包解析完成。
在这里插入图片描述

1.环境准备

1.1.安装wireshark

#环境是ubuntu 64位,windows开发笔者比较弱鸡

    $sudo apt-get update
    $sudo apt-get install wireshark

1.2 安装lua-protobuf支持库

wireshark中lua版本是5.2,所以需要先安装lua5.2

    $sudo apt-get update
    $sudo apt=get install lua5.2

克隆lua-protobuf项目并编译

	$git clone https://github.com/starwing/lua-protobuf.git
    $gcc -O2 -fPIC -I/usr/include/lua5.2 -c pb.c -o pb.o
    $gcc -shared -o pb.so -L/usr/local/lib pb.o

2.创建wireshark插件

我们通过一个例子来说明如何创建一个插件:

数据端口:7200
数据格式:
在这里插入图片描述

  • 协议标识:固定为0x00 0x00 0x00 0x01
  • 消息ID:标识Protobuf数据类型,这里只有一个消息ID0x0001
  • 长度:Protobuf数据长度
  • Protobuf数据:
    我们的Protobuf数据目前只有一个Person,对应的消息ID为0x0001。
	message Person{
	    required string name = 1;
	    required int32  age  = 2;
	    optional string email = 3;
	    enum PhoneType{
	        HOME = 1;
	        MOBILE = 2;
	        WORK = 3;
	    }
	    message Phone{
	        required int64 id = 1;
	        optional PhoneType type = 2 [default = HOME];
	    }
	    repeated Phone phoneNum = 4;
	}

大体思路如下:
1.创建一个wireshark插件,完成我们自定义数据包的识别,并提取协议标识、消息ID、数据长度、以及protobuf数据;
2.使用protobuf lua兼容库解析步骤1中提取出的protobuf数据,并显示;

2.1 创建插件,识别数据包及提取协议各字段内容

wireshark的自定义插件在\usr\lib\x86_64-linux-gnu\wireshark\plugins目录下,在该文件下创建一个xx.lua文件。

一个典型的wireshark插件代码结果如下:

do  
    local struct = Struct
    local data_dis = Dissector.get("data")
    -- 协议名称为 meteoric_proto,在Packet Details窗格显示为 XXX Protocol   
    -- 注意这里的Proto与protobuf一点关系也没有。
    local m_MeteoricProto = Proto("meteoric_proto","XXX Protocol")
    -- 添加协议字段ident、id、length和data
    local f_ident= ProtoField.bytes("meteoric_proto.ident","ident")
    local f_id= ProtoField.int32("meteoric_proto.id","ID")
    local f_len= ProtoField.int32("meteoric_proto.len","length")
    local f_data = ProtoField.bytes("meteoric_proto.data","Data")
    m_MeteoricProto .fields = { f_ident, f_id, f_len, f_data }

	--定义协议解析函数,解析正确则返回true,反之返回false
    local function Meteoric_dissector(buffer, pinfo, tree)
    	--取得数据长度
        local buf_len = buffer:len()

		--长度检测
        if buf_len < 8 then return false end

 		--头检测
        if (buffer(0,1):uint()~=0x00 or 
            buffer(1,1):uint()~=0x00 or 
            buffer(2,1):uint()~=0x00 or 
            buffer(3,1):uint()~=0x01) then
            return false
        end

		--字段解析
        tree:add(f_ident, buffer(0,4))  
        tree:add(f_id , buffer(4, 6):uint())  
        tree:add(f_len , buffer(6, 8):uint())  
        --这里只提取出了protobuf数据,并没有开始解析protobuf。
        tree:add(f_data , buffer(8, buf_len))  
        --设置协议显示
        pinfo.cols.protocol:set("XX_Protobuf")
        return true
    end

    function m_MeteoricProto.dissector(buffer, pinfo, tree) 
        --在主窗口的 Protocol 字段显示的名称为 XX_Protobuf

        if Meteoric_dissector(buffer, pinfo, tree) then          
        else
            -- data 这个 dissector 几乎是必不可少的; 当发现不是我的协议时, 交由其他协议尝试解析
            data_dis:call(buffer, pinfo, tree)
        end
    end

    --将该协议对象添加到tcp 7200端口上
    DissectorTable.get("tcp.port"):add(7200, m_MeteoricProto)
end

2.2 解析proto数据

首先生成将Person.proto生成.pb文件备用:

$protoc -o Person.pb Person.proto 
--加载pb对象
local pb = require "pb"
--载入pb文件 ,可以载入多个文件
pb.loadfile "Person.pb"
--反序列化,结果类型为table,
msgtable = pb.decode("Person", buffer:string())
--结果递归遍历显示
AddTreeNode(f_data, msgtable) 


local function AddTreeNode(nodeTree, msgTable)
     for k,v in pairs(msgTable) do
         if type(v) == "table" then
             AddTreeNode(nodeTree:add(k), v)
         else
             nodeTree:add(k..":", v)
         end
     end
 end

代码

    do  
        local struct = Struct
        local data_dis = Dissector.get("data")
        -- 协议名称为 meteoric_proto,在Packet Details窗格显示为 XXX Protocol   
        -- 注意这里的Proto与protobuf一点关系也没有。
        local m_MeteoricProto = Proto("meteoric_proto","XXX Protocol")
        -- 添加协议字段ident、id、length和data
        local f_ident= ProtoField.bytes("meteoric_proto.ident","ident")
        local f_id= ProtoField.int32("meteoric_proto.id","ID")
        local f_len= ProtoField.int32("meteoric_proto.len","length")
        local f_data = ProtoField.bytes("meteoric_proto.data","Data")
        m_MeteoricProto.fields = { f_ident, f_id, f_len, f_data }
        
    	-- protobuf解析结果递归显示
    	local function AddTreeNode(nodeTree, msgTable)
    	     for k,v in pairs(msgTable) do
    	         if type(v) == "table" then
    	             AddTreeNode(nodeTree:add(k), v)
    	         else
    	             nodeTree:add(k..":", v)
    	         end
    	     end
    	 end
    	--定义协议解析函数,解析正确则返回true,反之返回false
        local function Meteoric_dissector(buffer, pinfo, tree)
        	--取得数据长度
            local buf_len = buffer:len()
    
    		--长度检测
            if buf_len < 8 then return false end
    
     		--头检测
            if (buffer(0,1):uint()~=0x00 or 
                buffer(1,1):uint()~=0x00 or 
                buffer(2,1):uint()~=0x00 or 
                buffer(3,1):uint()~=0x01) then
                return false
            end
    
    		--字段解析
            tree:add(f_ident, buffer(0,4))  
            tree:add(f_id , buffer(4, 6):uint())  
            tree:add(f_len , buffer(6, 8):uint())  
            tree:add(f_data , buffer(8, buf_len))  
            
    		--加载pb对象
    		local pb = require "pb"
    		--载入pb文件 ,可以载入多个文件
    		pb.loadfile "Person.pb"
    		--反序列化,结果类型为table,
    		msgtable = pb.decode("Person", buffer(8, buf_len):string())
    		--结果递归遍历显示
    		AddTreeNode(f_data, msgtable) 
    		
            --设置协议显示
            pinfo.cols.protocol:set("XX_Protobuf")
            return true
        end
    
        function m_MeteoricProto.dissector(buffer, pinfo, tree) 
            --在主窗口的 Protocol 字段显示的名称为 XX_Protobuf
    
            if Meteoric_dissector(buffer, pinfo, tree) then          
            else
                -- data 这个 dissector 几乎是必不可少的; 当发现不是我的协议时, 交由其他协议尝试解析
                data_dis:call(buffer, pinfo, tree)
            end
        end
    
        --将该协议对象添加到tcp 7200端口上
        DissectorTable.get("tcp.port"):add(7200, m_MeteoricProto)
    end

参考资料

https://cloud.tencent.com/developer/article/1365481
https://www.jianshu.com/p/1e2f63a484d6

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
开发Wireshark插件是一个相对简单的过程。首先,需要了解Wireshark插件的结构和API。可以在Wireshark的官方文档中找到相关的信息和文档。然后,可以按照以下步骤进行Wireshark插件开发: 1. 使用C或者C++编写插件代码。Wireshark插件使用的是C语言和一些C++,所以需要熟悉这两种编程语言。 2. 在代码中使用Wireshark提供的API来访问和解析网络数据包。Wireshark提供了一系列函数和数据结构,用于访问网络数据包和解析协议。 3. 根据自己的需求,编写特定功能的插件代码。可以是解析某个特定协议的插件,也可以是添加新的功能或者修改现有功能的插件。 4. 编译插件代码。可以使用Wireshark提供的编译工具链来编译插件代码。编译后会生成一个.so(在UNIX/LINUX)或者.dll(在Windows)文件。 5. 将生成的.so或者.dll文件复制到Wireshark插件目录中。在UNIX/LINUX下一般是/usr/local/lib/wireshark/plugins/目录,在Windows下一般是C:\Program Files\Wireshark\plugins\目录。 6. 重新启动Wireshark插件将被加载并在Wireshark的菜单或者工具栏中显示。 为了能够在Wireshark开发和运行插件,可能需要获得root或管理员权限,以便访问网络接口。在一些情况下,可能还需要安装一些依赖库或者软件,如WinPcap。 请注意,为了保证插件的质量和安全性,应遵循Wireshark开发规范和最佳实践。同时,也应该遵守相关的法律法规,避免侵犯知识产权或者违反协议。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [wireshark插件开发](https://blog.csdn.net/comhaqs/article/details/7231968)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [wireshark插件开发详细流程(含源码)](https://blog.csdn.net/yang_chen_shi_wo/article/details/46669999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值