当前位置: 首页 > 科技观察

浅谈iOS识别虚拟位置研究

时间:2023-03-19 20:19:18 科技观察

本文转载自微信公众号“Swift社区”,作者景峰凌宇。转载本文请联系Swift社区公众号。前言在最近的业务开发中,遇到了我们项目的app定位被篡改的情况,尤其是在android端。为了防止这种黑产利用虚拟定位来挤羊毛,iOS也不得不避免使用虚拟定位。经过技术研究,我发现在苹果手机上,仅用一部手机很难实现虚拟定位,但还是有可能的。公司某项目APP的BUG记录反映有用户使用过。越狱苹果手机,着实让人觉得这种行为真的很可疑。在自己和公司小伙伴的共同努力下,大致调查了以下几种使用虚拟定位的情况(本文忽略Xcode虚拟定位的使用方式):第一种方法:使用越狱手机。一般app用户使用越狱的苹果手机,一般可以推断用户的行为有挖羊毛嫌疑(也有app被竞品公司反向分析的可能),因为买越狱手机比买越狱手机难购买普通手机,无论是系统升级还是应用商店的使用,都不如普通手机。通过iPhone5s越狱,浅浅接触了app逆向工程的肤浅知识。鉴定方法建议一刀切。通过识别手机是否安装了Cydia.app,如果安装了则直接判断为越狱手机,并向后台上报“设备异常”信息。如果您不使用此方法,请继续阅读,稍后会有其他方法解决。专业的逆向工程师绝对可以避免应用开发者对Cydia的安装检测。当然,这种情况是App在市场上的权重较大,被竞争对手用来进行逆向分析。在这种情况下,虚拟识别基本没有意义。我个人的建议是直接锁定并停止该手机APP的界面服务。这是一篇关于开发人员如何识别苹果手机已越狱的文章[1]。代码实现///判断是否越狱设备///-返回:true表示设备越狱funcisBrokenDevice()->Bool{varisBroken=falseletcydiaPath="/Applications/Cydia.app"letaptPath="/private/var/lib/apt"ifFileManager.default.fileExists(atPath:cydiaPath){isBroken=true}ifFileManager.default.fileExists(atPath:aptPath){isBroken=true}returnisBroken}第二种:使用爱思助手针对使用虚拟的场景定位,大部分应该是签到的司机或者对接人员。在这个场景下,可能会催生出一批专门利用虚拟定位签到的黑产品。对于苹果手机来说,目前能够很好实现的就是爱思助手的虚拟定位功能。使用步骤:下载爱思助手Mac客户端,连接苹果手机,点击工具箱中的虚拟位置,然后在地图上选择一个位置,然后点击修改虚拟位置即可修改地图的位置信息。原理:在未越狱的设备上,通过USB连接电脑和手机,电脑通过特殊协议向手机上的DTSimulateLocation服务发送模拟坐标数据,实现虚假定位。目前,Xcode内置的位置模拟就是借助该技术实现的。(文章来源[2])识别方法1、通过多次记录爱思助手的虚拟定位数据,发现虚拟定位信息的经纬度高度为0,纬度和经度的数据位数为0经度也值得关注。真实定位和虚拟定位数据如下图所示:真实定位和虚拟定位仔细观察数据,不难发现,如果我们将获取到的定位信息进行高度对比,验证经纬度两位数,虚拟定位的黑帽很容易被打破。那么如果我们将虚拟定位的高度与0进行比较,就会认为是虚拟定位,那么就会有一个问题,真实的高度为0,如何解决呢?这里是科普下的中国零度高度,中国标准零度点位于青岛东海中路银海世界的“中华人民共和国零度层”,是青岛唯一的零度层中国。唯一的零级。同时,因为对比经纬度两位数,发现虚拟定位的位数明显错误。检查swift中float和double的位数精度后发现,虚拟定位的经纬度数据只是敷衍满足double精度的位数,而swift的float的尾数为7,double的尾数为15当然,这个比较的体重相对于身高来说是比较低的。刚刚更新了爱思助手的版本,发现新版本的经纬度更加详细了,但是还是没有达到double的有效位数级别。对比爱思助手目前的身高对比,完全可以将其认定为虚拟定位。代码实现iflocation.altitude==0.0{print("VirtualPositioning")}//位数作为决定的权重比例。如果位数小于12(假设值,当前爱思助手虚拟定位该数据位数为9),判断为虚拟定位,//危险慎用,但仍有可能记录权重小的异常数据)iflongitudeStr.count<12{print("虚拟定位")}2.将定位数据的经纬度上传到后台,后台会根据接收到的经纬度获取详细的经纬度信息,执行深度比对司机除经纬度以外的地理信息,优先比对altitude、horizo??ntalAccuracy、verticalAccuracy值,根据值是否相等权衡后判断。3、(1)通过获取公网ip,可以通过接口根据ip地址获取大概位置,但是误差范围有点大。//获取公网ip地址varipAddress:String?{letipUrl=URL(string:"https://ipof.in/txt")!letip=try?String.init(contentsOf:ipUrl,encoding:.utf8)returnip}(2)通过Wi-Fi热点读取app的位置[3](3)使用CLCircularRegion设置指定区域中心的经纬度和可设置的监控半径范围。简单代码实现:manager=CLLocationManager()//设置位置服务管理器proxymanager?.delegate=self//设置位置模式管理器?.desiredAccuracy=kCLLocationAccuracyBest//更新距离管理器?.distanceFilter=100//发送授权应用程序管理器?.requestWhenInUseAuthorization()letlatitude=115.47560123242931letlongitude=29.9757535600194letcenterCoordinate=CLLocationCoordinate2D(latitude:latitude,longitude:longitude)letlocationIDStr=""letclRegion=CLCircularRegion(center:centerCoordinate,radius:100,identifier:locationIDStr)manager?:startRemonitoring()代理方法funlocationManager(_manager:CLLocationManager,didEnterRegionregion:CLRegion){}funlocationManager(_manager:CLLocationManager,didExitRegionregion:CLRegion){}(4)通过IBeacon技术,使用CoreBluetooth框架下的CBPeripheralManager建立蓝牙基站。这种定位是直接端到端的直接定位,不需要GPS卫星和蜂窝数据基站通信。简单的代码实现:funlocationManager(_manager:CLLocationManager,didRangeBeaconsbeacons:[CLBeacon],inregion:CLBeaconRegion){forbeaconinbeacons{varproximityStr:String=""switchbeacon.proximity{case.far:proximityStr="Unknown"case.immediate:proximityStr="Immediate"case.near:proximityStr="Near"case.unknown:proximityStr="Unknown"}varbeaconStr="Signal:"+beacon.proximityUUID.uuidString+"major:"+beacon.major.stringValue+"minor:"+beacon.minor.stringValue+"Distance:"+beacon.accuracy+"Signal:"+"\(Int64(beacon.rssi))"+"Proximity:"+proximityStrprint("Beaconinformation:\(beaconStr)")}}funlocationManager(_manager:CLLocationManager,rangingBeaconsDidFailForregion:CLBeaconRegion,withErrorerror:Error){}-------------------------------------------------------------------------------//不能单独创建遵守CBPeripheralManagerDelegate协议的类首先需要遵守NSObjectProtocol协议,这里直接继承自NSObjectclassCoreBlue吨oothManager:NSObject,CBPeripheralManagerDelegate{//搭建蓝牙基站lazyvarperipheralManager:CBPeripheralManager=CBPeripheralManager(delegate:self,queue:DispatchQueue.main,options:nil)lazyvarregion:CLBeaconRegion={guardletuuid=UUID(uuidString:"xxx")else{returnCLBeaconRegionMaminor()}letmajor:CLBeaconMaminorlet=CLBeaconRegion=1="创建的蓝牙基站名称"letregion=CLBeaconRegion(proximityUUID:uuid,major:major,minor:minor,identifier:id)returnregion}()funcperipheralManagerDidUpdateState(_peripheral:CBPeripheralManager){switchperipheral.state{caseCBManagerState.poweredOn:ifletdata=self.region.peripheralData(withMeasuredPower:nil)as?[String:Any]{self.peripheralManager.startAdvertising(data)}caseCBManagerState.poweredOff,CBManagerState.resetting,CBManagerState.unauthorized,CBManagerState.unsupported,CBManagerState.unknown:break}}funcperipheralManagerDidStartAdvertising(_peripheral:CBPeripheralManager,error:Error?){}}第四(待完善),iOS反黑产品假定位det文末附解决方案ection技术我试过了,通过kvc逐层读取CLLocation的_内部fLocationn,只能读到这里再通过kvc读,会报如下错误:Expressioncan'tberun,因为没有深入研究JITcompiledfunction,在苹果官方开发文档[4]上找到了这个解释,并且据说还设置了debug+优化策略,但是iOS默认的bug环境是-Onone级别的。其实主要原因好像是开发mac客户端时只能在Signing&Capabilities的HardenedRuntime中找到JIT设置。关于AllowExecutionofJIT-compiledCode的设置(官方文章[5])。最后只能卡在这里。如果有人可以通过其他方式读取CLLocation的真实位置(这是一个极其完美的解决方案),请告诉我。附件:CLLocation对象私有量_internal实例对象的官方指定[6]:@interfaceCLLocationInternal:NSObject{struct{intsuitability;struct{doublelatitude;doublelongitude;}coordinate;doublehorizo??ntalAccuracy;doublealtitude;doubleverticalAccuracy;doublespeed;doublespeedAccuracy;amp;doublecourse;intconfidence;doublelifespan;inttype;struct{doublelatitude;doublelongitude;}rawCoordinate;doublerawCourse;intfloor;unsignedintintegrity;intreferenceFrame;intrawReferenceFrame;}fLocation;CLLocationMatchInfo*fMatchInfo;doublefTrustedTimestamp;}@classNSData;@interfaceCLLocationMatchInfo:NSObject{id_internal;}@property(非原子,只读)longlongmatchQuality;@property(非原子,只读)CLLocationCoordinate2DmatchCoordinate;@property(非原子,只读)doublematchCourse;@property(非原子,只读)intmatchFormOfWay;@property(非原子,只读)intmatchRoadClass;@property(getter=isMatchShifted,非原子,只读)BOOLmatchShifted;@property(nonatomic,copy,readonly)NSData*matchDataArray;参考[1]如何用代码判断iOS系统是否越狱:https://www.huaweicloud.com/articles/7c6b8027253c4a97196d359840f638d9.html[2]iOS反越狱黑产虚假定位检测技术:https://cloud.tencent.com/developer/article/1800531[3]Wifi定位原理及iOSWifi列表获取:http://www.caojiarun.com/2017/01/iOS_Wifilist/[4]允许执行JIT编译的代码授权:https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit[5]强化运行时:https://developer.apple。com/documentation/security/hardened_runtime[6]_internal实例对象的官方定义:https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/CoreLocation.framework/CLLocationInternal.h