成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

談?wù)?iOS 識(shí)別虛擬定位調(diào)研

移動(dòng)開發(fā) iOS
最近業(yè)務(wù)開發(fā)中,有遇到我們的項(xiàng)目 app 定位被篡改的情況,在 android 端表現(xiàn)的尤為明顯。為了防止這種黑產(chǎn)使用虛擬定位薅羊毛,iOS 也不得不進(jìn)行虛擬定位的規(guī)避。

[[415572]]

本文轉(zhuǎn)載自微信公眾號(hào)「Swift社區(qū)」,作者靜楓靈雨。轉(zhuǎn)載本文請(qǐng)聯(lián)系Swift社區(qū)公眾號(hào)。

前言

最近業(yè)務(wù)開發(fā)中,有遇到我們的項(xiàng)目 app 定位被篡改的情況,在 android 端表現(xiàn)的尤為明顯。為了防止這種黑產(chǎn)使用虛擬定位薅羊毛,iOS 也不得不進(jìn)行虛擬定位的規(guī)避。

在做技術(shù)調(diào)研后,發(fā)現(xiàn)在蘋果手機(jī)上,單憑一部手機(jī),真正要實(shí)現(xiàn)虛擬定位,是比較難實(shí)現(xiàn)的,但還是有存在的可能性,公司的一個(gè)項(xiàng)目 app 的 bugly 記錄反饋用戶存在使用越獄蘋果手機(jī),這就著實(shí)讓人這種行為實(shí)在有大嫌。

本人和公司伙伴的共同努力下,大致調(diào)研了以下使用虛擬定位的情況(使用 Xcode 虛擬定位的方式本文忽略):

第一種:使用越獄手機(jī)

一般 app 用戶存在使用越獄蘋果手機(jī)的情況,一般可以推斷用戶的行為存在薅羊毛的嫌疑(也有 app 被競(jìng)品公司做逆向分析的可能),因?yàn)橘I一部越獄的手機(jī)比買一部正常的手機(jī)有難度,且在系統(tǒng)升級(jí)和 appstore 的使用上,均不如正常手機(jī),本人曾經(jīng)淺淺的接觸皮毛知識(shí)通過越獄 iPhone5s 進(jìn)行的 app 逆向。

識(shí)別方式

建議一刀切的方式進(jìn)行,通過識(shí)別手機(jī)是否安裝了 Cydia.app,如果安裝了直接判定為越獄手機(jī),并向后臺(tái)上報(bào)“設(shè)備異常”的信息。如果不使用這種方式的方式,請(qǐng)繼續(xù)看,后面會(huì)有其他方式解決。

專業(yè)的逆向人員是絕對(duì)可以避免 app 開發(fā)者對(duì) Cydia 的安裝檢測(cè)的,當(dāng)然這種情況是 app 在市場(chǎng)上有很大的份量,被競(jìng)爭(zhēng)對(duì)手拿來進(jìn)行逆向分析,對(duì)這種情況,虛擬的識(shí)別基本毫無意義。個(gè)人建議,直接鎖死停掉此手機(jī) app 的接口服務(wù)。這里推薦一篇開發(fā)者如何識(shí)別蘋果手機(jī)已經(jīng)越獄[1]的文章。

代碼實(shí)現(xiàn)

  1. /// 判斷是否是越獄設(shè)備 
  2. /// - Returnstrue 表示設(shè)備越獄 
  3. func isBrokenDevice() -> Bool { 
  4.      
  5.     var isBroken = false 
  6.      
  7.     let cydiaPath = "/Applications/Cydia.app" 
  8.      
  9.     let aptPath = "/private/var/lib/apt" 
  10.      
  11.     if FileManager.default.fileExists(atPath: cydiaPath) { 
  12.         isBroken = true 
  13.     } 
  14.      
  15.     if FileManager.default.fileExists(atPath: aptPath) { 
  16.         isBroken = true 
  17.     } 
  18.      
  19.     return isBroken 

第二種:使用愛思助手

對(duì)于使用虛擬定位的場(chǎng)景,大多應(yīng)該是司機(jī)或?qū)尤藛T打卡了。而在這種場(chǎng)景下,就可能催生了一批專門以使用虛擬定位進(jìn)行打卡薅羊毛的黑產(chǎn)。對(duì)于蘋果手機(jī),目前而言,能夠很可以的實(shí)現(xiàn)的,當(dāng)數(shù)愛思助手的虛擬定位功能了。

使用步驟: 下載愛思助手 mac 客戶端,連接蘋果手機(jī),工具箱中點(diǎn)擊虛擬定位,即可在地圖上選定位,然后點(diǎn)擊修改虛擬定位即可實(shí)現(xiàn)修改地圖的定位信息。

原理: 在未越獄的設(shè)備上通過電腦和手機(jī)進(jìn)行 USB 連接,電腦通過特殊協(xié)議向手機(jī)上的 DTSimulateLocation 服務(wù)發(fā)送模擬的坐標(biāo)數(shù)據(jù)來實(shí)現(xiàn)虛假定位,目前 Xcode 上內(nèi)置位置模擬就是借助這個(gè)技術(shù)來實(shí)現(xiàn)的。(文章來源[2])

識(shí)別方式

一、通過多次記錄愛思助手的虛擬定位的數(shù)據(jù)發(fā)現(xiàn),其虛擬的定位信息的經(jīng)緯度的高度是為 0 且經(jīng)緯度的數(shù)據(jù)位數(shù)也是值得考究的。真實(shí)定位和虛擬定位數(shù)據(jù)如下圖:

真實(shí)定位

虛擬定位

仔細(xì)觀察數(shù)據(jù),不難發(fā)現(xiàn),如果我們比對(duì)獲取定位信息的高度,以及對(duì)經(jīng)緯度的 double 位數(shù)也進(jìn)行校驗(yàn),虛擬定位的黑帽子就會(huì)輕易被破了。

那么如果我們比對(duì)虛擬定位的高度為 0 時(shí),就認(rèn)定為虛擬定位,那么就會(huì)產(chǎn)生一個(gè)疑問,真實(shí)海拔就是零的地點(diǎn),如何解決?這里科普下中國(guó)的海拔零度位置,中國(guó)水準(zhǔn)零點(diǎn)位于青島市東海中路銀海大世界內(nèi)的“中華人民共和國(guó)水準(zhǔn)零點(diǎn)”,是國(guó)內(nèi)唯一的水準(zhǔn)零點(diǎn)。唯一的水準(zhǔn)零點(diǎn)。

同時(shí),因?yàn)楸葘?duì)經(jīng)緯度的 double 位數(shù),發(fā)現(xiàn)虛擬定位的位數(shù)很明顯不對(duì),核對(duì) swift 的 float 和 double 的位數(shù)精度發(fā)現(xiàn),虛擬定位的經(jīng)緯度數(shù)據(jù)只是敷衍的滿足 double 精度位數(shù),swift 的 float 有效位數(shù)是 7,double 的有效位數(shù)是 15。

當(dāng)然這個(gè)比較的權(quán)重是相對(duì)高度比較低的,筆者剛剛更新愛思助手版本發(fā)現(xiàn)新版本經(jīng)緯度有更詳細(xì),但是還是達(dá)不到 double 的有效位數(shù)級(jí)別。相對(duì)于目前的愛思助手的高度比較識(shí)別為虛擬定位,已經(jīng)完全可以做到。

代碼實(shí)現(xiàn)

  1. if location.altitude == 0.0 { 
  2.     print("虛擬定位"
  3.  
  4. //位數(shù)作為判定的權(quán)重比,如果位數(shù)小于12(假定值,目前愛思助手的虛擬定位的此數(shù)據(jù)的位數(shù)是9),判斷為虛擬定位, 
  5. //危險(xiǎn)慎用,但是作為小權(quán)重的異常數(shù)據(jù)記錄還是可以的 
  6. let longitude = location.coordinate.longitude 
  7. let longitudeStr = "\(longitude)".components(separatedBy: ".").last ?? "" 
  8.  
  9. print("經(jīng)度的有效位數(shù):\(longitudeStr.count)"
  10. if longitudeStr.count < 12 { 
  11.  
  12.     print("虛擬定位"

二、把定位后的數(shù)據(jù)的經(jīng)緯度上傳給后臺(tái),后臺(tái)再根據(jù)收到的經(jīng)緯度獲取詳細(xì)的經(jīng)緯度信息,對(duì)司機(jī)的除經(jīng)緯度以外的地理信息進(jìn)行深度比較,優(yōu)先比較 altitude、horizontalAccuracy、verticalAccuracy 值,根據(jù)值是否相等進(jìn)行權(quán)衡后,確定。

三、

(一)通過獲取公網(wǎng) ip,大概再通過接口根據(jù) ip 地址可獲取大概的位置,但誤差范圍有點(diǎn)大。

  1. //獲取公網(wǎng)ip地址 
  2. var ipAddress: String? { 
  3.  
  4.     let ipUrl = URL(string: "https://ipof.in/txt")! 
  5.     let ip = try? String.init(contentsOf: ipUrl, encoding: .utf8) 
  6.  
  7.     return ip 

(二)通過 Wi-Fi 熱點(diǎn)來讀取 app 位置[3]

(三)利用 CLCircularRegion 設(shè)定區(qū)域中心的指定經(jīng)緯度和可設(shè)定半徑范圍,進(jìn)行監(jiān)聽。

代碼簡(jiǎn)略實(shí)現(xiàn):

  1. manager = CLLocationManager() 
  2. //設(shè)置定位服務(wù)管理器代理 
  3. manager?.delegate = self 
  4. //設(shè)置定位模式 
  5. manager?.desiredAccuracy = kCLLocationAccuracyBest 
  6. //更新距離 
  7. manager?.distanceFilter = 100 
  8. //發(fā)送授權(quán)申請(qǐng) 
  9. manager?.requestWhenInUseAuthorization() 
  10.  
  11. let latitude = 115.47560123242931 
  12. let longitude = 29.9757535600194 
  13. let centerCoordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 
  14. let locationIDStr = "" 
  15. let clRegion = CLCircularRegion(center: centerCoordinate, radius: 100, identifier: locationIDStr) 
  16. manager?.startMonitoring(for: clRegion) 
  17.  
  18. 代理方法 
  19.  
  20.  func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { 
  21.  
  22.  
  23. func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { 
  24.  

(四)通過 IBeacon 技術(shù),使用 CoreBluetooth 框架下的 CBPeripheralManager 建立一個(gè)藍(lán)牙基站。這種定位直接是端對(duì)端的直接定位,省去了 GPS 的衛(wèi)星和蜂窩數(shù)據(jù)的基站通信。

代碼簡(jiǎn)略實(shí)現(xiàn):

  1. func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) { 
  2.  
  3.     for beacon in beacons { 
  4.         var proximityStr: String = "" 
  5.         switch beacon.proximity { 
  6.         case .far: 
  7.             proximityStr = "Unknown" 
  8.         case .immediate: 
  9.             proximityStr = "Immediate" 
  10.         case .near: 
  11.             proximityStr = "Near" 
  12.         case .unknown: 
  13.             proximityStr = "Unknown" 
  14.         } 
  15.  
  16.         var beaconStr = "信號(hào):" + beacon.proximityUUID.uuidString + "major:" + beacon.major.stringValue + "minor:" + beacon.minor.stringValue + "距離:" + beacon.accuracy + "信號(hào):" + "\(Int64(beacon.rssi))" + "接近度:" + proximityStr 
  17.  
  18.         print("beacon信息: \(beaconStr)"
  19.     } 
  20.  
  21.  
  22. func locationManager(_ manager: CLLocationManager, rangingBeaconsDidFailFor region: CLBeaconRegion, withError error: Error) { 
  23.  
  24.      
  25. ---------------------------------------------------------------------------------- 
  26.  
  27. //不能單獨(dú)創(chuàng)建一個(gè)類遵守CBPeripheralManagerDelegate協(xié)議,需要先遵守NSObjectProtocol協(xié)議,這里直接繼承NSObject 
  28. class CoreBluetoothManager:NSObject, CBPeripheralManagerDelegate {  
  29.      
  30.     //建立一個(gè)藍(lán)牙基站。 
  31.     lazy var peripheralManager: CBPeripheralManager =  CBPeripheralManager(delegate: self, queue: DispatchQueue.main, options: nil) 
  32.              
  33.     lazy var region: CLBeaconRegion = { 
  34.          
  35.         guard let uuid = UUID(uuidString: "xxx"else { 
  36.             return CLBeaconRegion() 
  37.         } 
  38.         let major: CLBeaconMajorValue = 1 
  39.         let minor: CLBeaconMajorValue = 1 
  40.         let id = "創(chuàng)建的藍(lán)牙基站的名稱" 
  41.         let region = CLBeaconRegion(proximityUUID: uuid, major: major, minor: minor, identifier: id) 
  42.         return region 
  43.     }() 
  44.      
  45.     func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { 
  46.          
  47.         switch peripheral.state { 
  48.         case CBManagerState.poweredOn: 
  49.              
  50.             if let data = self.region.peripheralData(withMeasuredPower: nil) as? [String : Any] { 
  51.                  
  52.                 self.peripheralManager.startAdvertising(data) 
  53.             } 
  54.              
  55.         case CBManagerState.poweredOff, 
  56.              CBManagerState.resetting, 
  57.              CBManagerState.unauthorized, 
  58.              CBManagerState.unsupported, 
  59.              CBManagerState.unknown: 
  60.              
  61.             break 
  62.         } 
  63.     } 
  64.     
  65.     func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) { 
  66.          
  67.     } 
  68.          

四(待完善)、 iOS防黑產(chǎn)虛假定位檢測(cè)技術(shù) 文章的末尾附的解法本人有嘗試過,一層一層通過 kvc 讀取 CLLocation 的 _internal 的 fLocation,只能讀取到到此。再通過 kvc 讀取會(huì)報(bào)以下錯(cuò)誤:

  1. Expression can't be run, because there is no JIT compiled function 

深入研究,在蘋果的官方開發(fā)文檔上發(fā)現(xiàn)了這個(gè)解釋[4],也有說設(shè)置 debug+ 優(yōu)化策略的,但 iOS 默認(rèn) bug 環(huán)境就是 -Onone 級(jí)別的。其實(shí)主要原因貌似因?yàn)?JIT 的設(shè)置是在開發(fā) mac 客戶端的時(shí)候,才能在 Signing&Capabilities 的 Hardened Runtime 中找到。關(guān)于 Allow Execution of JIT-compiled Code 的設(shè)置(官方文章[5])。最終只能卡到這里,若有大神能通過其他方式讀取 CLLocation 的真實(shí)定位(這是極其完美的解決方案),還請(qǐng)不吝賜教。

附:

CLLocation 對(duì)象私有變量 _internal 實(shí)例對(duì)象的官方定義[6]:

  1. @interface CLLocationInternal : NSObject { 
  2.     struct { 
  3.         int suitability; 
  4.         struct { 
  5.             double latitude; 
  6.             double longitude; 
  7.         } coordinate; 
  8.         double horizontalAccuracy; 
  9.         double altitude; 
  10.         double verticalAccuracy; 
  11.         double speed; 
  12.         double speedAccuracy; 
  13.         double course; 
  14.         double courseAccuracy; 
  15.         double timestamp
  16.         int confidence; 
  17.         double lifespan; 
  18.         int type; 
  19.         struct { 
  20.             double latitude; 
  21.             double longitude; 
  22.         } rawCoordinate; 
  23.         double rawCourse; 
  24.         int floor; 
  25.         unsigned int integrity; 
  26.         int referenceFrame; 
  27.         int rawReferenceFrame; 
  28.     }  fLocation; 
  29.     CLLocationMatchInfo * fMatchInfo; 
  30.     double  fTrustedTimestamp; 
  1. @class NSData; 
  2.  
  3. @interface CLLocationMatchInfo : NSObject <NSCopying, NSSecureCoding> { 
  4.  
  5.     id _internal; 
  6. @property (nonatomic,readonly) long long matchQuality; 
  7. @property (nonatomic,readonly) CLLocationCoordinate2D matchCoordinate; 
  8. @property (nonatomic,readonly) double matchCourse; 
  9. @property (nonatomic,readonly) int matchFormOfWay; 
  10. @property (nonatomic,readonly) int matchRoadClass; 
  11. @property (getter=isMatchShifted,nonatomic,readonly) BOOL matchShifted; 
  12. @property (nonatomic,copy,readonly) NSData * matchDataArray; 

參考資料

[1]

用代碼判斷 iOS 系統(tǒng)是否越獄的方法: https://www.huaweicloud.com/articles/7c6b8027253c4a97196d359840f638d9.html

[2]

iOS 防黑產(chǎn)虛假定位檢測(cè)技術(shù): https://cloud.tencent.com/developer/article/1800531

[3]

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

[4]

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

[5]

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

[6]

_internal 實(shí)例對(duì)象的官方定義: https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/CoreLocation.framework/CLLocationInternal.h

 

責(zé)任編輯:武曉燕 來源: Swift社區(qū)
相關(guān)推薦

2018-03-13 15:33:14

虛擬化備份虛擬機(jī)

2010-01-13 10:53:51

Web前端工程師定位

2017-09-18 15:14:43

2017-11-29 14:42:28

虛擬化深度解密

2010-12-06 14:37:27

服務(wù)器虛擬化

2024-09-11 16:49:55

2014-07-17 14:51:52

2018-07-25 14:50:41

服務(wù)器虛擬化方案

2014-04-24 10:41:39

桌面虛擬化安全

2011-08-16 16:17:10

2013-11-27 09:38:31

云計(jì)算虛擬化

2025-02-21 15:25:54

虛擬線程輕量級(jí)

2018-04-02 19:30:43

人臉識(shí)別功能互聯(lián)網(wǎng)行業(yè)認(rèn)知度

2015-06-18 10:33:02

iOS粘性動(dòng)畫

2017-11-13 15:46:07

2013-04-01 13:19:43

iOS定位與坐標(biāo)算法

2018-03-13 09:53:14

人臉識(shí)別功能互聯(lián)、認(rèn)知度

2013-07-22 16:35:20

桌面虛擬化

2015-06-24 10:06:09

iOS 9適配后臺(tái)

2023-02-03 17:55:20

數(shù)據(jù)治理數(shù)據(jù)湖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久精品成人一区 | 欧洲视频一区二区 | 亚洲有码转帖 | 久久男人天堂 | 久久中文视频 | 久久国产精品一区二区三区 | 97色在线观看免费视频 | 色偷偷888欧美精品久久久 | 欧美精品一区二区三区四区 | 国产精品99久久久久久久vr | 91成人精品视频 | 翔田千里一区二区 | 欧美一区2区三区4区公司 | 一区二区三区不卡视频 | 大吊一区二区 | 日韩一区二区三区四区五区六区 | 日韩在线免费视频 | 午夜精品一区二区三区三上悠亚 | 欧美综合一区 | 欧美一区不卡 | 不卡一二三区 | 国产精品免费一区二区 | 少妇无套高潮一二三区 | 欧美在线一二三 | 亚洲一区免费 | 韩日精品一区 | 日本国产精品视频 | 99精品热视频 | 国产一二三视频在线观看 | 中文字幕在线视频观看 | 国产精品成人国产乱一区 | 欧美专区在线 | 男女下面一进一出网站 | 欧美视频二区 | 一区二区三区四区在线免费观看 | 断背山在线观看 | 国产一在线观看 | 欧美不卡| 狠狠操在线 | 免费国产视频在线观看 | 祝你幸福电影在线观看 |