Apple

最近在网上沸腾的 iOS 时间 bug 闹的沸沸扬扬,据说是将 iOS 系统时间修改为 1970/1/1,重启后系统将永远无法开机。那么这个事情是真的吗?如果是真的有什么合理的解释吗?

想要真正了解这一 bug,您可能需要以下知识。

UNIX 时间戳

在确认这件事情的真假前,你需要了解的一个知识是 Unix 时间戳。

iOS 系统时间使用 Unix 时间戳(Unix epoch)表示(time_t数据类型)。在系统中,使用系统位数个二进制位储存时间。

Unix 时间戳规定,UTC 时区的 1970 年 1 月 1 日 0 点 0 时 0 秒的值为0,以秒为单位,即每过一秒,二进制数字加1。

不能往前调,那我把时间往后调

有些好奇的朋友拿出了自己手机,心想:既然我不能往回调,那我要是把时间使劲往后调能怎样?

细心的朋友发现了一个问题,iOS 系统可以设置的最大时间是 2038 年 1 月 1 日,并不能再往后设置。苹果一定考虑到了这个问题,为什么这么说呢?

我们拿 32 位系统举例。在 32 位系统中,time_t是长度为 32 位的,有符号整数(signed int)类型。首个二进制位是符号位,用来储存正负。正数则为 1970/1/1 以后的时间,负数反之;其余的 31 位用来记数。当时间到达 2038 年 1 月 19 日 3 时 14 分 08 秒时,数值位全部向前进1,导致符号位被置1,其余 31 位为0。介时,将出现『时间回归』的情况,系统时间变为 1901 年 12 月 13 日 20 时 45 分 52 秒,系统将会出现错误。

所以 Apple 为了避免这种问题导致的错误发生,将最大时间期限定在了 2038 年 1 月 1 日 23 时 59 分 59 秒。这样即使超出这个范围,在 18 天内也不会有太大问题,况且 32 位设备到那个时候基本都已经淘汰了。

64 位系统会不会受到这个影响呢?通过计算我们可以得到,292,277,026,596 年 12 月 04 日 15 时 30 分 08 秒是 64 位系统可以表示的最大时间。

如果你想了解更多关于 32 位系统在 2038 将出现的问题,请移步: Year 2038 problem。

64 位处理器的『时间回归』问题

有了刚才的知识储备,现在我们回到正题,开始探讨搭载 64 位处理器设备的时间 bug。

我们说到了以 UTC 时区的 1970 年 1 月 1 日 0 点 0 时 0 秒为界限,数值为0,时间正常流逝为正数,反之为负数。不过各位需要留意的是,时间受到时区的影响。

假设一种情况,我原来是北京时区,假设将时间设置到了 1970 年 1 月 1 日 0 点 0 时 0 秒,那么我将这个时间转换为 UTC 时间,公式:北京时间 = GMT+8 = UTC+8,那么 UTC 时间则为 1969 年 12 月 31 日 16 时 0 分 0 秒。这样就会出现时间负值,即时间回归 bug 触发,系统启动卡在 Kernel 阶段,时间错误,无法继续进行启动。

触发 bug 条件与表现

满足以下条件,『时间回归』bug 被触发:

系统版本:iOS 8.0 ~ iOS 9.3 beta 3

硬件设备:搭载64 位处理器的设备(即处理器为A7~A9X的设备)

进入『设置』-『通用』-『时间与日期』,关闭『自动设置』,并将时间修改为 1970 年 1 月 1 日,分秒任意。

修改时间后,需要重启设备

Bug 触发表现:iOS 设备启动时,卡在苹果 Logo,无法继续启动。

Bug 危害分析

黑客可以利用此 bug 通过无线局域网发出范围性攻击。

当 iOS 设备连接到公共网络时,iOS 系统将会使用 NTP 服务对时区、时间进行校准。如果黑客发送恶意的 NTP 攻击,将 iOS 系统时间校准至 UTC < 0 的时间,那么所有用户设备均会受到此 bug 影响,在重新启动设备后无法使用设备。