让你在Wireshark中的数据包好看点(Lua脚本调试)

难看的抓包二进制数据流!

在这里插入图片描述
图1
在服务端调试网络问题时,我们一般会通过tcpdump命令去抓取我们关心的数据包,然后拿到Windows下使用Wireshark抓包工具进行分析二进制数据流,虽然Wireshark已经把链路层(Link Layer)、网络层(Internet Layer)、传输层(Transport Layer)和常见的应用层(Application Layer)协议的包头/包体数据,分层解析出来了,但是对于应用层是私有协议的数据包,Wireshark没办法识别。好家伙,每次如果打开应用层的数据包,看着一大串二进制数据流,然后对照私有协议的解析方式,一个个字节的比对,这效率也太低了吧。

好在Wireshark提供了自定义Lua脚本的方式,来自定义解析应用层数据包,我们来试试。

1. 私有协议消息头定义

  • 假设我们的私有协议,包含消息头和消息体,消息头是一个POD类型的结构体,定义如下
struct BananaHead
{
    uint32_t MsgLen;                // 消息长度
    uint32_t FunctionCode;          // 功能标识
    uint8_t Type;
    uint8_t BitFieldLow : 3;        // 位域低3位
    uint8_t BitFieldHigh : 5;       // 位域高5位
    union {
        uint16_t NodeNo;
        uint8_t reserved[2];
    };
    union {
        uint32_t Union4B;
        struct
        {
            char UnionLow3B[3];     // 低3字节当uint32_t使用,业务中代表消息体的长度
            uint8_t UnionHigh1B;
        };
    };
    uint64_t Token;
    uint32_t ConnectionID;
    uint32_t UserDefined;
};
  • 结构体在解析时,需要注意以下几点
    • 位域的解析(位操作,还好)
    • 联合体的解析(C++写习惯了,初次遇到uint24很不习惯)
    • 字节序(大小端)

2. 脚本编写,解析消息头

--[[
    Lua脚本批量注释
    把脚本命名为:banana_head_parse.lua
    ......
]]

-- 定义新的协议
BananaHead = Proto("BananaHead", "Custom Head Protocol")

print("Loading BananaMsg Protocol")

-- 定义枚举表
local TypeEnum = {
    [0] = "POST",
    [1] = "GET",
    [3] = "PUT"
}

local DestEnum = {
    [0] = "去姥姥家",
    [1] = "去外婆家",
    [2] = "回窝"
}

-- 定义协议的字段
local f_MsgLen = ProtoField.uint32("BananaHead.MsgLen", "消息长度", base.DEC)
local f_FunctionCode = ProtoField.uint32("BananaHead.FunctionCode", "功能码", base.DEC)
local f_Type = ProtoField.uint8("BananaHead.Type", "消息类型", base.HEX, TypeEnum)
-- 低3位
local f_BitFieldLow = ProtoField.uint8("BananaHead.BitFieldLow", "BitFieldLow", base.DEC, DestEnum, 0x07)
-- 高5位,BananaHead.BitFieldLow=3,BananaHead.BitFieldHigh=5,则该字节值:0x00101_011
local f_BitFieldHigh = ProtoField.uint8("BananaHead.BitFieldHigh", "BitFieldHigh", base.DEC, nil, 0xF8)
local f_NodeNo = ProtoField.uint16("BananaHead.NodeNo", "NodeNo", base.DEC)
local f_UnionLow3B = ProtoField.uint24("BananaHead.UnionLow3B", "UnionLow3B", base.DEC)
local f_UnionHigh1B = ProtoField.uint8("BananaHead.UnionHigh1B", "UnionHigh1B", base.DEC)
local f_Token = ProtoField.uint64("BananaHead.Token", "Token", base.HEX)
local f_ConnectionID = ProtoField.uint32("BananaHead.ConnectionID", "ConnectionID", base.HEX)
local f_UserDefined = ProtoField.uint32("BananaHead.UserDefined", "UserDefined", base.HEX)

-- 将字段添加到协议中
BananaHead.fields = {f_MsgLen, f_FunctionCode, f_Type, f_BitFieldLow, f_BitFieldHigh, f_NodeNo, f_UnionLow3B, f_UnionHigh1B, f_Token, f_ConnectionID, f_UserDefined}

-- 解析器函数
function BananaHead.dissector(buffer, pinfo, tree)
    -- 检查包长度是否足够长
    if buffer:len() < 32 then return false end

    -- 按逻辑判断是否为目标协议
    -- 例如检查某个字段值是否在预期范围
    local MsgLenVal = buffer(0, 4):le_uint()
    if MsgLenVal < 32 then return false end

    local SubTree = tree:add(BananaHead, buffer(), "BananaMsg Protocol Data")

    -- 解析字段
    SubTree:add(f_MsgLen, buffer(0, 4):le_uint()):append_text(" Bytes")
    SubTree:add(f_FunctionCode, buffer(4, 4):le_uint())
    SubTree:add(f_Type, buffer(8, 1))

    local TypeVal = buffer(8, 1):uint()
    local BitFieldLowVal = bit.band(TypeVal, 0x07)
    local BitFieldHighVal = bit.rshift(bit.band(TypeVal, 0xF8), 3)

    SubTree:add(f_BitFieldLow, buffer(8, 1), BitFieldLowVal)
    SubTree:add(f_BitFieldHigh, buffer(8, 1), BitFieldHighVal)
    
    SubTree:add(f_NodeNo, buffer(10, 2))
    SubTree:add(f_UnionLow3B, buffer(12, 3):le_uint()):append_text(" Bytes")
    SubTree:add(f_UnionHigh1B, buffer(15, 1))

    local TokenVal_Le = buffer(16, 8):le_uint64()
    local TokenVal_Be = buffer(16, 8):uint64()
    SubTree:add(f_Token, buffer(16, 8)):append_text(" Little-Endian(" .. TokenVal_Le .. "), Big-Endian(" .. TokenVal_Be .. ")")

    SubTree:add(f_ConnectionID, buffer(24, 4))

    local UserDefinedVal_Le = buffer(28, 4):le_uint()
    local UserDefinedVal_Be = buffer(28, 4):uint()
    SubTree:add(f_UserDefined, buffer(28, 4)):append_text(" Little-Endian(" .. UserDefinedVal_Le .. "), Big-Endian(" .. UserDefinedVal_Be .. ")")
    
    -- 设置信息列
    pinfo.cols.protocol = "BananaMsg"
    
    return true  -- 表示成功解析包
end

-- 注册启发式解析器
BananaHead:register_heuristic("tcp", BananaHead.dissector)
BananaHead:register_heuristic("udp", BananaHead.dissector)

3. 用用看

在这里插入图片描述
图2

  • 把脚本命名为:xxxx.lua(名字自定义)
  • 丢到如图所示的路径下(如图2)

在这里插入图片描述
图3
在这里插入图片描述
图4

  • 重启Wireshark,或者重新载入 Lua 插件(如图3)
  • Lua 的控制台输出在这里,可以看到脚本中的print("Loading BananaMsg Protocol")输出到了控制台,我们可以通过这个来调试我们的Lua脚本(如图4)

4. 使用效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值