Buscando encontrar la mejor manera de prevenir / detectar la suplantación de GPS en Android. ¿Alguna sugerencia sobre cómo se logra esto y qué se puede hacer para detenerlo? Supongo que el usuario tiene que activar las ubicaciones simuladas para falsificar el GPS, si esto se hace, ¿pueden falsificar el GPS?
Supongo que tendría que detectar si las ubicaciones simuladas están habilitadas. ¿Cualquier otra sugerencia?
Respuestas:
He hecho algunas investigaciones y comparto mis resultados aquí, esto puede ser útil para otros.
Primero, podemos verificar si la opción MockSetting está encendida
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; }
En segundo lugar, podemos verificar si hay otras aplicaciones en el dispositivo que estén usando
android.permission.ACCESS_MOCK_LOCATION
(Aplicaciones de suplantación de ubicación)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 los dos métodos anteriores, el primero y el segundo, son verdaderos, entonces hay buenas posibilidades de que la ubicación sea falsa o falsa.
Ahora, la suplantación de identidad se puede evitar utilizando la API de Location Manager.
Podemos eliminar el proveedor de prueba antes de solicitar las actualizaciones de ubicación de ambos proveedores (Red y 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);
He visto que removeTestProvider (~) funciona muy bien sobre Jelly Bean y versiones posteriores. Esta API parecía no ser confiable hasta Ice Cream Sandwich.
fuente
android.permission.ACCESS_MOCK_LOCATION
permiso pararemoveTestProvider
funcionar, lo que creo que es la mayor desventaja.isMockSettingsON()
,Location.isFromMockProvider()
yareThereMockPermissionApps()
con una lista de negro de aplicaciones. Hay muchas aplicaciones de sistema preinstaladas conACCESS_MOCK_LOCATION
permiso, por ejemplo, en dispositivos HTC y Samsung. Sería mejor una lista blanca de todas las aplicaciones legítimas, pero una lista negra de las aplicaciones de suplantación de ubicación más populares funcionó bien en mi caso. Y también verifiqué si el dispositivo estaba rooteado.Desde API 18, el objeto Location tiene el método .isFromMockProvider () para que pueda filtrar ubicaciones falsas.
Si desea admitir versiones anteriores a la 18, es posible usar algo como esto:
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"); }
fuente
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
Parece que la única forma de hacer esto es evitar que la suplantación de ubicación evite MockLocations. El lado negativo es que hay algunos usuarios que usan dispositivos GPS Bluetooth para obtener una mejor señal, no podrán usar la aplicación ya que están obligados a usar las ubicaciones simuladas.
Para hacer esto, hice lo siguiente:
// 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;
fuente
return !x
lugar deif(x) return false; else return true
.Me encontré con este hilo un par de años después. En 2016, la mayoría de los dispositivos Android tendrán un nivel de API> = 18 y, por lo tanto, deberían confiar en Location.isFromMockProvider () como lo señaló Fernando .
Experimenté extensamente con ubicaciones falsas / simuladas en diferentes dispositivos y distribuciones de Android. Desafortunadamente .isFromMockProvider () no es 100% confiable. De vez en cuando, una ubicación falsa no se etiquetará como simulada . Esto parece deberse a una lógica de fusión interna errónea en la API de ubicación de Google.
Escribí una publicación de blog detallada sobre esto , si desea obtener más información. En resumen, si se suscribe a las actualizaciones de ubicación desde la API de ubicación, luego enciende una aplicación GPS falsa e imprime el resultado de cada Location.toString () en la consola, verá algo como esto:
Observe cómo, en el flujo de actualizaciones de ubicación, una ubicación tiene las mismas coordenadas que las demás, pero no está marcada como una simulación y tiene una precisión de ubicación mucho más pobre.
Para remediar este problema, escribí una clase de utilidad que se ubicaciones de prueba fiable a suprimir en todas las versiones de Android modernos (API nivel 15 en adelante):
LocationAssistant: actualizaciones de ubicación sin complicaciones en Android
Básicamente, "desconfía" de las ubicaciones no simuladas que se encuentran dentro de 1 km de la última ubicación simulada conocida y también las etiqueta como simuladas. Lo hace hasta que haya llegado un número significativo de ubicaciones no simuladas. El LocationAssistant no sólo puede rechazar ubicaciones de prueba, sino que también se desahoga de la mayor parte de la molestia de crear y suscribirse a las actualizaciones de ubicación.
Para recibir solo actualizaciones de ubicación reales (es decir, suprimir simulacros), utilícelo de la siguiente manera:
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()
ahora solo se invocará con información de ubicación real. Hay algunos métodos más de escucha que necesita implementar, pero en el contexto de su pregunta (cómo evitar la suplantación de GPS), básicamente es así.Por supuesto, con un sistema operativo rooteado, aún puede encontrar formas de falsificar información de ubicación que son imposibles de detectar para las aplicaciones normales.
fuente
Si conocía la ubicación general de las torres de telefonía celular, puede verificar si la torre de telefonía celular actual coincide con la ubicación dada (dentro de un margen de error de algo grande, como 10 o más millas).
Por ejemplo, si su aplicación desbloquea funciones solo si el usuario se encuentra en una ubicación específica (su tienda, por ejemplo), puede verificar tanto los gps como las torres de telefonía celular. Actualmente, ninguna aplicación de suplantación de GPS también falsifica las torres de telefonía celular, por lo que podría ver si alguien en todo el país simplemente está tratando de burlarse de sus funciones especiales (estoy pensando en la aplicación Disney Mobile Magic, por ejemplo).
Así es como la aplicación Llama administra la ubicación de forma predeterminada, ya que la verificación de los identificadores de las torres de telefonía celular consume mucha menos batería que el GPS. No es útil para ubicaciones muy específicas, pero si la casa y el trabajo están a varias millas de distancia, puede distinguir entre las dos ubicaciones generales con mucha facilidad.
Por supuesto, esto requeriría que el usuario tuviera una señal celular. Y tendría que conocer todos los identificadores de torres de telefonía móvil de la zona, de todos los proveedores de la red, o correría el riesgo de obtener un falso negativo.
fuente
prueba este código es muy simple y útil
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; }
fuente
Este script funciona para todas las versiones de Android y lo encuentro después de muchas búsquedas
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 }
fuente
Puede agregar una verificación adicional basada en la triangulación de la torre celular o la información de los puntos de acceso Wifi utilizando la API de geolocalización de Google Maps
La forma más sencilla de obtener información sobre 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();
Puede comparar sus resultados con el sitio
Para obtener información sobre los puntos de acceso 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(); }
fuente