Vous cherchez à trouver le meilleur moyen de prévenir / détecter l'usurpation GPS sur Android. Avez-vous des suggestions sur la façon dont cela est accompli et que peut-on faire pour y mettre fin? Je suppose que l'utilisateur doit activer les emplacements fictifs pour usurper le GPS, si cela est fait, alors ils peuvent usurper le GPS?
Je suppose que je devrais simplement détecter si les emplacements simulés sont activés? D'autres suggestions?
Réponses:
J'ai fait quelques recherches et partage mes résultats ici, cela peut ê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 existe d'autres applications dans l'appareil qui utilisent
android.permission.ACCESS_MOCK_LOCATION
(Applications de spoofing de localisation)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, la première et la deuxième sont vraies, il y a de bonnes chances que l'emplacement soit usurpé ou faux.
Désormais, l'usurpation d'identité peut être évitée en utilisant l'API de Location Manager.
Nous pouvons supprimer le fournisseur de test avant de demander les mises à jour de localisation aux 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 Jelly Bean et les versions ultérieures. Cette API semblait peu fiable jusqu'à Ice Cream Sandwich.
la source
android.permission.ACCESS_MOCK_LOCATION
autorisationremoveTestProvider
de fonctionner, ce qui, à mon avis, est le plus gros inconvénient.isMockSettingsON()
,Location.isFromMockProvider()
etareThereMockPermissionApps()
avec une liste noire des applications. Il existe de nombreuses applications système préinstallées avecACCESS_MOCK_LOCATION
autorisation, par exemple sur les appareils HTC et Samsung. Une liste blanche de toutes les applications légitimes serait préférable, mais une liste noire des applications d'usurpation de localisation les plus populaires fonctionnait bien dans mon cas. Et j'ai également vérifié si l'appareil était enraciné.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, 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"); }
la source
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
Il semble que le seul moyen de le faire est d'empêcher l'usurpation d'emplacement d'empêcher les 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 doivent utiliser les emplacements simulés.
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;
la source
return !x
place deif(x) return false; else return true
.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 devraient donc s'appuyer sur Location.isFromMockProvider () comme l'a souligné Fernando .
J'ai beaucoup expérimenté avec des emplacements faux / simulés sur différents appareils et distributions Android. Malheureusement .isFromMockProvider () n'est pas fiable à 100%. De temps en temps, 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 Location, puis activez une fausse application GPS et imprimez le résultat de chaque Location.toString () sur la console, vous verrez quelque chose comme ceci:
Remarquez comment, dans le flux de mises à jour d'emplacement, un emplacement a les mêmes coordonnées que les autres, mais n'est pas signalé comme une simulation et a une précision de localisation beaucoup plus faible.
Pour remédier à ce problème, je l' ai écrit une classe utilitaire qui va Suppress les positions fictives de manière fiable dans toutes les versions Android modernes (niveau API 15 et plus):
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 fictif connu et les qualifie également de simulacre. Il le fait jusqu'à ce qu'un nombre significatif d'emplacements non simulés soit arrivé. L' assistant de localisation peut non seulement rejeter des emplacements fictifs, mais également vous soulager de la plupart des tracas liés à la configuration et à l'abonnement aux mises à jour de localisation.
Pour recevoir uniquement des mises à jour de localisation réelle (c'est-à-dire supprimer les simulations), 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 désormais invoqué qu'avec des informations de localisation réelles. Il y a d'autres méthodes d'écoute que vous devez implémenter, mais dans le contexte de votre question (comment empêcher l'usurpation GPS), c'est essentiellement cela.Bien sûr, avec un système d'exploitation enraciné, vous pouvez toujours trouver des moyens d'usurper les informations de localisation qui sont impossibles à détecter pour les applications normales.
la source
Si vous connaissez l'emplacement général des tours cellulaires, vous pouvez vérifier si la tour cellulaire actuelle correspond à l'emplacement indiqué (dans une marge d'erreur de quelque chose de grand, comme 10 miles ou plus).
Par exemple, si votre application ne déverrouille des fonctionnalités que 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 cellulaire. Actuellement, aucune application d'usurpation de GPS n'utilise également les tours de téléphonie cellulaire, vous pouvez donc voir si quelqu'un à travers le pays essaie simplement de se frayer un chemin dans vos fonctionnalités 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 des tours cellulaires est beaucoup moins gourmande en batterie que le GPS. Ce n'est pas utile pour des endroits très spécifiques, mais si la maison et le travail sont à plusieurs kilomètres, il peut très facilement faire la distinction entre les deux emplacements généraux.
Bien entendu, cela exigerait que l'utilisateur ait un signal de cellule. Et vous devrez connaître tous les identifiants des tours cellulaires de la région - sur tous les fournisseurs de réseau - ou vous courriez le risque d'un faux négatif.
la source
essayez ce code, c'est 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; }
la source
Ce script fonctionne pour toutes les versions d'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 }
la source
Vous pouvez ajouter une vérification supplémentaire en fonction de la triangulation de la tour cellulaire ou des informations sur les points d'accès Wifi en utilisant 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(); }
la source