#wireshark #lua #dissector

wirdigen

LUA Wireshark dissector验证器/生成器从JSON

3个版本 (破坏性更新)

0.3.0 2022年5月30日
0.2.0 2022年5月23日
0.1.0 2022年5月7日

#3 in #dissector

自定义许可证

32KB
520

RustCI Codecov RustAudit


目录

概述

Wirdigen (Wireshark DiGenerator) 是一个小的库,旨在根据要分析的包的JSON描述生成Wireshark的LUA dissector。

有关数据解包的更多信息,请参阅Wireshark 文档维基

如何使用

该库由两个工具组成

验证器

Validator 将JSON包描述与预定义的JSON模式进行比较,以确保插件生成时的数据完整性。

如果包描述无效,将通过 stderr 自动向用户报告错误,并提供详细的/描述。

use wirdigen::validator::Validator;
use wirdigen::error::WirdigenError;

fn foo() -> Result<(), WirdigenError> {
    // Load JSON file
    let file_path = "./example/example_dissector.json";
    let file = File::open(file_path)?;
    let rdr = BufReader::new(file);

    // Create serde JSON value from the file
    let value: Value = serde_json::from_reader(rdr)?;

    // Create Validator object
    let val = Validator::new()?;

    // Call to validation function
    match val.validate(&value) {
        true => println!("{}: VALID", file_path),
        false => println!("{}: INVALID", file_path)
    }
    Ok(())
}

生成器

Generator 生成基于用户提供的JSON输入的LUA插件。

use wirdigen::generator::Generator;
use wirdigen::error::WirdigenError;

fn foo() -> Result<(), WirdigenError> {
    // Load JSON file
    let file_path = "./example/example_dissector.json";
    let file = File::open(file_path)?;
    let rdr = BufReader::new(file);

    // Create Generator object
    let gen = Generator::default();
    // let gen = Generator::new();   <-- Alternative

    // Generate from a reader source
    let generated_file_path: String = gen.from_reader(rdr)?;
    println!("Generated: {}", generated_file_path);

    Ok(())
}

注意: Generator 不会对用户输入执行任何预验证。这是 Validator 的作用。在文件无效的情况下,Generator 的方法将返回适当的 Err(WirdigenError)。为了避免这些问题,最好首先进行验证,然后生成LUA dissector。

Generator 对象还有一个 from_value 方法,以便重用验证任务中的serde-json Value

fn foo() -> Result<(), WirdigenError> {
    // Open the JSON file
    let file_path = "./example/example_dissector.json";
    let file = File::open(file_path)?;
    let rdr = BufReader::new(file);

    // Create serde JSON value from the file
    let value: Value = serde_json::from_reader(rdr)?;

    // Create Validator object
    let val = Validator::new()?;

    // Call to validation method
    if val.validate(&value) {
        // Create Generator object
        let gen = Generator::default();

        // Generate plugin from validated data
        let generated_file_path: String = gen.from_value(value)?;
        println!("{}", generated_file_path);
    }
    else {
        println!("Invalid user input: {}", file_path);
    }
    
    Ok(())
}

默认情况下,插件是在环境变量中定义的临时文件夹中生成的。用户可以通过 set_output_directory() 方法修改输出目录,并通过 get_output_directory() 方法检索当前目录。

fn foo {
    let mut gen = Generator::default();

    println!("{}", gen.get_output_directory());

    let new_output = "/Documents/MyDissectors";
    gen.set_output_directory(new_output);

    println!("{}", gen.get_output_directory());
}

注意: 方法 set_output_directory 不会根据用户输入创建不存在的目录。如果输出目录不可达,则在尝试创建最终LUA文件时,生成方法将传播错误。

Dissector格式

JSON dissector描述由4个元素组成

  • 名称
  • Endianness
  • 连接
  • 数据

名称

name 元素是一个字符串(最大长度:32),表示要分析的协议名称,该名称将在 Wireshark 中("协议"列)用于识别您的数据包。

注意: 此名称也用于生成的 LUA 文件。例如,如果属性是 MY_PROTO,则生成的插件将被命名为 dissector_MY_PROTO.lua

字节序

定义协议使用的字节序的字符串。可能的值是 littlebig

连接

connection 对象包含 2 个字段

  • protocol:字符串。可以是 udptcp
  • ports:需要监视的端口号数组(介于 1 和 65535 之间)。

数据

data 是一个对象数组,用于描述数据包。每个对象定义了我们想要识别的数据包的一部分。

每个块包含以下属性

  • name:字符串(最大长度:32)。
  • format:表示块数据类型的字符串。有关可用值,请参阅下面的格式/基础矩阵。
  • base:表示值应如何显示的字符串。有关可用值,请参阅下面的格式/基础矩阵。
  • offset:从数据包开始的位置偏移量(以字节为单位)。
  • size:数据包内块的长度(以字节为单位)。
  • valstr(可选): 值/字符串对象数组,用于在有效负载中识别特定值。有关更多信息,请参阅下文。

关于 strval

此属性可用于通过其字符串表示形式识别和替换特定值(最大长度:32)。例如,当处理网页状态码时,在 Wireshark 捕获视图中查看状态码 404 作为 "NOT FOUND"200 作为 "OK" 可能很有用。此示例可以描述如下 dissector JSON 文件中

{
    ..., // First part of data chunk description
    "valstr" : [
        { "value": 404, "string": "NOT FOUND" },
        { "value": 200, "string": "OK"}
    ]
}

格式/基础兼容性矩阵

这些矩阵显示 Wirdigen 支持哪些格式/基础组合。

数字

格式 \ 基础 NONE DEC OCT HEX DEC_HEX HEX_DEC
bool X
char X X
uint8 X X X X X
uint16 X X X X X
uint24 X X X X X
uint32 X X X X X
uint64 X X X X X
int8 X
int16 X
int24 X
int32 X
int64 X
float(*) X X X X X X
double(*) X X X X X X

(*) = 对于指定的 format,Wireshark 会忽略 base

时间

格式 \ 基础 LOCAL UTC DOY_UTC
absolute_time X X X
relative_time(*) X X X

(*) = 对于指定的 format,Wireshark 会忽略 base

原始

格式 \ 基础 NONE DOT DASH COLON SPACE
byte X X X X X

特定

对于这些特定类型的数据,显示将由 Wirehsark 自动处理。因此,在这种情况下建议使用 NONE

  • none
  • ipv4
  • ipv6
  • ether
  • guid
  • oid

将解复用器导入 Wireshark

首先,您需要检查 Wireshark 在哪个目录中查找 LUA 插件。

为此,请打开 Wireshark 并转到 帮助 -> 关于 Wireshark -> 文件夹

找到与 "个人 Lua 插件" 相关的路径。这是您需要复制解复用器的位置。如果您的机器上不存在该路径,您可以手动创建缺失的目录。

解包脚本将在Wireshark刷新后生效。您可以重新启动Wireshark或按Ctrl + Shift + L重新加载所有Lua脚本。

注意:每次修改解包脚本时,都需要重新加载/重启。

路线图

  • 缺少数据类型

    • framenum
    • 字符串
    • 字符串z
    • ubytes
    • 协议
    • rel_oid
    • systemid
    • eui64
  • 支持子树,以便清晰地描述更复杂的数据包。

相关工具

依赖项

~10–19MB
~276K SLoC