ref: OLE Automation date in lua
I'm writing a simple UDP dissector in LUA to decode packets that contain a timestamp that was encoded as an OLE automation date. The encoding results in an 8-byte data pattern:
C2 F5 4F 12 FD 6B E5 40
which decodes as 43871.90848539352 = '2/10/2020 9:48:13 PM'. In C# .NET this is via the DateTime.ToOADate() method (which works fine).
Here is my simplified dissector, which 'decodes' an 8-byte message that consists only of the timestamp:
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
In the test packet I send the timestamp twice, the second time is with the bytes in reverse order to test for endian issues (the 'grasping at straws' approach). The packet data is:
C2 F5 4F 12 FD 6B E5 40 40 E5 6B FD 12 4F F5 C2
the two retrieved timestamps are
Aug 25, 2073 03:14:26.-4360608 UTC
Jul 2, 2004 14:06:53.307230146 UTC
the 'correct' timestamp should be
Feb 10, 2020 21:48:13 UTC
It looks like ProtoField.absolute_time with base.UTC is not quite what I am looking for. So my questions are
I had to learn a bit about OLE dates but found relevant information at DateTime.ToOADate Method. I also used information from the OLE Automation date in lua question as well as from Convert us-timestamp to absolute_time to come up with a possible solution for you. I doubt it's an optimal one, but it seems to work based on the data provided. Hopefully it works for you but if not, it should get you closer to a solution.
A long-term solution would be if Wireshark could supply native support for OLE dates, and for that to happen, I'd recommend filing a Wireshark enhancement bug report requesting just such a thing.
A possible solution (with some extra stuff for illustrative purposes):
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)
I'm sure this can be cleaned up/optimized, but I leave that as an exercise to the reader. Tested with the following hand-crafted packet:
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 .....
... and you should get the following decode of the "Logger" OLE date:
LOGGER OLE time: 18302.9084853935 Days: 18302 Partial: 78493.1380001362 OLE Abs time: Feb 10, 2020 21:48:13.000000000 UTC
You can use text2pcap
to convert it to a pcap file for testing. For example: text2pcap -a logger.txt logger.pcap
... where logger.txt
is a text file containing the raw packet bytes pasted above.