Mencari cara terbaik untuk mencegah / mendeteksi spoofing GPS di Android. Ada saran tentang bagaimana ini dicapai, dan apa yang dapat dilakukan untuk menghentikannya? Saya menduga pengguna harus mengaktifkan lokasi palsu untuk spoof GPS, jika ini dilakukan, maka mereka dapat melakukan spoof GPS?
Saya kira saya hanya perlu mendeteksi jika Lokasi Mock diaktifkan? Ada saran lain?
Jawaban:
Saya telah melakukan beberapa investigasi dan membagikan hasil saya di sini, ini mungkin berguna untuk orang lain.
Pertama, kita dapat memeriksa apakah opsi MockSetting DIAKTIFKAN
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; }
Kedua, kami dapat memeriksa apakah ada aplikasi lain di perangkat, yang menggunakan
android.permission.ACCESS_MOCK_LOCATION
(Aplikasi Spoofing Lokasi)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; }
Jika kedua metode di atas, pertama dan kedua benar, maka ada kemungkinan besar lokasi itu palsu atau palsu.
Sekarang, spoofing dapat dihindari dengan menggunakan API Pengelola Lokasi.
Kami dapat menghapus penyedia tes sebelum meminta pembaruan lokasi dari kedua penyedia (Jaringan dan 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);
Saya telah melihat bahwa removeTestProvider (~) bekerja sangat baik pada versi Jelly Bean dan seterusnya. API ini tampaknya tidak dapat diandalkan hingga Ice Cream Sandwich.
sumber
android.permission.ACCESS_MOCK_LOCATION
izin agarremoveTestProvider
dapat berfungsi, yang menurut saya merupakan kerugian terbesar.isMockSettingsON()
,Location.isFromMockProvider()
danareThereMockPermissionApps()
dengan daftar hitam aplikasi. Ada banyak aplikasi sistem yang sudah diinstal sebelumnya denganACCESS_MOCK_LOCATION
izin, misalnya di perangkat HTC dan Samsung. Daftar putih dari semua aplikasi yang sah akan lebih baik tetapi daftar hitam aplikasi spoofing lokasi paling populer bekerja dengan baik dalam kasus saya. Dan saya juga memeriksa apakah perangkat di-root.Sejak API 18, obyek Lokasi memiliki metode .isFromMockProvider () sehingga Anda dapat menyaring lokasi palsu.
Jika Anda ingin mendukung versi sebelum 18, dimungkinkan untuk menggunakan sesuatu seperti ini:
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"); }
sumber
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
Tampaknya satu-satunya cara untuk melakukannya adalah dengan mencegah Spoofing Lokasi mencegah MockLocations. Sisi negatifnya adalah ada beberapa pengguna yang menggunakan perangkat Bluetooth GPS untuk mendapatkan sinyal yang lebih baik, mereka tidak akan dapat menggunakan aplikasi karena mereka diharuskan untuk menggunakan lokasi palsu.
Untuk melakukan ini, saya melakukan hal berikut:
// 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;
sumber
return !x
sebagai penggantiif(x) return false; else return true
.Menemukan utas ini beberapa tahun kemudian. Pada 2016, sebagian besar perangkat Android akan memiliki API level> = 18 dan karenanya harus bergantung pada Location.isFromMockProvider () seperti yang ditunjukkan oleh Fernando .
Saya banyak bereksperimen dengan lokasi palsu / tiruan di berbagai perangkat dan distro Android. Sayangnya .isFromMockProvider () tidak 100% dapat diandalkan. Terkadang, lokasi palsu tidak akan diberi label sebagai tiruan . Ini tampaknya disebabkan oleh beberapa logika fusi internal yang salah di Google Location API.
Saya menulis posting blog mendetail tentang ini , jika Anda ingin mempelajari lebih lanjut. Untuk meringkas, jika Anda berlangganan pembaruan lokasi dari API Lokasi, kemudian mengaktifkan aplikasi GPS palsu dan mencetak hasil dari setiap Location.toString () ke konsol, Anda akan melihat sesuatu seperti ini:
Perhatikan bagaimana, dalam aliran pembaruan lokasi, satu lokasi memiliki koordinat yang sama dengan yang lain, tetapi tidak ditandai sebagai tiruan dan memiliki akurasi lokasi yang jauh lebih buruk.
Untuk memperbaiki masalah ini, saya menulis kelas utilitas yang andal akan menekan lokasi Mock di semua versi Android modern (API level 15 dan lebih tinggi):
LocationAssistant - Pembaruan lokasi tanpa kerumitan di Android
Pada dasarnya, ini "tidak mempercayai" lokasi bukan tiruan yang berada dalam jarak 1 km dari lokasi palsu terakhir yang diketahui dan juga menandainya sebagai tiruan. Ini dilakukan sampai sejumlah besar lokasi non-tiruan telah tiba. The LocationAssistant tidak hanya dapat menolak lokasi pura-pura, tetapi juga unburdens Anda dari sebagian besar kerumitan pengaturan dan berlangganan update lokasi.
Untuk hanya menerima pembaruan lokasi nyata (yaitu menekan tiruan), gunakan sebagai berikut:
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()
sekarang hanya akan dipanggil dengan info lokasi sebenarnya. Ada beberapa metode pendengar lagi yang perlu Anda terapkan, tetapi dalam konteks pertanyaan Anda (cara mencegah spoofing GPS), ini pada dasarnya.Tentu saja, dengan OS yang di-root, Anda masih dapat menemukan cara spoofing info lokasi yang tidak mungkin dideteksi oleh aplikasi normal.
sumber
Jika Anda kebetulan mengetahui lokasi umum menara seluler, Anda dapat memeriksa apakah menara seluler saat ini cocok dengan lokasi yang diberikan (dalam margin kesalahan dari sesuatu yang besar, seperti 10 mil atau lebih).
Misalnya, jika aplikasi Anda membuka fitur hanya jika pengguna berada di lokasi tertentu (toko Anda, misalnya), Anda dapat memeriksa gps serta menara seluler. Saat ini, tidak ada aplikasi spoofing gps yang juga memalsukan menara seluler, jadi Anda dapat melihat apakah seseorang di seluruh negeri hanya mencoba untuk memalsukan cara mereka ke fitur khusus Anda (saya memikirkan aplikasi Disney Mobile Magic, sebagai satu contoh).
Beginilah cara aplikasi Llama mengelola lokasi secara default, karena memeriksa id menara seluler jauh lebih hemat baterai daripada gps. Ini tidak berguna untuk lokasi yang sangat spesifik, tetapi jika rumah dan kantor berjarak beberapa mil, ini dapat membedakan dua lokasi umum dengan sangat mudah.
Tentu saja, ini mengharuskan pengguna untuk memiliki sinyal seluler sama sekali. Dan Anda harus mengetahui semua ID menara seluler di area tersebut - pada semua penyedia jaringan - atau Anda akan menghadapi risiko negatif palsu.
sumber
coba kode ini sangat sederhana dan berguna
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; }
sumber
Script ini bekerja untuk semua versi android dan saya menemukannya setelah banyak pencarian
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 }
sumber
Anda dapat menambahkan pemeriksaan tambahan berdasarkan triangulasi menara seluler atau info Titik Akses Wifi menggunakan Google Maps Geolocation API
Cara termudah untuk mendapatkan info tentang 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();
Anda dapat membandingkan hasil Anda dengan situs
Untuk mendapatkan info tentang Titik Akses 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(); }
sumber