Wireshark Lua 插件教程

本?主要介紹 Lua 腳本在 Wireshark 中的應?, Lua 腳本可以在 Wireshark 中完成如下功能:

  • 從?絡包中提取數據, 或者統計?些數據包(Dumper)

  • 需要解析?種 Wireshark 不提供原??持的協議(Dissector)

?例

協議解析

VREP 協議是 NOGD 框架對于 TRIP 協議的?種延伸和擴展. Wireshark 原?并不提供對于 VREP 協議的?持, 下圖展?了腳本前后對?.

(a) VREP 原始字節流如下
VREP raw byte stream

(b) 腳本解析過后的信息
VREP with Lua script

數據流提取

Wireshark 對 RTPRTSP 均提供?持, 但是沒提供對于 RTP over RTSP 協議的?持, 可以利?此處腳本提供的協議對此完成解析. 下圖展?了這種差異.

(a) RTP over RTSP 原始信息
RTP over RTSP raw

(b) 腳本加強解析后的信息
RTP over RTSP with Lua

使??法

假定你要使? foo.lua 腳本

  1. 將腳本拷?到 Wireshark home ?錄, 如 C:\Program\Files\Wireshark\foo.lua
  2. 修改 init.lua 腳本(C:\Program\Files\Wireshark\init.lua), 在末尾添加?? dofile("foo.lua")
  3. 重啟 Wireshark 使腳本?效

不同類型的腳本的使??法:

  • Dissector 在選定的數據流中右擊 -> 解碼為… -> 選擇腳本注冊的協議, 如 RTPP.
  • Dumper 在?具菜單下?選擇注冊的 dumper.(如 Dump MPEG TS Packet)

解析器(Dissector)

注冊新協議

注冊新協議的?般步驟.

  1. 注冊新協議

    • 基于 UDP 相對而??較簡單, 逐個解析 IP 包即可
    • 基于 TCP 解析器?較復雜, 需要考慮 TCP 重組(TCP Reassembly)
  2. 定義協議字段

  3. 注冊協議字段

  4. 定義解析函數

  5. 注冊到協議端口號

解析器代碼框架

local ror = Proto("ror", "RTP over RTSP Protocol")-- 定義協議字段
local pf_ror_magic = ProtoField.uint8("ror.magic", "Magic", base.HEX)
local pf_ror_channel = ProtoField.uint8("ror.channel", "Interleaved Channel", base.HEX)
local pf_ror_length = ProtoField.uint16("ror.length", "Length")-- 注冊協議字段
ror.fields = {pf_ror_magic ,pf_ror_channel ,pf_ror_length ,
}-- 在此處定義你精妙絕倫的解析函數function ror.dissector(tvbuf, pinfo, root)-- tvbuf: TCP segment-- pinfo: packet column info-- root: node info in the display zoneend-- 指定協議端?, 此處是tcp 端?
local tcp_dissector_table = DissectorTable.get("tcp.port")
tcp_dissector_table:add(554, ror)

TCP 包重組問題

作為 tcp 解析器必須要?能?處理下??種情況

  1. TCP 數據段只含有協議數據包的前?部分
  2. TCP 數據段含有多個協議數據包
  3. 協議數據包在 TCP 數據段的中間部分, 因為協議包的前?部分可能沒有被捕獲到
  4. 數據包可能有被截斷的情形
  5. 以上?種情形的任意組合

對以上問題的應對策略.

  1. 針對 4, 簡單來說就是不解析切斷的包(return 0)
  2. 針對 3, 解析函數必須要做?定的合法性檢查, 如果不是屬于該協議的包, 那么就丟棄該包(return 0)
  3. 針對 2, 在解析函數??做?個 while 循環(return 已解析的?度)
  4. 針對 1, 盡最?可能去確定協議數據包的?度, 如果不能確定, 那么就返回?個默認值 DESEGMENT_ONE_MORE_SEGMENT

dissector 函數的返回值如下:

  1. 如果 TCP 數據段攜帶的數據不屬于當前協議, 那么返回 0
  2. 如果需要更多的數據才能繼續解析, 那么設置 desegment_len, desegment_offset, 返回值為 nil 或者已解析的?度都可以
  3. 如果不需要更多數據, 那么返回 nil 或者已經解析的?度都可以

Dumper

可以導出指定的協議字段到?件. 可選的字段:

  1. 來?預定義的字段(ip.src, tcp.port, rtsp.length)
  2. ?定義的字段(ror.magic)

Dumper 代碼框架

-- 定義感興趣的字段
-- wireshark 現已?持的協議的字段
local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")
-- ?定義協議的字段
local ror_channel = Field.new("ror.channel")-- 激活對話框時候的回調
local function init_payload_dump(file, filter)local tap = Listener.new(nil, filter)-- this function is going to be called once each time our filter matchesfunction tap.packet(pinfo, tvb)-- do some fancy workendretap_packets()tap:remove()
end-- 窗?回調
local function begin_dialog_menu()new_dialog("Dump MPEG TS Packets", init_payload_dump, "Output file", ilter")
end-- 注冊窗?
register_menu("Dump MPEG TS Packets", begin_dialog_menu, MENU_TOOLS_UNSORTED)

樣例解析

如下是?些解析樣例.

  1. VREP Dissector
  2. RTP Over RTSP Dissector
  3. MPEG Dumper
  4. RTP over RTSP Dumper

VREP Dissector 解析樣例

這個文件比較長, 請參考我的Github Repo

RTP Over RTSP Dissector 解析樣例

-- 1. declare a new type of protocol
local rtpp = Proto("rtpp", "RTP over RTSP(iPanel Flavor)")-- 2. define some field into the rtpp
local pf_rtpp_magic = ProtoField.uint8("rtpp.magic", "Magic", base.HEX)local pf_rtpp_channel = ProtoField.uint8("rtpp.channel", "Interleaved Channel", base.HEX)
local pf_rtpp_length = ProtoField.uint16("rtpp.length", "Length")-- data 就是?法識別凈荷內容的情況下簡單的將其設置為?進制數據的?法
local default_parser = Dissector.get("data")-- 3. 注冊新協議擁有的字段, 這些字段可作為以后抽取數據之?
rtpp.fields = {pf_rtpp_magic,pf_rtpp_channel,pf_rtpp_length,
}-- 前向聲明
local dissect_rtpp
local rtpp_min_len = 4-- 此處處理TCP 重傳的邏輯
function rtpp.dissector(tvbuf, pktinfo, root)local segment_length = tvbuf:len()local bytes_consumed = 0local reported_len = tvbuf:reported_length_remaining()if segment_length ~= reported_len then-- captured packets are being sliced/cut-off,-- so don't try to desegment/reassemblereturn 0endwhile bytes_consumed < segment_length do-- 此處會調?具體的解析函數local result = dissect_rtpp(tvbuf, pktinfo, root, bytes_consumed)if result == 0 thenreturn 0elseif result > 0 thenbytes_consumed = bytes_consumed + resultelsetinfo.desegment_offset = bytes_consumedresult = -resultpktinfo.desegment_len = resultreturn segment_lengthendendreturn bytes_consumed
end-- RTP over RTSP 有基本的RTSP 協議信令也有數據流,
-- 對基本的信令?默認的RTSP 解析器來解析
-- 對interleaved-channel 形式的按照其載荷類型來解析
dissect_rtpp = function(tvbuf, pinfo, root, offset)local msglen = tvbuf:len() - offsetdebug("sub_buf len=" .. msglen .. ", offset=" .. offset)if msglen < rtpp_min_len thendebug("sliced packet")return - DESEGMENT_ONE_MORE_SEGMENTend-- 分類解析if tvbuf:range(offset, 1):uint() ~= 0x24 then-- 以普通的rtsp 消息來解析debug("interpret packet as normal rtsp")local rtsp_dissector = Dissector.get("rtsp")-- 此處的返回值尚不清楚, 對此的處理也?較幼稚rtsp_dissector:call(tvbuf:range(offset, msglen):tvb(), pinfo, root)info("ret=" .. ret)return msglenelse-- interleaved-channel 形式debug("interpret packet as interleaved channel")local len_buf = tvbuf:range(offset + 2, 2)local payload_len = len_buf:uint()local packet_len = payload_len + 4debug("rtsp packet_len=" .. packet_len .. ", payload_len load=" .. pyload_len)-- ?少需要4 個字節才可以區分出該包是否屬于RTP over RTSP 協議if msglen < packet_len thenreturn -(packet_len - msglen)end-- 添加?些界?顯?信息root:add(pf_rtpp_magic,   tvbuf:range(offset + 0, 1))root:add(pf_rtpp_channel, tvbuf:range(offset + 1, 1))root:add(pf_rtpp_length,  len_buf)offset = offset + 4-- 取凈荷的第?個字節來區分mpeg 和rtplocal probe_byte = tvbuf:range(offset, 1):uint()debug("probe_byte=" .. string.format( "0x%x ", probe_byte))if probe_byte == 0x47 then-- 0x47 開頭的就?mpeg 的解析器來解析debug("raw mp2t packet, offset=" .. offset .. ", payload_len=" .. payload_len)local mpeg_dissector = Dissector.get("mp2t")while (offset + 188) <= packet_len dolocal mpeg_tvb = tvbuf:range(offset, packet_len - offset):tvb()-- 暫時不知道該函數的返回值是什么情況mpeg_dissector:call(mpeg_tvb, pinfo, root)offset = offset + 188endreturn offsetelseif probe_byte == 0x80 then-- 0x80 開頭的嘗試?rtp 來解析debug("RTP packet, offset=" .. offset .. ", payload_len=" .. payload_len)local rtp_dissector = Dissector.get("rtp")local rtp_tvb = tvbuf:range(offset, payload_len):tvb()-- 同樣也是對返回值的情況不太了解.rtp_dissector:call(rtp_tvb, pinfo, root)if msglen ~= packet_len thendebug("length not match, payload_len + 4=" .. packet_len.. ", msglen=" .. msglen)endreturn packet_lenelsedefault_parser(tvbuf, pinfo, root)return packet_lenendend
end-- 將RTP over RTSP 協議注冊到554 端?
-- 需要注意的是因為調?了原?RTSP 解析器, 所以我們的解析結果并不影響普通的rtsp 解析
tcp_dissector_table:add(554, rtpp)
tcp_dissector_table:add(2554, rtpp)
info("rtpp (RTP over RTSP) protocol registed at TCP port 554")

MPEG 流抽取器

if not GUI_ENABLED thenprint("mpeg_packets_dump.lua only works in Wireshark")return
end-- 聲明要抽取的字段
local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")-- 窗口回調函數
local function init_payload_dump(file, filter)local packet_count = 0-- 對任意的udp 包進?過濾-- filter 為符合BPF 格式的任意過濾器local tap = Listener.new(nil, filter)local myfile = assert(io.open(file, "w+b"))-- 每次BPF 過濾器過濾出?個ip 包就會調?下?的函數function tap.packet(pinfo, tvb)-- 檢查當前包??是否有mpeg 包if (mpeg_pid()) thenpacket_count = packet_count + 1-- dump 出所有的mpeg 包local contents = {mpeg_pkt()}-- 逐個包輸出到?件for i, finfo in ipairs(contents) dolocal tvbrange = finfo.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())-- myfile:flush()endendend-- re-inspect all the packets that are in the current capture, thereby-- triggering the above tap.packet functionretap_packets()-- cleanupmyfile:flush()myfile:close()tap:remove()debug("Dumped mpeg packets: " .. packet_count)
endlocal function begin_dialog_menu()new_dialog("Dump MPEG TS Packets", init_payload_dump, "Output file", "Packet filter (optional)\n\nExamples:\nip.dst == 225.1.1.4\nmp2t\nmp2t.pid == 0x300")
end-- 注冊到程序菜單
register_menu("Dump MPEG TS Packets", begin_dialog_menu, MENU_TOOLS_UNSORTED)

RTP over RTSP 負載抽取

local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")
local rtp_payload = Field.new("rtp.payload")local function init_payload_dump(file, filter)local packet_count = 0local real_filter = "(rtpp.channel)"if filter ~= nil and filter ~= "" then-- 拼接??輸?的過濾參數real_filter = real_filter .. " and (" .. filter ..")"endlocal tap    = Listener.new(nil, real_filter)local myfile = assert(io.open(file, "w+b"))function tap.packet(pinfo, tvb)-- 檢查是否有mpeg 數據包if (mpeg_pid()) thenlocal contents = {mpeg_pkt()}for i, finfo in ipairs(contents) dolocal tvbrange = finfo.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())endelse-- 檢查是否是rtp 包local payload = rtp_payload()if payload thenlocal tvbrange = payload.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())endendendretap_packets()myfile:flush() myfile:close() tap:remove()
end

調試腳本

在命令?中啟? Wireshark, 然后可以在當前命令?中看到 Lua 腳本的打印輸出. debug,warn(), info() 會輸出到 Lua consolestdout

Debug Lua Script

參考鏈接

  • Wireshark Lua
  • Lua Dissector
  • Wireshark Lua Example

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72066.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72066.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72066.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

吐血整理:在 Docker 中運行 Milvus

直接用docker 錯誤命令&#xff08;這個我試了三遍&#xff0c;浪費了很多時間&#xff09;&#xff1a; docker run -d --name milvus -p 19530:19530 -p 9091:9091 -v /var/lib/milvus:/var/lib/milvus milvusdb/milvus:latest 先看報錯&#xff1a; 2025-02-24 16:02:39 …

【uniapp】在UniApp中實現持久化存儲:安卓--生成寫入數據為jsontxt

在移動應用開發中&#xff0c;數據存儲是一個至關重要的環節。對于使用UniApp開發的Android應用來說&#xff0c;緩存&#xff08;Cache&#xff09;是一種常見的數據存儲方式&#xff0c;它能夠提高應用的性能和用戶體驗。然而&#xff0c;緩存數據在用戶清除緩存或清除應用數…

【Excel】 Power Query抓取多頁數據導入到Excel

抓取多頁數據想必大多數人都會&#xff0c;只要會點編程技項的人都不會是難事兒。那么&#xff0c;如果只是單純的利用Excel軟件&#xff0c;我還真的沒弄過。昨天&#xff0c;我就因為這個在網上找了好久發好久。 1、在數據-》新建查詢-》從其他源-》自網站 &#xff0c;如圖 …

星環科技推出DeepSeek全場景解決方案:即開即用、企業級部署、端側智能三位一體

星環科技&#xff08;688031.SH&#xff09;正式發布DeepSeek全場景解決方案&#xff0c;全面覆蓋個人用戶、企業客戶及行業場景需求&#xff0c;為用戶提供從個人到企業、從云端到本地的全方位AI應用支持&#xff0c;為不同需求的用戶提供了靈活、高效且安全的AI解決方案。 省…

let、const【ES6】

?“我唯一知道的就是我一無所知。” - 蘇格拉底 目錄 塊級作用域&#xff1a;var、let、const的對比&#xff1a;Object.freeze()&#xff1a; 塊級作用域&#xff1a; 塊級作用域指由 {} 包圍的代碼塊&#xff08;如 if、for、while、單獨代碼塊等&#xff09;形成的獨立作用…

C++ 常見面試知識點

主要介紹C常見面試題 1、說一下你理解的C中的四種智能指針 常用接口 T* get(); T& operator*(); T* operator->(); T& operator(const T& val); T* release(); 將 封裝在內部的指針置為nullptr, 但并不會破壞指針所指向的內容, 函 數返回的是內部指針置空之前…

AWS API Gateway灰度驗證實現

在微服務架構中,灰度發布(金絲雀發布)是驗證新版本穩定性的核心手段。通過將小部分流量(如 10%)導向新版本服務,可以在不影響整體系統的情況下快速發現問題。AWS API Gateway 原生支持流量按比例分配功能,無需復雜編碼即可實現灰度驗證。本文將詳細解析其實現方法、最佳…

基于coze+微信小程序實現圖片上傳并利用大模型解析

項目截圖&#xff1a; 實現代碼&#xff08;直接搬去可用&#xff09; 前提&#xff1a;需要填寫你的oss配置coze的api授權配置&#xff01;&#xff01;&#xff01; <template><view class"container"><!-- 高斯模糊背景 --><view class&qu…

Spring-boot3.4最新版整合swagger和Mybatis-plus

好家伙,今天終于開始用spring-boot3開始寫項目了&#xff0c;以后要徹底告別1.x和2.x了&#xff0c;同樣的jdk也來到了最低17的要求了,廢話不多說直接開始 這是官方文檔的要求jdk最低是17 maven最低是3.6 一. 構建工程,這一步就不需要給大家解釋了吧 二. 整合Knife4j 1.大于…

jQuery UI API 文檔

jQuery UI API 文檔 引言 jQuery UI 是一個基于 jQuery 的用戶界面庫,它提供了豐富的交互式組件和效果,使得網頁開發變得更加簡單和高效。本文檔旨在為開發者提供全面的 jQuery UI API 信息,幫助您更好地理解和應用 jQuery UI。 jQuery UI 簡介 什么是 jQuery UI? jQu…

java GUI編程實現一個計算器

概述 閑來無事&#xff0c;利用java awt庫寫個簡單的計算器玩玩。 實現 pom.xml <dependencies><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version></dependency&…

C#裝箱拆箱機制詳解

在C#中&#xff0c;裝箱&#xff08;Boxing&#xff09;和拆箱&#xff08;Unboxing&#xff09; 是值類型與引用類型之間轉換的核心機制。它們的實現直接影響程序的性能和類型安全。 一、裝箱&#xff08;Boxing&#xff09; 定義&#xff1a; 將值類型轉換為引用類型&#…

MySQL 8.4 SQL 全攻略:所有知識點與實戰場景

一、引言 MySQL 作為一款廣泛使用的開源關系型數據庫管理系統&#xff0c;在數據存儲和管理領域占據著重要地位。MySQL 8.4 版本在性能、功能和安全性等方面都有了顯著的提升。本文將全面介紹 MySQL 8.4 中 SQL 的各種知識點&#xff0c;并結合實戰場景進行詳細講解&#xff0…

Qt監控系統遠程回放/錄像文件遠程下載/錄像文件打上水印/批量多線程極速下載

一、前言說明 在做這個功能的時候&#xff0c;著實費了點心思&#xff0c;好在之前做ffmpeg加密解密的時候&#xff0c;已經打通了極速加密保存文件&#xff0c;主要就是之前的類中新增了進度提示信號&#xff0c;比如當前已經處理到哪個position位置&#xff0c;發個信號出來…

超高速工業相機的應用

超高速工業相機一般安裝在機器流水線上代替人眼來做測量和判斷&#xff0c;通過數字圖像攝取目標轉換成圖像信號&#xff0c;傳送給專用的圖像處理系統。圖像處理系統對這些信號進行各種運算來抽取目標的特征&#xff0c;進而根據判別的結果來控制現場的設備動作。一般來說&…

Plugin ‘mysql_native_password‘ is not loaded`

Plugin ‘mysql_native_password’ is not loaded mysql_native_password介紹1. 使用默認的認證插件2. 修改 my.cnf 或 my.ini 配置文件3. 加載插件&#xff08;如果確實沒有加載&#xff09;4. 重新安裝或檢查 MySQL 版本 遇到錯誤 ERROR 1524 (HY000): Plugin mysql_nativ…

蒼穹外賣-阿里云OSS文件上傳

蒼穹外賣-阿里云OSS文件上傳 一、阿里云OSS簡介**獲取AccessKey**獲取enpoint 二、代碼實現1 引入依賴2 定義OSS相關配置2.1 application-dev.yml2.2 application.yml 3 讀取OSS配置3.1 AliOssProperties 4 生成OSS工具類對象4.1 AliOssUtil4.2 OssConfiguration2.5 CommonCont…

【工具】前端 js 判斷當前日期是否在當前自然周內

【工具】前端 js 判斷當前日期是否在當前自然周內 function isCurrentNaturalWeek(targetDate) {const today new Date();const dayOfWeek today.getDay(); // 0&#xff08;周日&#xff09;到6&#xff08;周六&#xff09;// 計算本周一的日期&#xff08;自然周從周一開…

【操作系統】處理機調度

處理機調度 一、調度的概念、層次1.1 三個層次1.2 七狀態模型 二、調度算法的評價指標2.1 CPU利用率2.2 系統吞吐率2.3 周轉時間2.4 等待時間2.5 響應時間 三、進程調度&#xff08;低級調度&#xff09;的時機3.1 需要進程調度的情況3.2 不能進程調度的情況3.3 閑逛進程 四、進…

SpringBoot 使用 spring.profiles.active 來區分不同環境配置

很多時候&#xff0c;我們項目在開發環境和生產環境的配置是不一樣的&#xff0c;例如&#xff0c;數據庫配置&#xff0c;在開發的時候&#xff0c;我們一般用測試數據庫&#xff0c;而在生產環境&#xff0c;我們要用生產數據庫&#xff0c;這時候&#xff0c;我們可以利用 p…