iOS Virtual Location Principles and Prevention#
Background#
When it comes to virtual location, the common impression is often associated with cloning software on Android or even the built-in location spoofing (the author has previously used the location spoofing feature on the ZUK Z2 system). It is generally believed that virtual location on iOS is more challenging. Before conducting research, I also held this belief. The known method for virtual location was to use Xcode to add a GPX file and edit the latitude and longitude to achieve virtual location. However, this operation can only be performed by those familiar with iOS development and requires a Mac computer, which further reinforced my impression that virtual location on iOS is quite difficult.
However, after conducting research, I found that virtual location on iOS is not as difficult as it seems, and in fact, it can be simpler than on Android. Below, I will introduce several methods for virtual location on iOS.
Several Methods and Principles of Virtual Location#
After my research, I found that there are roughly four methods for virtual location on iOS:
- Using Xcode to virtualize location through a GPX file
- Using the virtual location feature in iTunes Assistant to directly virtualize location
- Using external devices, such as connecting via Bluetooth to send virtual location data
- Virtualizing location through hooking location methods on jailbroken devices
Let’s analyze and practice each method one by one:
Using Xcode to Virtualize Location through a GPX File#
Using Xcode to virtualize location through a GPX file is generally familiar to iOS developers. The steps are as follows:
Create a new iOS project, then add a file and select to create a GPX file.

Edit the content to change lat and lon to the desired simulated latitude and longitude, as follows:
<wpt lat="31.2416" lon="121.333">
<name>Shanghai</name>
</wpt>
</gpx>
Then select Product -> Scheme -> Edit Scheme, select the Options tab, check Allow Location Simulation, and then run to virtualize the location.

Note: Generally, when using Xcode to run virtual location, after stopping the run, the latitude and longitude will revert to the original. However, if the project is running and the data cable is directly unplugged (while running), the phone's latitude and longitude will remain as the simulated coordinates. To restore it, you need to restart the phone or wait 2 to 5 days for it to automatically recover.
Principle: It calls the com.apple.dt.simulatelocation service in the iOS device. com.apple.dt.simulatelocation is a debugging feature provided by Apple for simulating GPS locations on devices since Xcode 6 and iOS 8.0. The principle is to obtain the device handle via USB, then start the service ("com.apple.dt.simulatelocation") within the device, and simulate the location using fixed coordinates or a GPX file.
Using the Virtual Location Feature in iTunes Assistant to Directly Virtualize Location#
This method is the simplest. I was previously unaware of this method. Download iTunes Assistant, open it, connect the phone to the computer, and select the Toolbox tab under Virtual Location.

Then enter the location you want to set and click to modify the location.

Note: This method of virtual location is indeed simple. As of now, after my attempts, I found that both DingTalk and Enterprise WeChat have not detected this method.
Principle: It activates the com.apple.dt.simulatelocation service through the service module of libimobiledevice, thus achieving location simulation without using Xcode. libimobiledevice is an open-source, cross-platform library for calling iOS protocols.
Virtualizing Location by Sending Virtual Location Data through External Devices#
I had no prior knowledge of this method of sending virtual location data through external devices. I must say, it is truly impressive, showcasing the infinite wisdom of the people, with the representative being the Displacement Elf. I did not purchase external devices, so I could not try it, but I can attach a video for reference:
Video link: https://haokan.baidu.com/v?pd=wisenatural&vid=17675944846390412165
Principle: Through MFi (Made For iOS) certified manufacturers, one can obtain the MFI Accessory Interface Specification document, which provides many hidden features, including time communication, music data communication, location functions, etc. The use of location functions only requires sending corresponding location data according to the protocol format as specified in the document. MFI Accessory Interface Specification can be found at: https://usermanual.wiki/Document/MFiAccessoryInterfaceSpecificationR18NoRestriction.1631705096.pdf
Searching for Location in the document will reveal location-related information, as shown below:

Virtualizing Location through Hooking Location Methods on Jailbroken Devices#
Virtual location on jailbroken devices involves using jailbreak plugins that have virtual location capabilities. In god mode, jailbreak plugins can freely intercept system functions. For example: GPS Location Manager, which can manage the GPS location of each iOS application..
Principle: After jailbreaking, it injects a library that hooks the location delegate methods in CLLocationManager, thereby tampering with the normal location information.
In summary:

Detection of Various Methods of Virtual Location#
As a developer, knowing the methods of virtual location is not enough; it is also necessary to understand how to address these virtual location methods. This is especially important for the development of OA applications and game applications. Let’s take a step-by-step look:
Detection of Virtual Location Using Xcode through GPX Files and Using the Virtual Location Feature in iTunes Assistant#
The ultimate principle of virtual location using Xcode through GPX and using iTunes Assistant is the same; both achieve virtual location by calling the com.apple.simulatelocation service.
I have summarized that there are roughly two verification methods mentioned online:
- Judging based on characteristic values
- Location accuracy: The accuracy of virtual location coordinates is not as high as that of real location, so it can be judged by the accuracy of the latitude and longitude.
- Location altitude and altitude accuracy: The altitude value of virtual location is 0, and the vertical accuracy is -1; thus, these two values can be used for judgment.
- Number of callback calls for location: Virtual location callbacks will only be called once, while real location callbacks will be triggered multiple times; hence, the number of triggers can be used for judgment.
- Function response time: The response of virtual location returns immediately, while real location does not; thus, response time can be used for judgment.
- Judging based on the private property
_internalofCLLocationwhich contains the type.
The above is the detection scheme summarized from the internet. Now let’s practice to see if the facts align with the descriptions. I will use the method of simulating latitude and longitude with iTunes Assistant.
Strongly Note: Using third-party map location and system location will also affect the following methods!!! I learned this the hard way.
Judging Based on Characteristic Values#
-
Location Accuracy
To obtain the accuracy of latitude and longitude, do not use "%f" for direct formatting, as the default formatting string "%f" retains up to six decimal places, making it impossible to compare differences.
The code is as follows:/// Location accuracy of latitude and longitude /// @param location Location Item - (void)testLocationAccuracy:(CLLocation *)location { NSString *longitudeStr = [NSString stringWithFormat:@"%@", @(location.coordinate.longitude)]; // NSString *longitudeStr = [[NSDecimalNumber numberWithDouble: location.coordinate.longitude] stringValue]; // This method retrieves 17 digits NSString *lastPartLongitudeStr = [[longitudeStr componentsSeparatedByString:@"."] lastObject]; NSString *latitudeStr = [NSString stringWithFormat:@"%@", @(location.coordinate.latitude)]; NSString *lastPartLatitudeStr = [[latitudeStr componentsSeparatedByString:@"."] lastObject]; NSLog(@"Location accuracy longitude digits: %d, latitude digits: %d", lastPartLongitudeStr.length, lastPartLatitudeStr.length); }When using normal location, the result is as follows:
Location accuracy longitude digits: 13, latitude digits: 14When using iTunes Assistant to search for
Hongqiao Railway Station Subway Station, the automatically located coordinates are 6 digits, and the input box can input up to 8 decimal places. After enabling virtual location, the result is as follows:Location accuracy longitude digits: 13, latitude digits: 14I tested this for a long time, and due to the issue of decimal precision, I tried several methods. The final conclusion is that this method cannot be used for judgment. Although iTunes Assistant has a limit on the number of digits for latitude and longitude, the final coordinates obtained do not match the actual location, and due to decimal precision issues, accurate judgment is not possible. Therefore, this method does not work.
-
Location Altitude and Altitude Accuracy
UsealtitudeandverticalAccuracyto judge. Thealtitudeproperty of CLLocation indicates the altitude. TheverticalAccuracyproperty is used to judge the accuracy of the altitude. The altitude value may have an error of the size ofverticalAccuracy, and whenverticalAccuracyis negative, it indicates that the altitude cannot be obtained.The code is as follows:
/// Location altitude and vertical accuracy /// @param location Location Item - (void)testLocationAltitudeAccuracy:(CLLocation *)location { NSLog(@"Altitude: %f", location.altitude); NSLog(@"Vertical accuracy: %f", location.verticalAccuracy); }When using normal location, the result is as follows:
Altitude: 9.224902 Vertical accuracy: 16.078646When using iTunes Assistant to enable location, the result is as follows:
Altitude: 0.000000 Vertical accuracy: -1.000000From the above, it can be seen that the altitude and vertical accuracy of normal location and simulated location are different, thus it can be used to distinguish. However, whether places with a real altitude of 0 will be mistakenly identified needs to be considered and tested.
-
Number of Callback Calls for Location
I declared a property for the number of callback calls in the location class, initialized it to 0 when calling the method to start location, and incremented it by 1 each time the callback succeeds, printing the result.
The code is roughly as follows:@TestLocationManager() @property (nonatomic, assign) NSInteger callbackCount; @end @implementation TestLocationManager() - (void)startLocation { self.callbackCount = 0; } - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error { self.callbackCount += 1; NSLog(@"Baidu Map single location callback count: %ld", self.callbackCount); } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { self.callbackCount += 1; NSLog(@"System location single callback count: %ld", self.callbackCount); } @endWhen using normal location, the result is as follows:
Baidu Map single location callback count: 1 System location single callback count: 1 System location single callback count: 2When using iTunes Assistant to simulate location, the result is as follows:
Baidu Map single location callback count: 1 System location single callback count: 1The results I tested showed that when using third-party map location, there is no difference in callback counts between virtual location and normal location, thus this method does not work when using third-party map location. When using system location, the callback counts for virtual location and normal location are different, therefore theoretically, this method can be used to distinguish when using system location; however, the accuracy of this judgment is not high, as system location may occasionally only trigger once. Moreover, if using callback to judge, how to distinguish the end of the callback is a problem. For example, I wrote a delay of 0.5s to check the callback count; hence, it is recommended to use this as a reference but not as a judgment basis.
-
Function Response Time
I declared a property for the start time in the location class, and when calling the method to start location, I set it, then in the callback for the location result, I obtained the end time, and the time difference is the response time.
The code is roughly as follows:@TestLocationManager() @property (nonatomic, strong) NSDate *locateBeginDate; @end @implementation TestLocationManager() - (void)startLocation { self.locateBeginDate = [NSDate date]; } - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error { NSDate *locateEndDate = [NSDate date]; NSTimeInterval gap = [locateEndDate timeIntervalSinceDate: self.locateBeginDate]; NSLog(@"Single location time: %lf", gap); } @endWhen using normal location, the result is as follows:
Single location time: 0.332915When using iTunes Assistant to simulate location, the result is as follows:
Single location time: 0.298709Based on my testing results, there is no significant difference in the interval of location when the network is good, thus this method does not work.
Judging Based on the Private Property _internal of CLLocation#
Referencing iOS Anti-Fraud False Location Detection Technology, according to the article, the CLLocation object has a private property type, which has different values under different location sources.
| Value | Meaning | Remarks |
|---|---|---|
| 0 | unknown | Location data generated by the application, generally generated by virtual location programs on jailbroken devices. |
| 1 | gps | Location data generated by GPS |
| 2 | nmea | |
| 3 | accessory | Location data generated by external devices such as Bluetooth |
| 4 | wifi | Location data generated by WIFI |
| 5 | skyhook | Location data generated by WIFI |
| 6 | cell | Location data generated by mobile base stations |
| 7 | lac | Location data generated by LAC |
| 8 | mcc | |
| 9 | gpscoarse | |
| 10 | pipeline | |
| 11 | max |
My verification steps are as follows:
In the successful location callback, check the type property of CLLocation.
- (void)testLocationIntervalProperty:(CLLocation *)location {
NSString *type = [location valueForKey:@"type"];
NSLog(@"Location source type: %@", type);
return;
// If you want to see all properties of location, you can use the following method
unsigned int intervalCount;
objc_property_t *properties = class_copyPropertyList([location class],
&intervalCount);
for (unsigned int y = 0; y < intervalCount; y++) {
objc_property_t property = properties[y];
NSString *propertyName = [[NSString alloc] initWithCString:
property_getName(property)];
if ([propertyName containsString:@"type"]) {
id propetyValue = [location valueForKey:propertyName];
NSLog(@"Property name: %@, Property info: %@", propertyName, propetyValue);
}
else {
// NSLog(@"Property name: %@", propertyName);
}
}
}
When using normal location, with Wi-Fi on, the result is 4; with Wi-Fi off, the result is 6; the result is as follows:
// With Wi-Fi on, the result is 4; with Wi-Fi off, the result is 6;
// However, when the network is poor, the result is 1;
Location source type: 4
When using virtual location, the result is as follows:
Location source type: 1
However, when using third-party map location, regardless of whether it is virtual location or normal location, the result is as follows:
Location source type: 0
My comparison results are as follows: When using system location, under normal network conditions, the results for virtual location and normal location differ, but under poor network conditions, the location source type is 1 for both, thus making it difficult to distinguish. When using third-party system location, the results for virtual location and normal location are the same, making it impossible to distinguish.
Detection of Virtual Location by Sending Virtual Location Data through External Devices#
I have not practiced this virtual location method with devices, but based on online information, it can be inferred that external devices connect via Bluetooth to the phone. Therefore, I speculate that it can also be judged based on the private property _internal of CLLocation. Since the definition of type=3 is location data generated by Bluetooth and other external devices, this virtual location should be distinguishable by this type value.
Detection of Virtual Location through Hooking Location Methods on Jailbroken Devices#
Currently, I have researched two methods for this. One is to directly target jailbroken devices and prompt if the iPhone is jailbroken to avoid it; the other is to check whether the delegate methods have been hooked and whether the implementation of the hooked methods is in the app.
Method 1: Determine if the device is jailbroken, refer to Methods to Determine if iOS System is Jailbroken
There are several methods to determine if a device is jailbroken:
-
Check for common jailbreak files, maintain a list of common jailbreak files, and if any exist, it indicates that the device is jailbroken.
/// Determine if the device is jailbroken based on a whitelist /// - Returns: true- jailbroken; false- not jailbroken class func isJailedDevice() -> Bool { let jailPaths = ["/Applications/Cydia.app", "/Library/MobileSubstrate/MobileSubstrate.dylib", "/bin/bash", "/usr/sbin/sshd", "/etc/apt"] var isJailDevice = false for item in jailPaths { if FileManager.default.fileExists(atPath: item) { isJailDevice = true break } } return isJailDevice } -
Determine if Cydia's URL Scheme can be opened to check if Cydia.app is installed.
/// Determine if the device is jailbroken based on whether Cydia scheme can be opened /// - Returns: true- jailbroken; false- not jailbroken class func isJailedDevice() -> Bool { let cydiaSchemeStr = "cydia://" if let url = URL(string: cydiaSchemeStr), UIApplication.shared.canOpenURL(url) { return true } else { return false } } -
Determine if all system applications can be read; jailbroken devices can read them, while non-jailbroken devices cannot.
/// Determine if the device is jailbroken based on whether all applications can be accessed /// - Returns: true- jailbroken; false- not jailbroken class func isJailedDevice() -> Bool { let appPathStr = "/User/Applications" if FileManager.default.fileExists(atPath: appPathStr) { do { let appList = try FileManager.default.contentsOfDirectory(atPath: appPathStr) if appList.count > 0 { return true } else { return false } } catch { return false } } else { return false } }
Method 2: Check whether the delegate methods have been hooked and whether the implementation of the hooked methods is in the app, refer to Exploration of Virtual Location Detection on iOS
The implementation of virtual location through injected dylib methods often utilizes Method Swizzling to hook the target function of the location method. The module where the new implementation of the method being replaced is located will not be the same as the module where the original implementation is located. For jailbreak plugins, the new implementation is usually in the dylib of the plugin itself; for dynamic library injection through IPA cracking, the new implementation is usually in the injected dylib. — from http://devliubo.com/2016/2016-12-23-iOS%E4%B8%8A%E8%99%9A%E6%8B%9F%E5%AE%9A%E4%BD%8D%E6%A3%80%E6%B5%8B%E7%9A%84%E6%8E%A2%E7%A9%B6.html
Practice:
The code is as follows:
#import <objc/runtime.h>
#import <dlfcn.h>
static void logMethodInfo(const char *className, const char *sel)
{
Dl_info info;
IMP imp = class_getMethodImplementation(objc_getClass(className),
sel_registerName(sel));
if(dladdr(imp,&info)) {
NSLog(@"method %s %s:", className, sel);
NSLog(@"dli_fname:%s",info.dli_fname);
NSLog(@"dli_sname:%s",info.dli_sname);
NSLog(@"dli_fbase:%p",info.dli_fbase);
NSLog(@"dli_saddr:%p",info.dli_saddr);
} else {
NSLog(@"error: can't find that symbol.");
}
}
For example, I verified using the following method. In my project, I performed Method Swizzling on layoutSubviews of UIView, while viewDidLayoutSubviews was not. The comparison is as follows:
- (void)testViewDidLayoutSubviews {
const char *className = object_getClassName([UIView new]);
SEL selector = @selector(viewDidLayoutSubviews);
const char *selName = sel_getName(selector);
logMethodInfo(className, selName);
}
- (void)testLayoutSubviews {
const char *className = object_getClassName([UIView new]);
SEL selector = @selector(layoutSubviews);
const char *selName = sel_getName(selector);
logMethodInfo(className, selName);
}
The comparison results are as follows:


From the comparison results above, it can be seen that the dli_fname of the method that has not used Method Swizzling is /usr/lib/libobjc.A.dylib, and the dli_sname is _objc_msgForward; while the dli_fname of the method that has used Method Swizzling is /private/var/containers/Bundle/Application/0106942C-7D3F-45A9-BB1B-2C0FBD994744/xxx.app/xxx, and the dli_sname is -[UIView(MSCorner)ms_layoutSubviews]. It can be seen that from dli_sname, it can be determined whether the method has been hooked, and from dli_fname, it can be known whether the method's implementation is in the project's module. (I do not have a jailbroken phone or have done cracking injection, so if anyone is interested, you can verify it.)
Conclusion#
Based on my verification results, the altitude and altitude accuracy in the characteristic values can distinguish between using iTunes Assistant or Xcode for simulated location. The type can distinguish different location sources. For accuracy, I combine altitude, altitude accuracy, and type to make judgments.
I have written a detection code, and the repository address is as follows: https://github.com/mokong/DetectFakeLocation
The principle is: using swizzlemethod to hook the startUpdatingLocation method of CLLocationManager and the locationManager:didUpdateLocations: method of CLLocationManagerDelegate, then detect jailbreak status, altitude and altitude accuracy, and location type, and based on these aspects, determine whether it is virtual location.

References#
- iOS Virtual Location Monitoring
- Apple's Virtual Location Technology Principles and Detection
- Notes on Debugging Non-Jailbroken Virtual Location Plugins and Detection Schemes | B1nGzL Author
- iOS Anti-Fraud False Location Detection Technology
- Various Ways to Implement Virtual Location on iOS
- Research on Identifying Virtual Location on iOS
- Exploration of Virtual Location Detection on iOS