我们的很多应用中都会使用到系统的定位功能,通过定位功能就可以知道手机当前所在的位置,进而获得当前所在的城市,进而进行一些特定的基于地理位置的推荐或者消息推送。还有一些应用会借助当前的位置进行考勤打卡处理。出行软件会借助定位进行线路选择和导航处理。因此基于定位的应用无处不在。而那些基于定位产生收益的应用更是严重依赖定位系统的正确性。
有收益就意味这有人会应用不正当的手段来获取不正当的利益。既然定位这么重要,那么如果能够模拟出当前的位置或者模拟出特定的位置,黑产人员就可以利用一些漏洞来获取不当的利益。如何打击黑产就成为应用安全和风控部门的重要任务。
在iOS中获取当前定位位置的框架叫CoreLocation.framework。我们可以通过CLLocation来得到一个经纬度坐标信息,具体如何获取的这里就不详细介绍了。CLLocation对象明面上所携带的信息只有经纬度、海拔、方向、速度、精确度等几个属性。
我们知道手机上定位数据的产生主要来源于手机和GPS卫星通讯产生的位置,或者手机和基站通信时根据基站和手机的距离算出当前的坐标位置,或者手机连接wifi时根据wifi站点和手机的距离算出当前的坐标位置,也就是每个坐标位置都应该有一个数据来源。 在Android系统中我们就很容易拿到坐标的源,但是在iOS系统中我们是无法拿到每个坐标的源的,至少公开层面是拿不到的。
目前黑产主要通过3个手段来实现坐标位置的模拟的:
-
在越狱设备中通过方法交换的形式来拦截CLLocationManager对象的delegate属性中的
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
实现来返回虚假的定位数据。 -
在未越狱的设备上通过电脑和手机进行USB连接,电脑通过特殊协议向手机上的DTSimulateLocation服务发送模拟的坐标数据来实现虚假定位,目前Xcode上内置位置模拟就是借助这个技术来实现的。
-
在未越狱的设备上通过符合MFI认证的蓝牙设备和手机连接,并通过MFI蓝牙设备向手机发送虚假的定位数据来实现定位模拟。比较有代表意义的就是市面上的:位置精灵app。
上面的3种方法中,前面越狱设备上的虚假定位数据还好检测,而后面两种基于非越狱的虚拟定位数据的模拟因为是系统层面的,所以我们的应用根本无法检测得到。
真的就这样无能为力,让黑产肆意的产生无法被发现的虚拟定位数据吗?当然不是。因为这些虚拟的定位数据并不是真实的定位源所产生的数据,如果我们能够找到每个定位坐标的来源,并发现这些虚假定位数据的特征,问题就迎刃而解了。其实所有的这些信息就藏在前面提到的CLLocation对象中。
在每个CLLocation对象中有一个内部的私有数据成员:_internal
这个内部的私有属性是一个内部类CLLocationInternal的实例。而这个内部类CLLocationInternal中有一个结构体CLLocationInfo指针数据成员:fLocation
。CLLocationInfo结构体定义如下:
struct CLLocationInfo {
#if defined(__i386__) || defined(__x86_64__)
int padding1;
#endif
int suitability; //定位的magic数
CLLocationCoordinate2D coordinate; //经纬度
CLLocationAccuracy horizontalAccuracy; //水平精确度
CLLocationDistance altitude; //海拔
CLLocationAccuracy verticalAccuracy; //垂直精确度
#if defined(__i386__) || defined(__x86_64__)
double padding2;
double padding3;
#endif
CLLocationSpeed speed; //速度
CLLocationAccuracy speedAccuracy; //速度精确度
CLLocationDirection course; //方向
CLLocationAccuracy courseAccuracy; //方向精确度
double timestamp; //时间戳
int confidence; //置信值?
double lifespan; //有效期限?
int type; //定位数据来源类型
CLLocationCoordinate2D rawCoordinate; //原始经纬度
CLLocationDirection rawCourse; //原始方向
int floor; //楼层
#if !defined(__i386__)
unsigned int integrity; //信息完整度? :75=High 50=Medium 25=Low 0=None
int referenceFrame; //参考坐标系:2=ChinaShifted 1=wgs84 0=unknown
int rawReferenceFrame; //原始参考坐标系
#endif
};
复制代码
可以在上述的结构体中看到很多隐藏的数据信息。CLLocation对象中的那些对外公开的属性其实都是通过读取这个结构体的成员数据来返回的。在上述的结构体中有一个很重要的数据成员type
。这个数据成员就是用来标明当前定位的数据是怎么产生的,也就是定位来源。具体的取值如下:
值 | 所表示的意义 | 备注 |
---|---|---|
0 | unknown | 应用程序生成的定位数据,一般在越狱设备下,通过虚拟定位程序来生成。 |
1 | gps | GPS生成的定位数据 |
2 | nmea | |
3 | accessory | 蓝牙等外部设备模拟定位生成的定位数据 |
4 | wifi | WIFI定位生成的数据 |
5 | skyhook | WIFI定位生成的数据 |
6 | cell | 手机基站定位生成的数据 |
7 | lac | LAC生成的定位数据 |
8 | mcc | |
9 | gpscoarse | |
10 | pipeline | |
11 | max |
上述表格的类型定义来源于苹果的定位服务locationd中
从上面的类型定义中可以看出:只要是我们手动创建的CLLocation对象其type值都是0。只要是通过蓝牙等外设生成的定位对象type值都是3。如果是系统正常生成的定位对象则type值通常为1或者4或者6三个值。当然我们不能单纯通过type类判定某个定位数据是否是虚拟定位数据,而是应该通过更多的特征值来判断。下面的表格分别列举出了:正常、手动或越狱拦截、DTSimulateLocation服务模拟、蓝牙设备模拟 一共四种情况下CLLocationInfo结构体中各成员的数据值:
结构体成员 | 中文描述 | 正常 | 手动或越狱拦截 | DTSimulateLocation服务模拟 | 蓝牙设备模拟 |
---|---|---|---|---|---|
suitability | magic数 | 65535 | 65535 | 65535 | 65535 |
coordinate | 经纬度 | 正常值 | 指定值 | 模拟值 | 模拟值 |
horizontalAccuracy | 水平精确度 | 正常值或-1 | 指定值或0 | 5 | 模拟值 |
altitude | 海拔 | 正常值或-1 | 指定值或0 | 0 | 模拟值 |
verticalAccuracy | 垂直精确度 | 正常值或-1 | 指定值或-1 | 小于0 | 模拟值 |
speed | 速度 | 正常值或-1 | 指定值或-1 | 小于0 | 模拟值 |
speedAccuracy | 速度精确度 | 正常值或-1 | -1 | 小于0 | 模拟值 |
course | 方向 | 正常值或-1 | 指定值或-1 | 小于0 | 模拟值 |
courseAccuracy | 方向精确度 | 正常值或-1 | -1 | 小于0 | 模拟值 |
timestamp | 时间戳 | 系统生成 | 系统生成或指定 | 系统生成 | 系统生成 |
confidence | 置信值? | 正常值 | 0 | 100 | 95 |
lifespan | 有效期限? | 正常值或-1 | -1 | -1 | 10 |
type | 定位数据来源类型 | 上面的枚举值 | 0 | 1 | 3 |
rawCoordinate | 原始经纬度 | 正常值 | 0 | 模拟值 | 模拟值 |
rawCourse | 原始方向 | 正常值或-1 | -1 | -1 | 模拟值 |
floor | 楼层 | 2147483647 | 2147483647 | 2147483647 | 2147483647 |
integrity | 信息完整度? | 正常值 | 0 | 0 | 50 |
referenceFrame | 参考坐标系 | 枚举值 | 0 | 0或1 | 1 |
rawReferenceFrame | 原始参考坐标系 | 枚举值 | 0 | 0 | 1 |
上述的表格中可以看出不同的定位方法所产生的数据是不一样的,我们可以根据这些特征值来进一步分析本次定位对象所生成的数据是模拟的定位数据还是真实的定位数据。同时我们还可以借助这个完整的结构体来分析正常定位情况下的一些更加详细的定位信息。比如那些不对外公布的属性:speedAccuracy、courseAccuracy、confidence、lifespan、integrity 等的值来更进一步的分析当前定坐标的有效性或者完整性等方面的信息。