Ищете лучший способ предотвратить / обнаружить спуфинг GPS на Android. Есть предложения о том, как этого добиться и что можно сделать, чтобы это остановить? Я предполагаю, что пользователь должен включить фиктивные местоположения, чтобы подделать GPS, если это будет сделано, тогда они могут подделать GPS?
Думаю, мне нужно просто определить, включены ли Mock Locations? Есть другие предложения?
Ответы:
Я провел небольшое расследование и поделился своими результатами здесь, это может быть полезно для других.
Во-первых, мы можем проверить, включена ли опция MockSetting.
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; }
Во-вторых, мы можем проверить, есть ли на устройстве другие приложения, которые используют
android.permission.ACCESS_MOCK_LOCATION
(приложения для подмены местоположения)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; }
Если оба вышеуказанных метода, первый и второй, верны, есть большая вероятность, что местоположение может быть поддельным или поддельным.
Теперь спуфинга можно избежать с помощью API Location Manager.
Мы можем удалить поставщика тестов, прежде чем запрашивать обновления местоположения у обоих поставщиков (сети и 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);
Я видел, что removeTestProvider (~) очень хорошо работает с Jelly Bean и более поздними версиями. Этот API оказался ненадежным до Ice Cream Sandwich.
источник
android.permission.ACCESS_MOCK_LOCATION
разрешение наremoveTestProvider
работу, что, на мой взгляд, является самым большим недостатком.isMockSettingsON()
,Location.isFromMockProvider()
иareThereMockPermissionApps()
с черным списком приложений. Есть много предустановленных системных приложений сACCESS_MOCK_LOCATION
разрешением, например на устройствах HTC и Samsung. Белый список всех законных приложений был бы лучше, но черный список самых популярных приложений для подмены местоположения в моем случае работал хорошо. И я также проверил, было ли устройство рутировано.Начиная с API 18, у объекта Location есть метод .isFromMockProvider (), поэтому вы можете отфильтровывать поддельные местоположения.
Если вы хотите поддерживать версии до 18, можно использовать что-то вроде этого:
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"); }
источник
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
Похоже, что единственный способ сделать это - предотвратить подмену местоположения, предотвращающую MockLocations. Обратной стороной является то, что некоторые пользователи используют устройства Bluetooth GPS для получения лучшего сигнала, они не смогут использовать приложение, так как им необходимо использовать фиктивные местоположения.
Для этого я сделал следующее:
// 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;
источник
return !x
вместоif(x) return false; else return true
.Наткнулся на эту ветку пару лет спустя. В 2016 году большинство устройств Android будут иметь уровень API> = 18 и, следовательно, должны полагаться на Location.isFromMockProvider (), как указал Фернандо .
Я много экспериментировал с фальшивыми / фиктивными локациями на разных устройствах и дистрибутивах Android. К сожалению .isFromMockProvider () не на 100% надежен. Время от времени поддельное местоположение не будет помечено как фиктивное . Похоже, это происходит из-за некоторой ошибочной внутренней логики объединения в Google Location API.
Я написал подробный пост об этом в блоге , если вы хотите узнать больше. Подводя итог, если вы подпишетесь на обновления местоположения из Location API, затем включите поддельное приложение GPS и распечатаете результат каждого Location.toString () на консоли, вы увидите что-то вроде этого:
Обратите внимание, что в потоке обновлений местоположения одно местоположение имеет те же координаты, что и другие, но не помечено как фиктивное и имеет гораздо более низкую точность определения местоположения.
Чтобы решить эту проблему, я написал служебный класс, который надежно подавит фиктивные местоположения во всех современных версиях Android (уровень API 15 и выше):
LocationAssistant - беспроблемное обновление местоположения на Android
По сути, он «не доверяет» немодельным местоположениям, которые находятся в пределах 1 км от последнего известного фиктивного местоположения, а также помечает их как фиктивные. Это происходит до тех пор, пока не появится значительное количество немодельных локаций. LocationAssistant может не только отказаться от фиктивных местоположений, но и разгружает вас от большинства хлопот настройки и подписок на обновление местоположения.
Чтобы получать только реальные обновления местоположения (то есть подавлять моки), используйте его следующим образом:
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()
теперь будет вызываться только с реальной информацией о местоположении. Есть еще несколько методов прослушивания, которые вам нужно реализовать, но в контексте вашего вопроса (как предотвратить подделку GPS) это в основном это.Конечно, с рутированной ОС вы все еще можете найти способы подделки информации о местоположении, которые обычные приложения не могут обнаружить.
источник
Если вам известно общее расположение вышек сотовой связи, вы можете проверить, совпадает ли текущая вышка сотовой связи с заданным местоположением (в пределах погрешности чего-то большого, например, 10 или более миль).
Например, если ваше приложение открывает функции только в том случае, если пользователь находится в определенном месте (например, в вашем магазине), вы можете проверить GPS, а также вышки сотовой связи. В настоящее время ни одно приложение для спуфинга GPS также не подделывает вышки сотовой связи, поэтому вы можете увидеть, не пытается ли кто-то по всей стране просто обманом проникнуть в ваши специальные функции (например, я думаю о приложении Disney Mobile Magic).
Именно так приложение Llama управляет местоположением по умолчанию, поскольку проверка идентификаторов вышек сотовой связи требует гораздо меньшего расхода заряда батареи, чем gps. Это бесполезно для очень определенных мест, но если дом и работа находятся в нескольких милях от него, он может очень легко различить два основных местоположения.
Конечно, это потребует от пользователя вообще наличия сотового сигнала. И вам нужно будет знать идентификаторы всех вышек сотовой связи в этом районе - всех сетевых провайдеров - или вы рискуете получить ложноотрицательный результат.
источник
попробуйте этот код, он очень простой и полезный
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; }
источник
Этот скрипт работает для всех версий Android, и я нашел его после многих поисков
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 }
источник
Вы можете добавить дополнительную проверку на основе данных триангуляции вышек сотовой связи или информации о точках доступа Wi-Fi с помощью Google Maps Geolocation API.
Самый простой способ получить информацию о 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();
Вы можете сравнить свои результаты с сайтом
Чтобы получить информацию о точках доступа Wi-Fi
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(); }
источник