草庐IT

Wireshark解析器(Dissector)插件-Lua

KSPT 2023-03-28 原文

现有问题

如果直接使用Wireshark查看常见诸如Http等协议报文,并不会有任何不便,

但是如果查看私有协议报文,无法区分哪些是TCP协议相关报文,哪些是含有消息体的私有协议报文,也只能看到一串Byte和对应ASCII编码的Data值,无法知道数据中的各个字节对应哪个字段代表什么含义,更不能根据这些对应字段值进行过滤

什么是解析器(Dissector)

解析器(Dissector)是Wireshark中的概念,用于解析协议,将报文中对应的Bytes转为相应的字段值

可以简单理解为Wireshark中的解码器。

它不止能解析将相应位置的Bytes转为对应字段,还能将解析出来的字段用于报文过滤,还能自定义信息(Info)列中显示的自定义信息。

能方便开发人员调试诊断协议相关问题,比如断连后不重连,报文不正确,未发心跳。

编写流程

解析器可以使用C语言编写,也可以使用Lua编写

本篇使用Lua编写,因为该语言是脚本语言,不需要编译后执行,方便开发修改调试

缺点是比C语言编写的解析器慢

编写解析器需要使用lua 语言 所以建议先学一点基础,或者碰到看不懂的再查也行

Lua基础知识请参考

添加解析器插件文件

  • 在%APPDATA%\Wireshark 中新建文件夹plugins ,可以使用Win+R 键然后输入%APPDATA%\Wireshark然后回车,快速打开该目录
  • 在plugins 文件夹下新建xxx.lua 文件,其中xxx 一般以协议名为文件名

解析器由什么部分组成

  • 协议定义
  • 字段定义
  • 协议和字段关联
  • 解析器主函数
  • 协议注册

解析器代码详解

-- 协议定义,名称为ScoreBoard,在Packet Details窗格显示为ScoreBoard Protocol
local p_ScoreBoard = Proto('ScoreBoard', 'ScoreBoard Protocol')

-- 协议的各个字段定义
local f_identifier = ProtoField.bytes('ScoreBoard.identifier', 'Identifier')
local f_operator =
    ProtoField.uint8(
    'ScoreBoard.operator',
    'Operator',
    base.HEX,
    -- 这个字段的数字值都有相应的含义,可以自动对应成字符串
    {
        [0] = 'get-value',
        [1] = 'set-value',
        [128] = 'resp-value',
        [16] = 'get-color',
        [17] = 'set-color',
        [144] = 'resp-color'
    }
)
-- 所有可能的字段都要定义,到时没有t:add就不会显示
local f_left = ProtoField.uint32('ScoreBoard.left', 'Value Left', base.DEC)
local f_right = ProtoField.uint32('ScoreBoard.right', 'Value Right', base.DEC)
local f_red = ProtoField.uint8('ScoreBoard.red', 'Color Red', base.DEC)
local f_green = ProtoField.uint8('ScoreBoard.green', 'Color Green', base.DEC)
local f_blue = ProtoField.uint8('ScoreBoard.blue', 'Color Blue', base.DEC)

-- 将字段添加到协议中
p_ScoreBoard.fields = {
    f_identifier,
    f_operator,
    f_left,
    f_right,
    f_red,
    f_green,
    f_blue
}

-- 获取Wireshark自带的Data解析器
-- 后续解析发现不是有效报文需要调用该解析器显示报文数据
local data_dis = Dissector.get('data')

local function ScoreBoard_dissector(buf, pkt, root)
    local buf_len = buf:len()
    -- 先检查报文长度,太短的不是我的协议
    if buf_len > 17 then
        return false
    end
    -- 取得前16字节identifier字段的值
    local v_identifier = buf(0, 16)
    -- 验证identifier是否正确
    if
        ((buf(0, 1):uint() ~= 226) or (buf(1, 1):uint() ~= 203) or (buf(2, 1):uint() ~= 181) or
            (buf(3, 1):uint() ~= 128) or
            (buf(4, 1):uint() ~= 203) or
            (buf(5, 1):uint() ~= 9) or
            (buf(6, 1):uint() ~= 78) or
            (buf(7, 1):uint() ~= 186) or
            (buf(8, 1):uint() ~= 163) or
            (buf(9, 1):uint() ~= 107) or
            (buf(10, 1):uint() ~= 246) or
            (buf(11, 1):uint() ~= 7) or
            (buf(12, 1):uint() ~= 206) or
            (buf(13, 1):uint() ~= 149) or
            (buf(14, 1):uint() ~= 63) or
            (buf(15, 1):uint() ~= 43))
     then -- 不正确就不是我的协议
        return false
    end
    -- 取得operator的值
    local v_operator = buf(16, 1)
    local i_operator = v_operator:uint()

    -- 现在知道是我的协议了,放心大胆添加Packet Details
    local t = root:add(p_ScoreBoard, buf)
    -- 在Packet List窗格的Protocol列也可以"做个小广告"
    pkt.cols.protocol = 'ScoreBoard'
    t:add(f_identifier, v_identifier)
    t:add(f_operator, v_operator)

    if ((i_operator == 1) or (i_operator == 128)) and (buf_len >= 25) then
        -- 把存在的字段逐个添加进去
        t:add(f_left, buf(17, 4))
        t:add(f_right, buf(21, 4))
    elseif ((i_operator == 17) or (i_operator == 144)) and (buf_len >= 20) then
        t:add(f_red, buf(17, 1))
        t:add(f_green, buf(18, 1))
        t:add(f_blue, buf(19, 1))
    end
    return true
end

--[[
    下面定义 foo 解析器的主函数,这个函数由 wireshark调用
    第一个参数是 Tvb 类型,表示的是需要此解析器解析的数据
    第二个参数是 Pinfo 类型,是协议解析树上的信息,包括 UI 上的显示
    第三个参数是 TreeItem 类型,表示上一级解析树
--]]
function foo_proto.dissector(tvb, pinfo, treeitem)
    -- 设置一些UI中报文列表中Proto列和Info列显示的信息
    pinfo.cols.protocol:set('FOO')
    pinfo.cols.info:set('Foo Protocol')

    if ScoreBoard_dissector(buf, pkt, root) then
        -- 如果是有效的报文
    else
        -- 当发现不是我的协议时,就使用Wiresahrk自带的Data解析器显示
        data_dis:call(buf, pkt, root)
    end
end

-- 向 wireshark 注册协议插件被调用的条件为TCP协议且端口为12345的报文
-- 符合条件就会调用上面的foo_proto.dissector函数
-- local udp_port_table = DissectorTable.get("udp.port")
local tcp_port_table = DissectorTable.get('tcp.port')
tcp_port_table:add(12345, foo_proto)

如何调试

重新加载脚本

  • 修改Lua 脚本
  • 在Wireshark 中使用Ctrl+Shift+L 快捷键重新加载修改后的Lua 脚本

查看控制台输出

  • Lua 脚本中print(VariableName) 在控制台输出对应变量值
  • Edit 编辑 -> Preferences... 首选项(Ctrl+Shif+P ) -> Advanced 高级
  • 搜索gui.console_open 并将对应值修改为 ALWAYS

如何使用

  • 在%APPDATA%\Wireshark 中新建文件夹plugins ,可以使用Win+R 键然后输入%APPDATA%\Wireshark然后回车,快速打开该目录
  • 复制编写好的脚本到该文件夹%APPDATA%\Wireshark\plugins
  • 重新打开抓包文件或者Ctrl+Shift+L 快捷键重新加载插件脚本

高级

  • 不绑定端口怎么办?

启发式解析器

在 Lua 中创建独立于端口(启发式)的 Wireshark 解调器|米卡的技术博客 (mika-s.github.io)

wireshark/README.heuristic at master - wireshark/wireshark (github.com)

  • 粘包,分包问题

粘包使用while 循环处理

分包设置pinfo.desegment_len 的值或者使用dissect_tcp_pdus 函数

使用 lua 编写 wireshark 协议解析插件_mb5fe55a9dbe9dd的技术博客_51CTO博客

11.6. Functions For New Protocols And Dissectors (wireshark.org)

  • 大端(Big End)小端(Little End)问题

Wireshark中默认是大端,如果需要处理小端协议,可以将add 函数替换为add_le 的函数

参考

Lua语法

Lua 5.2 Reference Manual - contents

教程

用Lua语言编写Wireshark dissector插件 (archive.org)

Creating a Wireshark dissector in Lua - part 1 (the basics) | Mika's tech blog (mika-s.github.io)

强烈推荐:Mika's tech blog (mika-s.github.io)

Wireshark Dissector文档

Dissectors (wireshark.org)

10.3. Example: Dissector written in Lua (wireshark.org)

Chapter 11. Wireshark's Lua API Reference Manual

11.7. Adding Information To The Dissection Tree (wireshark.org)


原文链接:https://www.cnblogs.com/KSPT/p/16688475.html

有关Wireshark解析器(Dissector)插件-Lua的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  4. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  5. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  6. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  7. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und

  8. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  9. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  10. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

随机推荐