web-dev-qa-db-fra.com

Désactiver / Vérifier l’emplacement fictif (éviter l’usurpation gps)

Vous cherchez le meilleur moyen de prévenir/détecter l’usurpation GPS sur Android. Avez-vous des suggestions sur la manière dont cela est accompli et sur ce qui peut être fait pour l'arrêter? Je suppose que l'utilisateur doit activer les faux emplacements pour usurper le GPS. Si cela est fait, alors il peut usurper le GPS?

Je suppose que je devrais simplement détecter si les emplacements factices sont activés? D'autres suggestions?

81
Chrispix

J'ai fait quelques recherches et partage mes résultats ici, cela pourrait être utile pour d'autres.

Tout d'abord, nous pouvons vérifier si l'option MockSetting est activée

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;
}

Deuxièmement, nous pouvons vérifier s'il y a d'autres applications dans l'appareil, qui utilisent Android.permission.ACCESS_MOCK_LOCATION (Applications d'usurpation d'emplacement)

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;
}

Si les deux méthodes ci-dessus, première et seconde sont vraies, il y a de fortes chances pour que l'emplacement soit simulé ou falsifié.

Il est désormais possible d'éviter l'usurpation d'identité à l'aide de l'API de Location Manager.

Nous pouvons supprimer le fournisseur de test avant de demander les mises à jour d'emplacement des deux fournisseurs (réseau et 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);

J'ai vu que removeTestProvider (~) fonctionne très bien sur la version Jelly Bean et les versions suivantes. Cette API ne semblait pas fiable avant le sandwich à la crème glacée.

114
Jambaaz

Depuis l'API 18, l'objet Location a la méthode . IsFromMockProvider () afin que vous puissiez filtrer les faux emplacements.

Si vous souhaitez prendre en charge les versions antérieures à 18 ans, il est possible d'utiliser quelque chose comme ceci:

boolean isMock = false;
if (Android.os.Build.VERSION.SDK_INT >= 18) {
    isMock = location.isFromMockProvider();
} else {
    isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}
35
Fernando

Il semble que le seul moyen de le faire est d’empêcher l’endommagement de la localisation par MockLocations. L'inconvénient est que certains utilisateurs utilisent des appareils GPS Bluetooth pour obtenir un meilleur signal. Ils ne pourront pas utiliser l'application, car ils sont tenus d'utiliser l'emplacement fictif.

Pour ce faire, j'ai fait ce qui suit:

// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(getContentResolver(),
       Settings.Secure.ALLOW_MOCK_LOCATION).equals("0")) 
       return false; 
       else return true;
35
Chrispix

Je suis tombé sur ce fil quelques années plus tard. En 2016, la plupart des appareils Android auront un niveau d'API> = 18 et devront donc s'appuyer sur Location.isFromMockProvider () comme indiqué par - Fernando .

J'ai longuement expérimenté l'utilisation de faux/faux emplacements sur Android appareils et distributions. Malheureusement . IsFromMockProvider () n'est pas fiable à 100%. un moment, un faux emplacement ne sera pas qualifié de faux. Cela semble être dû à une logique de fusion interne erronée dans l'API Google Location.

J'ai écrit un article de blog détaillé à ce sujet , si vous voulez en savoir plus. Pour résumer, si vous vous abonnez aux mises à jour de localisation à partir de l’API de localisation, activez une fausse application GPS et imprimez le résultat de chaque Location.toString () sur la console. voir quelque chose comme ça:

enter image description here

Notez que, dans le flux de mises à jour d'emplacement, un emplacement a les mêmes coordonnées que les autres, mais n'est pas marqué comme une maquette et a une précision d'emplacement beaucoup plus faible.

Pour remédier à ce problème, j'ai écrit une classe d'utilitaires qui will supprime de manière fiable les emplacements factices dans toutes les versions modernes Android (niveaux d'API 15 et supérieurs):

LocationAssistant - Mises à jour de localisation sans tracas sur Android

Fondamentalement, il "se méfie" des emplacements non simulés qui se trouvent à moins de 1 km du dernier emplacement simulé connu et les qualifie également de simulacres. Il le fait jusqu’à ce qu’un nombre significatif d’emplacements non simulés soient arrivés. L'assistant de localisation peut non seulement rejeter les emplacements fictifs, mais vous libère également de la plupart des tracas liés à la configuration et à l'abonnement aux mises à jour d'emplacement.

Pour recevoir uniquement les mises à jour d'emplacement réelles (c.-à-d. Supprimer les modèles), utilisez-le comme suit:

public class MyActivity extends Activity implements LocationAssistant.Listener {

    private LocationAssistant assistant;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // You can specify a different accuracy and interval here.
        // The last parameter (allowMockLocations) must be 'false' to suppress mock locations.  
        assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        assistant.start();
    }

    @Override
    protected void onPause() {
        assistant.stop();
        super.onPause();
    }

    @Override
    public void onNewLocationAvailable(Location location) {
        // No mock locations arriving here
    }

    ...
}

onNewLocationAvailable() ne sera maintenant appelé qu'avec des informations de localisation réelles. Vous devez implémenter d'autres méthodes d'écoute, mais dans le contexte de votre question (comment empêcher l'usurpation GPS), il s'agit en gros de cela.

Bien sûr, avec un système d’exploitation enraciné, vous pouvez toujours trouver des moyens de masquer les informations de localisation qui sont impossibles à détecter par les applications normales.

23
KlaasNotFound

Si vous connaissez l'emplacement général des tours de téléphonie cellulaire, vous pouvez vérifier si la tour de téléphonie cellulaire actuelle correspond à l'emplacement indiqué (à l'intérieur d'une marge d'erreur de quelque chose de grand, par exemple 10 km ou plus).

Par exemple, si votre application déverrouille des fonctionnalités uniquement si l'utilisateur se trouve dans un emplacement spécifique (votre magasin, par exemple), vous pouvez vérifier le GPS ainsi que les tours de téléphonie mobile. À l'heure actuelle, aucune application d'usurpation d'identité GPS ne permet également d'usurper les tours de téléphonie cellulaire, ce qui vous permet de voir si quelqu'un à travers le pays essaie simplement de se faire passer pour vos fonctions spéciales (je pense à l'application Disney Mobile Magic, par exemple).

C’est ainsi que l’application Llama gère l’emplacement par défaut, car la vérification des identifiants de tour de téléphonie cellulaire nécessite beaucoup moins de batterie que le GPS. Cela n'est pas utile pour des emplacements très spécifiques, mais si la maison et le lieu de travail se trouvent à plusieurs kilomètres de distance, il est très facile de faire la distinction entre les deux emplacements.

Bien entendu, cela nécessiterait que l'utilisateur ait un signal de cellule. Et vous auriez à connaître tous les identifiants de tours de téléphonie cellulaire de la région - sur tous les fournisseurs de réseau - sinon vous courriez le risque d'un faux négatif.

6
Stephen Schrauger

essayez ce code très simple et utile

  public boolean isMockLocationEnabled() {
        boolean isMockLocation = false;
        try {
            //if Marshmallow
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                AppOpsManager opsManager = (AppOpsManager) getApplicationContext().getSystemService(Context.APP_OPS_SERVICE);
                isMockLocation = (opsManager.checkOp(AppOpsManager.OPSTR_MOCK_LOCATION, Android.os.Process.myUid(), BuildConfig.APPLICATION_ID)== AppOpsManager.MODE_ALLOWED);
            } else {
                // in Marshmallow this will always return true
                isMockLocation = !Android.provider.Settings.Secure.getString(getApplicationContext().getContentResolver(), "mock_location").equals("0");
            }
        } catch (Exception e) {
            return isMockLocation;
        }
        return isMockLocation;
    }
3
Mostafa Pirhayati

Ce script fonctionne pour toutes les versions de Android et je le trouve après de nombreuses recherches

LocationManager locMan;
    String[] mockProviders = {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER};

    try {
        locMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        for (String p : mockProviders) {
            if (p.contentEquals(LocationManager.GPS_PROVIDER))
                locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
                        Android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_HIGH);
            else
                locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
                        Android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_LOW);

            locMan.setTestProviderEnabled(p, true);
            locMan.setTestProviderStatus(p, Android.location.LocationProvider.AVAILABLE, Bundle.EMPTY,
                    Java.lang.System.currentTimeMillis());
        }
    } catch (Exception ignored) {
        // here you should show dialog which is mean the mock location is not enable
    }
2
ali

Vous pouvez ajouter une vérification supplémentaire sur la base de la triangulation de la tour cellulaire ou des informations sur les points d'accès Wifi à l'aide de API de géolocalisation de Google Maps

Le moyen le plus simple d’obtenir des informations sur CellTowers

final TelephonyManager telephonyManager = (TelephonyManager) appContext.getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = telephonyManager.getNetworkOperator();
int mcc = Integer.parseInt(networkOperator.substring(0, 3));
int mnc = Integer.parseInt(networkOperator.substring(3));
String operatorName = telephonyManager.getNetworkOperatorName();
final GsmCellLocation cellLocation = (GsmCellLocation) telephonyManager.getCellLocation();
int cid = cellLocation.getCid();
int lac = cellLocation.getLac();

Vous pouvez comparer vos résultats avec site

Pour obtenir des informations sur les points d'accès Wifi

final WifiManager mWifiManager = (WifiManager) appContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

if (mWifiManager != null && mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {

    // register WiFi scan results receiver
    IntentFilter filter = new IntentFilter();
    filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                List<ScanResult> results = mWifiManager.getScanResults();//<-result list
            }
        };

        appContext.registerReceiver(broadcastReceiver, filter);

        // start WiFi Scan
        mWifiManager.startScan();
}
1
yoAlex5