Detect or Prevent If User Uses Fake Location

Preventing iOS/Android users from faking their GPS location

There is pretty much no way to validate the correctness of your GPS readings. However, there are workarounds you could use to detect possible spoofing:

First, you can detect if they Mock Location setting is on (which is commonly used by GPS faking apps). To do so, lookup Settings.Secure.ALLOW_MOCK_LOCATION) setting and check if it's enabled or not. Then check which apps have that permission (namely android.permission.ACCESS_MOCK_LOCATION). If there are apps present that use that permission and that setting is on, there is a high change they may be faking user's location.

You could also try to use Location.isFromMockProvider, although I am not sure how accurate the result is. The function returns true if the location you're checking has been acquired through a GPS faking app.

Disable / Check for Mock Location (prevent gps spoofing)

I have done some investigation and sharing my results here,this may be useful for others.

First, we can check whether MockSetting option is turned ON

public static boolean isMockSettingsON(Context context) {
// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else
return true;
}

Second, we can check whether are there other apps in the device, which are using android.permission.ACCESS_MOCK_LOCATION (Location Spoofing Apps)

public static boolean areThereMockPermissionApps(Context context) {
int count = 0;

PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages =
pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo applicationInfo : packages) {
try {
PackageInfo packageInfo = pm.getPackageInfo(applicationInfo.packageName,
PackageManager.GET_PERMISSIONS);

// Get Permissions
String[] requestedPermissions = packageInfo.requestedPermissions;

if (requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
if (requestedPermissions[i]
.equals("android.permission.ACCESS_MOCK_LOCATION")
&& !applicationInfo.packageName.equals(context.getPackageName())) {
count++;
}
}
}
} catch (NameNotFoundException e) {
Log.e("Got exception " , e.getMessage());
}
}

if (count > 0)
return true;
return false;
}

If both above methods, first and second are true, then there are good chances that location may be spoofed or fake.

Now, spoofing can be avoided by using Location Manager's API.

We can remove the test provider before requesting the location updates from both the providers (Network and GPS)

LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);

try {
Log.d(TAG ,"Removing Test providers")
lm.removeTestProvider(LocationManager.GPS_PROVIDER);
} catch (IllegalArgumentException error) {
Log.d(TAG,"Got exception in removing test provider");
}

lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener);

I have seen that removeTestProvider(~) works very well over Jelly Bean and onwards version. This API appeared to be unreliable till Ice Cream Sandwich.

Flutter Update:
Use Geolocator and check Position object's isMocked property.

How to prevent the detection of fake GPS?

The calls

invoke-virtual {p1}, Landroid/location/Location;->isFromMockProvider()Z
move-result v1

returns 1 (true) if a mock provider is used and 0 otherwise. The result is stored in v1.

Later the value is used for a conditional branch in

if-eqz v1, :cond_1e   // if v1==0 GOTO cond_1e

So only if there is no mock provider used (v1=0) it jumps to a special code part. Otherwise it continues with a code part that handles the mock location which is most likely what you don't want.

So you have to tweak that check and for doing so you have two possibilities:

  1. Overwrite v1 with 0 before the check, e.g. via the command const/4 v1, 0x0
  2. Replace the conditional branch if-eqz v1, :cond_1e with a non-conditional goto :cond_1e so it doesn't matter what value v1 has.

How to detect mock location in flutter for ios and android

you can use TrustLocation

permissions:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

usage :

import 'package:trust_location/trust_location.dart';

/* Assuming in an async function */
/// query the current location.
LatLongPosition position = await TrustLocation.getLatLong;

/// check mock location on Android device.
bool isMockLocation = await TrustLocation.isMockLocation;

using steam:

// input seconds into parameter for getting location with repeating by timer.
// this example set to 5 seconds.
TrustLocation.start(5);

/// the stream getter where others can listen to.
TrustLocation.onChange.listen((values) =>
print('${values.latitude} ${values.longitude} ${values.isMockLocation}')
);

/// stop repeating by timer
TrustLocation.stop();

Example:

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:trust_location/trust_location.dart';

import 'package:location_permissions/location_permissions.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
String _latitude;
String _longitude;
bool _isMockLocation;

/// initialize state.
@override
void initState() {
super.initState();
requestLocationPermission();
// input seconds into parameter for getting location with repeating by timer.
// this example set to 5 seconds.
TrustLocation.start(5);
getLocation();
}

/// get location method, use a try/catch PlatformException.
Future<void> getLocation() async {
try {
TrustLocation.onChange.listen((values) => setState(() {
_latitude = values.latitude;
_longitude = values.longitude;
_isMockLocation = values.isMockLocation;
}));
} on PlatformException catch (e) {
print('PlatformException $e');
}
}

/// request location permission at runtime.
void requestLocationPermission() async {
PermissionStatus permission =
await LocationPermissions().requestPermissions();
print('permissions: $permission');
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Trust Location Plugin'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Column(
children: <Widget>[
Text('Mock Location: $_isMockLocation'),
Text('Latitude: $_latitude, Longitude: $_longitude'),
],
)),
),
),
);
}
}

for more information you can see https://pub.dev/packages/trust_location

github link : https://github.com/wongpiwat/trust-location



Related Topics



Leave a reply



Submit