这是什么时间结构?

逆向工程 数字取证 二进制格式
2021-06-13 21:27:52

我有一个现有的软件,没有源代码和可能的编辑。它包含一个网格(看起来像一个旧的 DevExpress,软件本身是在 Delphi 7 中创建的)。网格内容存储在内存中,我必须在外部读取和修改。

我已经成功解码了结构,除了日期+时间字段。它存储在 8 个字节中。我检查了所有常见的结构,例如TDateTime双变量、TTimeStamp两个整数TFileTime、Windows OLE、MySQL 时间戳、其他时间戳,但没有发现任何密切相关的结构。

我可以输入任何数据并检查表中的结果,所以我确定数据是正确的。

我已经提供了以字节为单位的数据时间和网格中的结果的示例。如果有帮助,可以测试任何其他。

00 00 00 00 00 00 00 43 - 04.03.17840 11:03:41
00 00 00 00 00 00 00 41 - "0.131072 is not a valid timestamp"
00 00 00 00 00 00 00 42 - 09.04.001 10:05:34
00 00 00 00 00 00 67 42 - 15.01.0026 16:33:02
00 00 00 00 00 00 CB 42 - 22.06.1882 18:24:59
00 00 00 00 00 00 CC 42 - 28.02.1952 10:12:35
00 00 00 00 00 E4 CC 42 - 22.03.2014 07:24:02
00 00 00 00 00 E5 CC 42 - 29.06.2014 17:29:37
00 00 00 00 3D E5 CC 42 - 23.07.2014 10:03:17
00 95 1E 7E 3D E5 CC 42 - 23.07.2014 14:38:48
00 87 F9 7C 3D E5 CC 42 - 23.07.2014 14:36:18
00 4C 99 57 38 E5 CC 42 - 21.07.2014 14:38:26
80 55 0C 2E 3E E4 CC 42 - 15.04.2014 10:57:32

更新 1:评论中提到的年份的奇怪差异导致发现,该日期与旧字节并不严格线性。我已经测试过这个:

00 00 00 00   00 00 CA 42 - 16.10.1812
00 00 00 00   00 00 CB 42 - 22.06.1882
00 00 00 00   00 00 CC 42 - 28.02.1952

值之间的差异是 ~70 年(~25452 天)

现在这个:

00 00 00 00   00 00 BA 42 - 23.11.0906
00 00 00 00   00 00 BB 42 - 26.09.0941
00 00 00 00   00 00 BC 42 - 30.07.0976

差异实际上是 ~35 年(~12726 天)

总结一下,这里是细分:

00 00 00 00   00 00 BD 42 - 04.06.1011
00 00 00 00   00 00 BE 42 - 06.04.1046 (+35 years)
00 00 00 00   00 00 BF 42 - 07.02.1081 (+35 years)
...
00 00 00 00   00 00 C0 42 - 13.12.1115 (+35 years)
00 00 00 00   00 00 C1 42 - 19.08.1185 (+70 years)
00 00 00 00   00 00 C2 42 - 25.04.1255 (+70 years)
...
00 00 00 00   00 00 C8 42 - 02.06.1673 (+70 years)
00 00 00 00   00 00 C9 42 - 08.02.1743 (+70 years)
00 00 00 00   00 00 CA 42 - 16.10.1812 (+70 years)
...
00 00 00 00   00 00 CE 42 - 11.07.2091 (+70 years)
00 00 00 00   00 00 CF 42 - 18.03.2161 (+70 years)
...
00 00 00 00   00 00 D0 42 - 24.11.2230 (+70 years)
00 00 00 00   00 00 D1 42 - 07.04.2370 (+140 years)
00 00 00 00   00 00 D2 42 - 19.08.2509 (+140 years)

所以看起来老位是一些系数,而不是直接的日期

我测试了较少的部分,它们的行为似乎更合乎逻辑:

00 00 00 00   00 00 CC 42 - 28.02.1952
00 00 00 00   00 01 CC 42 - 06.06.1952
00 00 00 00   00 02 CC 42 - 14.09.1952

~100 天

00 00 00 00   00 CC CC 42 - 09.09.2007
00 00 00 00   00 CD CC 42 - 17.12.2007
00 00 00 00   00 CE CC 42 - 26.03.2008

~100 天

00 00 00 00   00 FC CC 42 - 02.10.2020
00 00 00 00   00 FD CC 42 - 09.01.2021
00 00 00 00   00 FE CC 42 - 19.04.2021

~100 天

对于第四个字节:

00 00 00 00   00 CC CC 42 - 09.09.2007 05:10:12
00 00 00 00   01 CC CC 42 - 09.09.2007 14:29:26
00 00 00 00   02 CC CC 42 - 09.09.2007 23:48:26

~9 小时

00 00 00 00   CC CC CC 42 - 27.11.2007 10:35:16
00 00 00 00   CD CC CC 42 - 27.11.2007 19:54:30
00 00 00 00   CE CC CC 42 - 28.11.2007 05:13:45

~9 小时

对于+1m、+1h等细分的问题,测试起来要困难得多,因为我无法输入随机日期并获取其代码,只能相反。但我可以手动添加该值,并测试其内部结构。这是我今天设法抓住的:

00 90 D2 80   4A E5 CC 42 - 28.07.2014 15:54:50
00 E3 D4 80   4A E5 CC 42 - 28.07.2014 15:54:51

80 5D 48 81   4A E5 CC 42 - 28.07.2014 15:55:50
80 5A 4B 81   4A E5 CC 42 - 28.07.2014 15:55:51

80 D4 49 9C   4A E5 CC 42 - 28.07.2014 16:54:50
00 8C 4C 9C   4A E5 CC 42 - 28.07.2014 16:54:51
2个回答

非线性是一种浮点编码的线索。如果您熟悉查看内存转储中的浮点值,那么最重要的字节通常在0x3f-0x4f范围内,代表双精度值从3e-5到 的2e77在这种情况下,它是小端的。

例如00 4C 99 57 38 E5 CC 42 - 21.07.2014 14:38:26-> 解压到 ->63541636706968.0

从另一个方向工作,让我们检查该日期的标准编码。UNIX time_t(自 1970 纪元以来的秒数)= 1405949906.

这太小了四个数量级。不好; 也许我们可以尝试自公元 1 年以来的秒数。365.2425现在假设每年的天数,并记住从 1 开始的日、月和年编号:

(21-1 + 181 days before July + (2014-1AD)*365.2425)*86400 sec/day + 14*3600 + 38*60 + 26 = 63541563483.0
63541563483.0 * 1000 = 63541563483000.0

这与解码后的数字相似,但相差约 1000 倍;编码值必须以毫秒为单位。预测不准确,我们将关闭大约 1 天。我们仍然应该测试它是否继续适用于其他值。

00 00 00 00 00 00 CB 42 - 22.06.1882 18:24:59
decoding: 59373627899904.0
prediction: 59373553811000.0

00 00 00 00 00 00 67 42 - 15.01.0026 16:33:02
decoding: 790273982464.0
prediction: 790192982000.0

关闭,但再次关闭大约 1 天。我们必须检查我们的假设。我们使用的带有闰年的公历系统只能追溯到 1582 年,但该系统在此之前有一个零点。我们必须猜测程序员做了什么将其向后扩展到 1AD。

您可以通过程序运行浮点零(全零)来找到零点;它应该显示程序员选择的确切日期时间来源。如果程序不接受零,您可以使用非常小的双精度值,如DBL_MIN. 您还必须准确检查程序如何处理闰日,是否正确考虑了 400 年规则以及任何实现错误。

不看前三个加号28.02.1952 10:12:35, 29.06.2014 17:29:37,15.04.2014 10:57:32行,我得到以下信息:

右侧的值以 1/128000 秒为单位,与 UNIX 时间戳的偏移量为 4805619185047532800 秒。所以,我们有:

yourtime =  4805619185047532800 +128000 * unixtime

不过它看起来并不熟悉,这意味着t=0-> 1187749 BC。

如果你离开,0x42 那么t=0将是 10363 BC,仍然不是一个熟悉的数字。