iOS 检测模拟位置

iOS detect mock locations

目前我正在开发一款应用程序,其中地理定位功能是其最重要的功能。实际上,我们非常关心模拟 GPS 值。我在 iOS 和 Android 上阅读了很多关于模拟位置的评论,其中大多数倾向于解释未越狱的 iOS 设备无法模拟位置,但事实是我我创建了另一个项目,使用 GPX 文件模拟该项目的位置,当执行时,整个系统认为我在另一个城市。我所有的 locationManager 回调都告诉我,我正处于具有正确时间戳的模拟位置,伪造整个信息就像它是真实的一样。这完全违背了我们应用程序的目的,因为用户可以在去过的地方伪造。

有什么方法可以检测并防止这种行为吗?我假设一个封闭的目标,攻击者必须是开发人员才能使这个漏洞发挥作用,但唉,它仍然存在

我认为不可能检测到位置模拟器。

伪装位置的更简单方法是使用外部蓝牙或串行连接到 GPS simulator that outputs NMEA sentences。尽管您确实需要 Android phone 到 运行 模拟器,但您不需要开发者帐户。

iPhone 将自动检测外部 GPS,CLLocationManager 将使用外部 GPS 源代替自己的内部 GPS。这对于地图和导航应用程序的实验室测试非常方便。

问题:有什么方法可以检测并防止这种行为?

实际上有 2 个不同的问题:(1) 如何检测,以及 (2) 如何预防?

(1) 的答案:模拟位置行为与回调时的真实位置行为完全不同 locationManager:didUpdateLocations:

[模拟位置] 回调 returns 几乎在调用 startUpdatingLocation 之后立即执行,然后每隔一秒重复调用一次。如果我们选择固定位置,位置也都是相同的。这是一个例子:

location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:48 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:49 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:50 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:51 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:52 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:53 Час: Індокитай
location: <+51.50998000,-0.13370000> +/- 5.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:12:54 Час: Індокитай

[real locations] 回拨需要几秒(如果先运行),然后随机重拨。即使您根本不移动,您也可以看到这些位置之间发生重大变化的时间。这是一个例子:

location: <+10.77219361,+106.70597441> +/- 67.39m (speed -1.00 mps / course -1.00) @ 30.03.15 14:16:26 Час: Індокитай
location: <+10.77213011,+106.70591088> +/- 65.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:16:31 Час: Індокитай
location: <+10.77219507,+106.70587790> +/- 65.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:16:38 Час: Індокитай
location: <+10.77214753,+106.70587741> +/- 65.00m (speed -1.00 mps / course -1.00) @ 30.03.15 14:16:49 Час: Індокитай

(2) 的答案:为了防止,我现在只是临时解决,我们需要查找至少 3 个位置来确定它是模拟位置还是真实位置。

提醒一下,这只是检测模拟位置的临时解决方案。将来,Apple 可能会改变这种行为。

顺便说一下,我还尝试在方案中禁止在 xCode 上模拟位置: 不幸的是,它仍然允许模拟位置。

您可能知道的更多问题here。 希望对你有帮助。

为了详细说明@KennyHo 的回答,我发现真实位置反馈和模拟位置反馈之间还有另一个区别。

一个模拟位置,正如我注意到的,总是returns这些位置的值组合properties/options:

horizontalAccuracy: 5
verticalAccuracy: -1
altitude: 0.000000
speed: -1

真实位置 会在 99% 的情况下给出不同的组合,例如

horizontalAccuracy: 5
verticalAccuracy: 10
altitude: +/- 0.4243232
speed: -1

请注意,模拟位置的组合可能与上述组合不同,但前提是用户使用 xcode Automation target test。但是,用户只能将位置模拟到具有开发身份的已签名应用程序(必须拥有该应用程序)。这意味着除了您之外,没有人可以伪造具有不同 altitudeverticalAccuracy 的位置来在 xcode.

中欺骗您的应用程序

也可以使用 software-defined 收音机和 GitHub 的 gps-sdr-sim 来欺骗 iPhone。 您使用 gps-sdr-sim 生成包含 GPS 信号的 I/Q 文件,并使用 SDR 传输这些样本 over-the-air。 这种欺骗更难检测。

自 iOS15 以来,苹果在 CLLocation 中引入了两个新特性:

    /*
     * isSimulatedBySoftware
     *
     * Discussion:
     *  Set to YES if this location was detected as being generated by a software simulator, such as Xcode
     */
    open var isSimulatedBySoftware: Bool { get }

    
    /*
     * isProducedByAccessory
     *
     * Discussion:
     *  Set to YES if this location was generated from an external accessory, such as CarPlay or an MFi accessory
     */
    open var isProducedByAccessory: Bool { get }

这两个属性位于:

/*
 *  sourceInformation
 *
 *  Discussion:
 *    Contains information about the source of this location.
 */
@available(iOS 15.0, *)
open var sourceInformation: CLLocationSourceInformation? { get }

我已经使用第三方应用程序等虚拟位置生成器对此进行了测试,xcode 和 isSimulatedBySoftware 在所有情况下都是正确的。我会订购一个外部 GPS 设备以确保另一个也能正常工作(希望 :D)然后会更新我的答案。