首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS 识别虚拟定位调研

iOS 识别虚拟定位调研

作者头像
Swift社区
发布于 2021-11-26 07:15:09
发布于 2021-11-26 07:15:09
2.6K00
代码可运行
举报
文章被收录于专栏:Swift社区Swift社区
运行总次数:0
代码可运行

前言

最近业务开发中,有遇到我们的项目 app 定位被篡改的情况,在 android 端表现的尤为明显。为了防止这种黑产使用虚拟定位薅羊毛,iOS 也不得不进行虚拟定位的规避。

在做技术调研后,发现在苹果手机上,单凭一部手机,真正要实现虚拟定位,是比较难实现的,但还是有存在的可能性,公司的一个项目 appbugly 记录反馈用户存在使用越狱苹果手机,这就着实让人这种行为实在有大嫌。

本人和公司伙伴的共同努力下,大致调研了以下使用虚拟定位的情况(使用 Xcode 虚拟定位的方式本文忽略):

第一种:使用越狱手机

一般 app 用户存在使用越狱苹果手机的情况,一般可以推断用户的行为存在薅羊毛的嫌疑(也有 app 被竞品公司做逆向分析的可能),因为买一部越狱的手机比买一部正常的手机有难度,且在系统升级和 appstore 的使用上,均不如正常手机,本人曾经浅浅的接触皮毛知识通过越狱 iPhone5s 进行的 app 逆向。

识别方式

建议一刀切的方式进行,通过识别手机是否安装了 Cydia.app,如果安装了直接判定为越狱手机,并向后台上报“设备异常”的信息。如果不使用这种方式的方式,请继续看,后面会有其他方式解决。

专业的逆向人员是绝对可以避免 app 开发者对 Cydia 的安装检测的,当然这种情况是 app 在市场上有很大的份量,被竞争对手拿来进行逆向分析,对这种情况,虚拟的识别基本毫无意义。个人建议,直接锁死停掉此手机 app 的接口服务。

代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// 判断是否是越狱设备
/// - Returns: true 表示设备越狱
func isBrokenDevice() -> Bool {
    
    var isBroken = false
    
    let cydiaPath = "/Applications/Cydia.app"
    
    let aptPath = "/private/var/lib/apt"
    
    if FileManager.default.fileExists(atPath: cydiaPath) {
        isBroken = true
    }
    
    if FileManager.default.fileExists(atPath: aptPath) {
        isBroken = true
    }
    
    return isBroken
}

第二种:使用爱思助手

对于使用虚拟定位的场景,大多应该是司机或对接人员打卡了。而在这种场景下,就可能催生了一批专门以使用虚拟定位进行打卡薅羊毛的黑产。对于苹果手机,目前而言,能够很可以的实现的,当数爱思助手的虚拟定位功能了。

使用步骤: 下载爱思助手 mac 客户端,连接苹果手机,工具箱中点击虚拟定位,即可在地图上选定位,然后点击修改虚拟定位即可实现修改地图的定位信息。

原理: 在未越狱的设备上通过电脑和手机进行 USB 连接,电脑通过特殊协议向手机上的 DTSimulateLocation 服务发送模拟的坐标数据来实现虚假定位,目前 Xcode 上内置位置模拟就是借助这个技术来实现的。(文章来源[2]

识别方式

一、通过多次记录爱思助手的虚拟定位的数据发现,其虚拟的定位信息的经纬度的高度是为 0 且经纬度的数据位数也是值得考究的。真实定位和虚拟定位数据如下图:

真实定位

虚拟定位

仔细观察数据,不难发现,如果我们比对获取定位信息的高度,以及对经纬度的 double 位数也进行校验,虚拟定位的黑帽子就会轻易被破了。

那么如果我们比对虚拟定位的高度为 0 时,就认定为虚拟定位,那么就会产生一个疑问,真实海拔就是零的地点,如何解决?这里科普下中国的海拔零度位置,中国水准零点位于青岛市东海中路银海大世界内的“中华人民共和国水准零点”,是国内唯一的水准零点。唯一的水准零点。

同时,因为比对经纬度的 double 位数,发现虚拟定位的位数很明显不对,核对 swiftfloatdouble 的位数精度发现,虚拟定位的经纬度数据只是敷衍的满足 double 精度位数,swiftfloat 有效位数是 7double 的有效位数是 15

当然这个比较的权重是相对高度比较低的,笔者刚刚更新爱思助手版本发现新版本经纬度有更详细,但是还是达不到 double 的有效位数级别。相对于目前的爱思助手的高度比较识别为虚拟定位,已经完全可以做到。

代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if location.altitude == 0.0 {
    print("虚拟定位")
}

//位数作为判定的权重比,如果位数小于12(假定值,目前爱思助手的虚拟定位的此数据的位数是9),判断为虚拟定位,
//危险慎用,但是作为小权重的异常数据记录还是可以的
let longitude = location.coordinate.longitude
let longitudeStr = "\(longitude)".components(separatedBy: ".").last ?? ""

print("经度的有效位数:\(longitudeStr.count)")
if longitudeStr.count < 12 {

    print("虚拟定位")
}

二、把定位后的数据的经纬度上传给后台,后台再根据收到的经纬度获取详细的经纬度信息,对司机的除经纬度以外的地理信息进行深度比较,优先比较 altitudehorizontalAccuracyverticalAccuracy 值,根据值是否相等进行权衡后,确定。

三、

(一)通过获取公网 ip,大概再通过接口根据 ip 地址可获取大概的位置,但误差范围有点大。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//获取公网ip地址
var ipAddress: String? {

    let ipUrl = URL(string: "https://ipof.in/txt")!
    let ip = try? String.init(contentsOf: ipUrl, encoding: .utf8)

    return ip
}

(二)通过 Wi-Fi 热点来读取 app 位置[3]

(三)利用 CLCircularRegion 设定区域中心的指定经纬度和可设定半径范围,进行监听。

代码简略实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
manager = CLLocationManager()
//设置定位服务管理器代理
manager?.delegate = self
//设置定位模式
manager?.desiredAccuracy = kCLLocationAccuracyBest
//更新距离
manager?.distanceFilter = 100
//发送授权申请
manager?.requestWhenInUseAuthorization()

let latitude = 115.47560123242931
let longitude = 29.9757535600194
let centerCoordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let locationIDStr = ""
let clRegion = CLCircularRegion(center: centerCoordinate, radius: 100, identifier: locationIDStr)
manager?.startMonitoring(for: clRegion)

代理方法

 func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {

}

func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {

}

(四)通过 IBeacon 技术,使用 CoreBluetooth 框架下的 CBPeripheralManager 建立一个蓝牙基站。这种定位直接是端对端的直接定位,省去了 GPS 的卫星和蜂窝数据的基站通信。

代码简略实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {

    for beacon in beacons {
        var proximityStr: String = ""
        switch beacon.proximity {
        case .far:
            proximityStr = "Unknown"
        case .immediate:
            proximityStr = "Immediate"
        case .near:
            proximityStr = "Near"
        case .unknown:
            proximityStr = "Unknown"
        }

        var beaconStr = "信号:" + beacon.proximityUUID.uuidString + "major:" + beacon.major.stringValue + "minor:" + beacon.minor.stringValue + "距离:" + beacon.accuracy + "信号:" + "\(Int64(beacon.rssi))" + "接近度:" + proximityStr

        print("beacon信息: \(beaconStr)")
    }

}

func locationManager(_ manager: CLLocationManager, rangingBeaconsDidFailFor region: CLBeaconRegion, withError error: Error) {

}
    
----------------------------------------------------------------------------------

//不能单独创建一个类遵守CBPeripheralManagerDelegate协议,需要先遵守NSObjectProtocol协议,这里直接继承NSObject
class CoreBluetoothManager:NSObject, CBPeripheralManagerDelegate { 
    
    //建立一个蓝牙基站。
    lazy var peripheralManager: CBPeripheralManager =  CBPeripheralManager(delegate: self, queue: DispatchQueue.main, options: nil)
            
    lazy var region: CLBeaconRegion = {
        
        guard let uuid = UUID(uuidString: "xxx") else {
            return CLBeaconRegion()
        }
        let major: CLBeaconMajorValue = 1
        let minor: CLBeaconMajorValue = 1
        let id = "创建的蓝牙基站的名称"
        let region = CLBeaconRegion(proximityUUID: uuid, major: major, minor: minor, identifier: id)
        return region
    }()
    
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        
        switch peripheral.state {
        case CBManagerState.poweredOn:
            
            if let data = self.region.peripheralData(withMeasuredPower: nil) as? [String : Any] {
                
                self.peripheralManager.startAdvertising(data)
            }
            
        case CBManagerState.poweredOff,
             CBManagerState.resetting,
             CBManagerState.unauthorized,
             CBManagerState.unsupported,
             CBManagerState.unknown:
            
            break
        }
    }
   
    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        
    }
        
}

四(待完善)、 iOS防黑产虚假定位检测技术 文章的末尾附的解法本人有尝试过,一层一层通过 kvc 读取 CLLocation_internalfLocation,只能读取到到此。再通过 kvc 读取会报以下错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Expression can't be run, because there is no JIT compiled function

深入研究,在苹果的官方开发文档上发现了这个解释[4],也有说设置 debug+ 优化策略的,但 iOS 默认 bug 环境就是 -Onone 级别的。其实主要原因貌似因为 JIT 的设置是在开发 mac 客户端的时候,才能在 Signing&CapabilitiesHardened Runtime 中找到。关于 Allow Execution of JIT-compiled Code 的设置(官方文章[5])。最终只能卡到这里,若有大神能通过其他方式读取 CLLocation 的真实定位(这是极其完美的解决方案),还请不吝赐教。

附:

CLLocation 对象私有变量 _internal 实例对象的官方定义[6]

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface CLLocationInternal : NSObject {
    struct {
        int suitability;
        struct {
            double latitude;
            double longitude;
        } coordinate;
        double horizontalAccuracy;
        double altitude;
        double verticalAccuracy;
        double speed;
        double speedAccuracy;
        double course;
        double courseAccuracy;
        double timestamp;
        int confidence;
        double lifespan;
        int type;
        struct {
            double latitude;
            double longitude;
        } rawCoordinate;
        double rawCourse;
        int floor;
        unsigned int integrity;
        int referenceFrame;
        int rawReferenceFrame;
    }  fLocation;
    CLLocationMatchInfo * fMatchInfo;
    double  fTrustedTimestamp;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@class NSData;

@interface CLLocationMatchInfo : NSObject <NSCopying, NSSecureCoding> {

    id _internal;
}
@property (nonatomic,readonly) long long matchQuality;
@property (nonatomic,readonly) CLLocationCoordinate2D matchCoordinate;
@property (nonatomic,readonly) double matchCourse;
@property (nonatomic,readonly) int matchFormOfWay;
@property (nonatomic,readonly) int matchRoadClass;
@property (getter=isMatchShifted,nonatomic,readonly) BOOL matchShifted;
@property (nonatomic,copy,readonly) NSData * matchDataArray;

参考资料

[1]iOS 防黑产虚假定位检测技术: https://cloud.tencent.com/developer/article/1800531

[2]Wifi 定位原理及 iOS Wifi 列表获取: http://www.caojiarun.com/2017/01/iOS_Wifilist/

[3]Allow Execution of JIT-compiled Code Entitlement: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit

[4]Hardened Runtime: https://developer.apple.com/documentation/security/hardened_runtime

[5]_internal 实例对象的官方定义: https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/CoreLocation.framework/CLLocationInternal.h

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Swift社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS-世界那么大,CoreLocation带你去看看
一. 简介 在我们日常生活中时常用到地图和定位功能,来导航去你想去的地方或者寻找周边的景点,餐厅,电影院等等,在iOS开发中,要想加入这两大功能,必须基于两个框架进行开发,有了这两个框架,想去哪就去哪。 CoreLocation :用于地理定位,地理编码,区域监听等(着重功能实现) MapKit :用于地图展示,例如大头针,路线、覆盖层展示等(着重界面展示) 二. CoreLocation框架的基本使用 1. CoreLocation使用步骤 导入CoreLocation框架。 创建CLLocation
xx_Cc
2018/05/10
1.6K0
iOS地理围栏技术的应用
遇到一个需求,要求监测若干区域,设备进入这些区域则要上传数据,且可以后台监测,甚至app被杀死也要监测。发现oc的地理围栏技术完美匹配这个需求,任务做完了,把遇到的坑记录下来,也许能帮到你呢。 要做这个需求,我们需要把任务分成两大块,一块是支持后台监测且app被杀掉也要持续监测,另一块是如何进行区域监测。 而区域监测我们有3种方法完成: 1,oc自有的,利用CLLocationManager监测若干CLCircularRegion区域 2,高德地图旧版地理围栏,利用AMapLocationManager监测
王大锤
2018/05/17
2.2K0
iOS区域监控(地理围栏)
区域监控,高德地图上叫地理围栏,两者都是同一个意思。此功能实现的是:首先创建一个区域(围栏),当用户设备进入或者离开此区域时,会有相应的代理方法响应,开发者可以做一些操作。并且最重要的一点是当开启了区域监控,即使用户杀死了APP还是可以监听到代理方法的响应,从而做一些操作。
用户6094182
2019/08/23
1.7K0
iOS区域监控(地理围栏)
iOS-CoreLocation框架的定位和逆地址解析详解
一、权限问题 在iOS8以后,应用定位需要获取用户授权,我们可以请求的定位权限有两种: 1.仅在使用时定位requestWhenInUseAuthorization(应用在前台才能定位); 2.始
用户2215591
2018/06/29
1.4K0
iOS-定位
-需要在info.plist配置NSLocationWhenInUseUsageDescription字段;
GuangdongQi
2021/11/24
1.6K0
iOS-定位
iOS设备限制境外定位(支付交易风险控制策略)
iOS定位、地理/逆地理编码的使用:https://kunnan.blog.csdn.net/article/details/119685612
公众号iOS逆向
2021/08/25
1.3K0
iOS设备限制境外定位(支付交易风险控制策略)
iOS小技能:封装定位SDK,统一数据模型和错误处理。
需求背景:收款页面需要请求IP定位API获取经纬度,由于高德的API的库不准确(没有实时更新),使用公司决定换腾讯API。
公众号iOS逆向
2022/08/22
1K0
iOS小技能:封装定位SDK,统一数据模型和错误处理。
iOS开发-用户定位获取-CoreLocation的实际应用-CLLocationManger获取定位权限-CLLocation详细使用方式
iOS提供了两个框架用来定位以及地图显示。CoreLocation框架包含的类可以帮助设备确定位置和航向以及使用基于位置的有效信息。MapKit框架未定位提供了户用页面的支持(地图显示),里面包含了地图视图、卫星地图视图以及2D、3D混合视图,并且能够让开发人员管理地图标注和地图覆盖层,前者 用于标注地点(常见的地图大头针),后者用来突出某区域或者路线等。
全栈程序员站长
2022/09/17
5K0
iOS开发-用户定位获取-CoreLocation的实际应用-CLLocationManger获取定位权限-CLLocation详细使用方式
iOS定位--CoreLocation框架
CoreLocation框架的使用 // 首先导入头文件 #import <CoreLocation/CoreLocation.h> CoreLocation框架中所有数据类型的前缀都是CL CoreLocation中使用CLLocationManager对象来做用户定位 1.CLLocationManager的使用 CLLocationManager的常用操作 /** * 定位管理者,全局变量强引用,防止销毁 */ @property (nonatomic ,strong) CLLocationMa
用户1941540
2018/05/11
2K0
iOS iOS 地图与定位开发系列教程
iPhone SDK提供了三个类来管理位置信息:CLLocation CLLocationManager 和 CLLHeading(不常用)。除了使用GPS来获取当前的位置信息外,iPhone也可以基于WiFi基站和无线发射塔来获得位置信息。GPS的精度最高,可以精确到米级别,但是也最耗电。
全栈程序员站长
2022/09/17
2.8K0
iOS逆向入门实践 — 逆向微信,伪装定位(二)
还是跟之前的步骤一致,创建工程,然后配置 Makefile。注意创建工程时名字只能包含数字跟字母。
全栈程序员站长
2022/09/05
1.5K0
【IOS开发基础系列】地图开发专题
http://www.cnblogs.com/syxchina/archive/2012/10/14/2723522.html
江中散人_Jun
2023/10/16
5950
【IOS开发基础系列】地图开发专题
iOS开发之定位
在iOS开发中,定位是很多App都需要使用的功能。本文主要对iOS中的定位知识点进行介绍。本文代码环境为:Xcode 10.1 + Swift 4.2。
YungFan
2019/03/21
1.7K0
iOS开发之定位
IOS 定位CoreLocation代码
定位需要使用苹果官方的类库CoreLocation,通过GPS来确定位置信息 并且需要实现CLLocationManagerDelegate协议 1.首先添加类库CoreLocation
用户8671053
2021/10/29
6390
GPS用户定位
现在的手机大多数都提供了GPS模块、通过GPS模块可以接收GPS信号,并可精确地指定目前所在的位置,如果将GPS定位功能应用到地图上,还可以实现导航、搜索公交、搜索驾车路线等实用且有趣功能。本章中我们先学习GPS的基本知识,然后通过具体的案例讲解Android环境中GPS开发的基本原理及步骤。学习过本章知识之后我们能够利用GPS进行简单的定位功能的开发。学习本章的重点是掌握LocationManager、LocationProvider与LocationListener等API的功能和用法,并可以通过它们来监听、获取GPS定位信息。
张哥编程
2024/12/17
5430
GPS用户定位
iOS_系统自带地图圆形区域选择范围
5.聚集操作:删除原理的大头针,在新经纬度添加大头针,并将地图移动到新的经纬度(反地理编码获得位置信息)
mikimo
2022/07/20
2.5K0
iOS_系统自带地图圆形区域选择范围
iOS学习——自动定位
  最近在项目中需要做自动定位功能,就是你在参加会议通过扫描二维码签到的时候自动定位并将你的定位信息在签到中上传,这样可以避免我们进行假签到。在这个功能中,主要用到的是系统自带的定位模块,首先我们是需要配置定位功能的参数,然后当我们定位成功时调用特定的方法进行相应操作就可以了,当然,在定位失败时我们也可以进行相应的操作,这些都有对应的一些回调方法,我们只需要重写对应的回调方法就可以实现对应的功能了。   首先,我们用到的系统自带的定位模块是: <CoreLocation/CoreLocation.h> ,定
mukekeheart
2018/03/26
1K0
IOS定位服务的应用 原
在IOS8之后,IOS的定位服务做了优化,若要使用定位服务,必须先获取用户的授权。
珲少
2018/08/15
9750
IOS定位服务的应用
                                                                            原
iOS8新特性之基于地理位置的消息通知UILocalNotification
iOS8中更新和公开了非常多接口,当中有一项本地消息通知UILocalNotification,大家肯定都不陌生。
全栈程序员站长
2022/07/10
5080
iOS8新特性之基于地理位置的消息通知UILocalNotification
iOS关于地图定位基础(二)[通俗易懂]
在前一篇文章 iOS关于地图定位基础(一) 中我们主要总结了 iOS 里面利用原生 CoreLocation 框架实现基本定位功能和一些注意点,侧重点主要是iOS8+之后的定位授权与授权状态的使用。接下来本篇文章主要是讲解如何利用 CoreLocation 框架实现地理定位、区域监听、地理编码的具体实现。(PS:下文涉及我自定义的指南针Demo请去我的GitHub仓库查看源码https://github.com/IMLoser/HWCompass,谢谢大家支持。)
全栈程序员站长
2022/09/17
1.2K0
iOS关于地图定位基础(二)[通俗易懂]
相关推荐
iOS-世界那么大,CoreLocation带你去看看
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档