DoubleBlak [CurrentPowerLog & the Monotonic Clock]
CurrentPowerLog与单调时钟
Apple电源日志时间戳一直是个容易混淆的点,这很容易理解。我承认几年前在尝试验证电源日志记录时也陷入了同样的困惑。当时,从CurrentPowerLog.PLSQL数据库中提取的一个设备事件对我的案件很重要,我试图验证所显示的时间。我像往常一样去查看源数据库,但我感兴趣的时间戳却无处可寻。
2022年,我的朋友兼前同事Mike Williamson与Sab Strong制作了一个关于"单调时间戳"的视频,我推荐观看(https://youtu.be/PwzKq1K0bkM?si=NdnmLBBva-Quqaln)。
但三年后,这仍然造成混淆,所以我也尝试一下,看看是否能提供一些额外的清晰度、理解或信息。
技术细节
iOS有一系列与设备电源活动相关的数据库。这些数据库记录诸如电池电量、使用情况、按键操作、电源循环、电池状态等信息。
所有这些数据库都始于一个名为CurrentPowerLog.PLSQL的数据库,这是当前正在使用的文件。几天后,该文件被压缩并以其包含数据的日期相关的新名称保存。例如:powerlog_2024-12-08_15DAA1E8.PLSQL.gz
PowerLog数据库的独特之处在于它们以不同于iOS设备上其他所有数据库的方式记录日期时间信息。
与健康、位置、消息和通话等相关的数据库都使用相同的系统时钟。虽然它们可能以不同的方式记录数据,例如自2001年1月1日起的秒数或纳秒数,但这根本上源于同一个时钟,也就是屏幕上显示给用户的相同时间。这意味着所有活动都可以按顺序排列,即使时间设置不正确。
然而,PowerLog数据库使用所谓的"单调时钟"。这本质上是一个以恒定速率向前推进的计数器,不受用户活动(如手动调整时间)或系统活动(如应用夏令时偏移)引起的时间变化的影响。
完全断电/电池耗尽等中断可能导致单调时钟以意外方式运行,影响计数器,因为计数器功能依赖于足够的电源(或电池电量)才能按预期工作。
想象一下你购买的一个普通数字时钟。当它是全新的时候,你设置适当的时间。但逐渐地,那个时钟上的时间开始漂移。一年后,那个时钟可能不再显示正确时间,需要你重新设置。这基本上就是单调时钟发生的情况,iOS不断根据网络时间进行同步。
数据工作原理示例
这是CurrentPowerLog.PLSQL的PLBATTERYAGENT_EVENTBACKWARD_BATTERY表的部分记录:
“timestamp"字段看起来像是UNIX时间戳(自1970年1月1日午夜起的秒数),可以通过将1724473913.3173292秒加到1970年1月1日午夜来转换为人类可读日期。这等于2024年8月24日04:31:53(UTC)。
此日期在Magnet的Axiom工具中显示,并标记为"单调日期/时间”,但该记录还附带另外两个时间戳,它们不是PLBATTERYAGENT_EVENTBACKWARD_BATTERY表的一部分。这些显示为"基带日期/时间"和"显示日期/时间",并在下图中以红色突出显示。
如该记录的"位置"部分(以绿色突出显示)所示,正在使用另一个表来填充数据。这是PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表。
要理解PLBATTERYAGENT_EVENTBACKWARD_BATTERY表中的时间戳值,需要根据PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表中的值进行偏移。
PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表包含5个字段:ID、timestamp、baseband、kernel和system。
这些记录可以描述为"检查点",系统根据单调时钟记录时间,以及单调时钟与基带和系统时钟等其他来源时间之间的差值。
Axiom引用的偏移记录是记录70,如下所示:
这里的"timestamp"字段是"检查点"时单调时钟的值,除了帮助确定计算下一步需要哪个偏移记录外,不用于其他用途。
来自PLBATTERYAGENT_EVENTBACKWARD_BATTERY表的时间戳值需要通过加上PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表中的基带和系统字段值来进行偏移。
| 记录值 | 来自电池表 | 偏移 | 来自偏移表 | 总和(记录+偏移) | 日期时间(UTC) |
|---|---|---|---|---|---|
| 单调 | 1724473913.3173292 | - | - | 2024年8月24日04:31:53 | |
| 基带 | 1724473913.3173292 | 926987.1864346266 | 1725400900.5037638 | 2024年9月3日22:01:40 | |
| 系统 | 1724473913.3173292 | 926986.9725067616 | 1725400900.289836 | 2024年9月3日22:01:40 |
这些值可以看到与Axiom提供的时间戳相同。
测试1
当测试设备显示正确时间/日期时,手电筒在2024年12月28日09:56:00准时使用了30秒。
这导致在CurrentPowerLog的PLCAMERAAGENT_EVENTFORWARD_TORCH表中创建了2条记录,时间戳为1734095910.699675和1734095940.9988012。
当作为UNIX时间戳处理时,这些值等于2024年12月13日的时间,比手电筒活动实际发生时间早了几周。
PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表也更新了一条新记录,显示:
偏移记录的选择基于感兴趣表(本例中为PLCAMERAAGENT_EVENTFORWARD_TORCH表)中的"timestamp"字段与PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET表中的timestamp字段之间的比较。
根据我的测试,偏移表中的选定时间戳应尽可能接近正在调查的记录,而不应更高(如果可能)。
例如,上面的屏幕截图显示了偏移表中的单个记录。但偏移表实际上包含更多记录,例如:
偏移表中的每条记录都需要与TORCH表中感兴趣的时间戳进行比较。这涉及确定两个时间戳中哪个值更高。最高值以绿色突出显示。
| 时间戳 | Torch表 | ID | 时间戳偏移表 | 差值 |
|---|---|---|---|---|
| 1734095910.699675 | 868 | 1734038057.364263 | TORCH比OFFSET晚57853.335412 | |
| 1734095910.699675 | 869 | 1734059715.028399 | TORCH比OFFSET晚36195.671276 | |
| 1734095910.699675 | 870 | 1734060316.651987 | TORCH比OFFSET晚35594.047688 | |
| 1734095910.699675 | 871 | 1734080544.3651023 | TORCH比OFFSET晚15366.3345727 | |
| 1734095910.699675 | 872 | 1734097162.374874 | TORCH比OFFSET早1251.67519 |
在这种情况下,最接近但不超出的值是记录ID 871。因此,使用的偏移值是第871行系统字段的值,如下所示。
如上所述,将TORCH时间戳和系统偏移值相加。 Torch.Timestamp + Offset.System = 时间戳 1734095910.699675 + 1309054.919729948 = 1735404965.3135737541 = 2024年12月28日09:56:05(UTC-7:00) 1734095940.9988012 + 1309054.919729948 = 1735404995.6126999541 = 2024年12月28日09:56:35(UTC-7:00)
这意味着我们得到: 手电筒开启于2024年12月28日09:56:05(UTC-7:00) 手电筒关闭于2024年12月28日09:56:35(UTC-7:00)
这些结果与手电筒事件的实际时间相差在5秒内。请注意,这5秒的差异每次使用手电筒时都会出现,但在我见过的其他项目(如按键)上不存在。
测试2
然后将设备日期和时间设置手动设置为2024年11月28日上午6点(UTC-7)。
当设备显示06:19:00时,再次使用手电筒30秒。
请注意,正确时间是2024年12月28日10:36:05。这意味着第二次测试发生在第一次测试后40分钟5秒(您可能记得第一次测试是在09:56:00进行的)。
此测试导致2条记录按预期写入数据库。
当作为UNIX时间戳处理时,值显示:
尽管设备上的时钟被设置回一个多月,但此处显示的值仍然显示2024年12月13日。
与设备显示正确时间时创建的先前记录相比,可以看到记录之间有约40分钟的差异,这是测试进行时的实际时间差。
偏移表中出现了一些新记录,最值得注意的是一个具有负值的记录。
再次应用上述逻辑: 1734098314.841299 + -1298370.4157130718 = 1732799944.4255859282 = 2024年11月28日06:19:04(UTC-7:00) 1734098346.215589 + -1298370.4157130718 = 1732799975.7998759282 = 2024年11月28日06:19:35(UTC-7:00)
再次执行此计算得到的时间戳可以看到与使用手电筒时设备上显示的时间相差在几秒内。
总结
CurrentPowerLog表中提供的"timestamp"值不应混淆为实际时间戳,需要根据数据库中的其他值进行偏移以计算事件的实际时间。
取证工具应考虑这种差异,Axiom采取了额外步骤在其工具中提供3个时间戳,但这仅应用于辅助验证,并不意味着所有3个时间戳都具有任何相关性。