Lua wireshark 解析器以 OLE 自动化格式提取时间戳

Lua wireshark dissector extract timestamp in OLE automation format

参考:

我正在 LUA 中编写一个简单的 UDP 解析器来解码包含被编码为 OLE 自动化日期的时间戳的数据包。编码结果为 8 字节数据模式:

C2 F5 4F 12 FD 6B E5 40     

解码为 43871.90848539352 = '2/10/2020 9:48:13 PM'。在 C# .NET 中,这是通过 DateTime.ToOADate() 方法(工作正常)。

这是我的简化解析器,其中 'decodes' 仅包含时间戳的 8 字节消息:

local logger_proto = Proto("logger", "LOGGER")
local logger_hdr={
    atime = ProtoField.absolute_time("test.atime","test atime",base.UTC),
    rtime = ProtoField.relative_time("test.rtime","test rtime",base.UTC),
}
logger_proto.fields=logger_hdr

function logger_proto.init() end

function logger_proto.dissector(tvbuf, pktinfo, root)
    root:add(logger_hdr.atime,tvbuf:range(0,8))
    root:add(logger_hdr.atime,tvbuf:range(8,8))
end

在测试数据包中,我发送了两次时间戳,第二次是使用相反顺序的字节来测试字节序问题('grasping at straws' 方法)。数据包数据为:

C2 F5 4F 12 FD 6B E5 40 40 E5 6B FD 12 4F F5 C2 

检索到的两个时间戳是

Aug 25, 2073 03:14:26.-4360608 UTC
Jul  2, 2004 14:06:53.307230146 UTC

'correct' 时间戳应该是

Feb 10, 2020 21:48:13 UTC

看起来 ProtoField.absolute_time 和 base.UTC 并不是我想要的。所以我的问题是

  1. 是否有 ProtoField 选项可以以排除小数秒的格式正确提取此时间戳?
  2. 如果不是,我将如何按字节提取 date/time 并进行计算以手动格式化正确的日期?

我不得不学习一些关于 OLE 日期的知识,但在 DateTime.ToOADate Method. I also used information from the question as well as from Convert us-timestamp to absolute_time 找到了相关信息,为您提出了一个 可能的 解决方案。我怀疑它是否是最佳选择,但根据提供的数据,它 似乎 有效。希望它对你有用,但如果没有,它应该会让你更接近解决方案。

如果 Wireshark 可以提供对 OLE 日期的 本地 支持,那么一个长期的解决方案是,为了实现这一点,我建议提交 Wireshark 增强 bug report 请求这样的东西。

一个可能的解决方案(有一些额外的东西用于说明目的):

local p_logger = Proto("logger", "LOGGER")
local logger_hdr = {
    -- Only the oletime_abs field is useful; the rest just help illustrate things
    -- and helped me during debugging.  Remove/rename as you see fit.

    oletime = ProtoField.double("logger.oletime", "OLE time"),

    -- Note: .int64 doesn't work so just using .int32
    oletime_days = ProtoField.int32("logger.oletime.days", "Days"),
    oletime_partial = ProtoField.double("logger.oletime.partial", "Partial"),
    oletime_abs = ProtoField.absolute_time("logger.oleabstime", "OLE Abs time", base.UTC)
}
p_logger.fields = logger_hdr

function p_logger.dissector(tvbuf, pinfo, tree)
    local logger_tree = tree:add(p_logger, tvbuf(0,-1))
    local OLE_DIFF_TO_UNIX = 25569
    local SECS_PER_DAY = 86400
    local oletime = tvbuf:range(0, 8):le_float() - OLE_DIFF_TO_UNIX
    local oletime_days = math.floor(oletime)
    local oletime_partial = (oletime - oletime_days) * SECS_PER_DAY
    local secs = oletime_days * SECS_PER_DAY + math.floor(oletime_partial)
    local nstime = NSTime.new(secs, 0)

    pinfo.cols.protocol:set("LOGGER")
    logger_tree:add(logger_hdr.oletime, tvbuf:range(0, 8), oletime)
    logger_tree:add(logger_hdr.oletime_days, tvbuf:range(0, 8), oletime_days)
    logger_tree:add(logger_hdr.oletime_partial, tvbuf:range(0, 8), oletime_partial)
    logger_tree:add(logger_hdr.oletime_abs, tvbuf:range(0, 8), nstime)
end

-- Register dissector (this particular registration is just for my testing)
local udp_table = DissectorTable.get("udp.port")
udp_table:add(33333, p_logger)

我确定这可以被清理 up/optimized,但我将其作为练习留给 reader。使用以下手工制作的数据包进行测试:

0000   00 0e b6 00 00 02 00 0e b6 00 00 01 08 00 45 00   ..............E.
0010   00 37 00 00 40 00 40 11 b5 ea c0 00 02 65 c0 00   .7..@.@......e..
0020   02 66 82 35 82 35 00 23 e8 54 c2 f5 4f 12 fd 6b   .f.5.5.#.T..O..k
0030   e5 40 40 e5 6b fd 12 4f f5 c2 00 00 00 00 00 00   .@@.k..O........
0040   00 00 00 00 00                                    .....

... 你应该得到 "Logger" OLE 日期的以下解码:

LOGGER
    OLE time: 18302.9084853935
    Days: 18302
    Partial: 78493.1380001362
    OLE Abs time: Feb 10, 2020 21:48:13.000000000 UTC

您可以使用text2pcap将其转换为pcap文件进行测试。例如:text2pcap -a logger.txt logger.pcap ... 其中 logger.txt 是包含上面粘贴的原始数据包字节的文本文件。