1

参考:lua 中的 OLE 自动化日期

我正在 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() 方法(工作正常)。

这是我的简化解析器,它“解码”一条仅包含时间戳的 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

在测试数据包中,我发送了两次时间戳,第二次是字节顺序相反以测试字节序问题(“抓住稻草”方法)。数据包数据为:

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

“正确”的时间戳应该是

Feb 10, 2020 21:48:13 UTC

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

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

1 回答 1

2

我必须了解一些有关 OLE 日期的知识,但在DateTime.ToOADate Method找到了相关信息。我还使用了 lua question 中的 OLE 自动化日期以及将 us-timestamp 转换为 absolute_time的信息来为您提供可能的解决方案。我怀疑这是一个最佳方案,但它似乎根据提供的数据起作用。希望它对您有用,但如果不是,它应该让您更接近解决方案。

如果 Wireshark 可以提供对 OLE 日期的本机支持,一个长期的解决方案是,为此,我建议提交一份 Wireshark 增强错误报告来请求这样的事情。

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

本地 p_logger = Proto("logger", "LOGGER")
本地 logger_hdr = {
    -- 只有oletime_abs 字段有用;其余的只是帮助说明事情
    - 并在调试过程中帮助了我。根据需要删除/重命名。

    oletime = ProtoField.double("logger.oletime", "OLE 时间"),

    -- 注意:.int64 不起作用,所以只使用 .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

函数 p_logger.dissector(tvbuf,pinfo,树)
    本地 logger_tree = 树:add(p_logger, tvbuf(0,-1))
    本地 OLE_DIFF_TO_UNIX = 25569
    本地 SECS_PER_DAY = 86400
    本地 oletime = tvbuf:range(0, 8):le_float() - OLE_DIFF_TO_UNIX
    本地 oletime_days = math.floor(oletime)
    本地 oletime_partial = (oletime - oletime_days) * SECS_PER_DAY
    本地秒 = oletime_days * SECS_PER_DAY + math.floor(oletime_partial)
    本地 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)
结尾

-- 注册解析器(这个特殊的注册只是为了我的测试)
本地 udp_table = DissectorTable.get("udp.port")
udp_table:add(33333, p_logger)

我确信这可以清理/优化,但我将其作为练习留给读者。使用以下手工制作的数据包进行测试:

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 .....

...并且您应该获得“记录器” OLE 日期的以下解码:

记录器
    OLE时间:18302.9084853935
    天数:18302
    部分:78493.1380001362
    OLE Abs 时间:2020 年 2 月 10 日 21:48:13.000000000 UTC

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

于 2020-02-14T16:51:00.457 回答