Nonaktifkan / Periksa Lokasi Mock (cegah spoofing gps)

90

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?

Chrispix
sumber
2
Saya rasa dia bertanya tentang fungsi Location Spoofing yang tersedia dalam tampilan DDMS di Eclipse.
Shawn Walton
2
Saya memiliki permainan berbasis lokasi yang saya tidak ingin orang-orang selingkuh, jadi saya akan memblokir spoofing, pemahaman saya adalah hal itu dapat terjadi dengan salah satu dari dua cara .. Mengaktifkan lokasi palsu, dan membuat gambar khusus yang melakukan spoofing tingkat rendah dan mengabaikan setelan spoofing di aplikasi setelan. Mencoba menemukan Settings.System Provider for MockLocations, atau ingin melihat apakah itu diaktifkan (dengan pendengar di tengah aplikasi).
Chrispix

Jawaban:

125

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.

Jambaaz
sumber
Pengamatan yang sangat menarik. Terutama yang terakhir +1 untuk membagikan ini.
ar-g
2
Catatan tentang metode removeTestProvider. Jika Anda mengizinkan Pengelola Lokasi untuk bekerja di latar belakang, pengguna dapat membuka aplikasi palsu dan memulai ulang lokasi palsu. Manajer lokasi Anda kemudian akan mulai menerima lokasi palsu sampai Anda memanggil removeTestProvider lagi.
Timur_C
4
Aplikasi Anda juga harus memiliki android.permission.ACCESS_MOCK_LOCATIONizin agar removeTestProviderdapat berfungsi, yang menurut saya merupakan kerugian terbesar.
Timur_C
18
Terima kasih atas jawabannya! hanya satu poin: di Android 6.0 ALLOW_MOCK_LOCATION sudah tidak digunakan lagi. Dan sebenarnya tidak ada kotak centang untuk lokasi palsu juga. Seseorang dapat memeriksa apakah lokasi itu palsu atau tidak langsung dari objek lokasi
Silwester
2
@Blackkara Aku sama sekali tidak menggunakannya. Saya menggunakan kombinasi yang disesuaikan isMockSettingsON(), Location.isFromMockProvider()dan areThereMockPermissionApps()dengan daftar hitam aplikasi. Ada banyak aplikasi sistem yang sudah diinstal sebelumnya dengan ACCESS_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.
Timur_C
45

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");
}
Fernando
sumber
Saya cukup yakin ekspresi kedua Anda terbalik (kembalikan true saat harus mengembalikan false). Saya pikir itu seharusnya:isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
AjahnCharles
3
Sama-sama. Terima kasih telah memposting jawaban yang lebih modern! Sungguh ini adalah jawaban yang benar untuk hari ini.
AjahnCharles
1
Bagaimana kita bisa melakukannya tanpa objek "lokasi" untuk SDK di atas 18?
Ajit Sharma
35

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;
Chrispix
sumber
4
Ini bukan bukti yang bodoh. Pengguna pada perangkat yang tidak di-rooting masih dapat mengatur lokasi palsu, dengan waktu di masa mendatang, kemudian menonaktifkan lokasi palsu, dan lokasi palsu masih aktif. Lebih buruk lagi, mereka dapat memanggil lokasi tiruan dengan nama penyedia yang sama dengan Jaringan / Gps dan tampaknya menarik dari itu ..
Chrispix
3
Selain itu, GPS Palsu tidak memerlukan pengaturan lokasi palsu pada perangkat yang di-rooting.
Paul Lammertsma
Selalu dapat memeriksa untuk memverifikasi bahwa aplikasi fake.gps tidak diinstal :)
Chrispix
11
Anda dapat menggunakan return !xsebagai pengganti if(x) return false; else return true.
CodesInChaos
Faktanya, Lokasi palsu akan mengubah pengaturan lokasi palsu bahkan pada perangkat yang di-rooting.
PageNotFound
25

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:

masukkan deskripsi gambar di sini

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.

KlaasNotFound
sumber
Anda harus meringkas entri blog yang ditautkan secara singkat (jika isFromMockProvider gagal).
AjahnCharles
@CodeConfident - terima kasih atas komentarnya! Tidak yakin apa yang harus saya tambahkan. Paragraf kedua dari jawaban saya adalah ringkasan dari posting blog. .isFromMockProvider gagal secara sporadis dan tidak terduga. Dalam artikel tersebut saya hanya menjelaskan secara lebih rinci langkah-langkah yang saya ambil untuk menemukan dan memperbaiki ini.
KlaasTidak Ditemukan
Yah saya terpaksa melompat ke artikel Anda untuk memahami yang menurut saya itu bertentangan dengan maksud SO. Saran terbaik saya adalah: (1) sisipkan foto Anda yang menunjukkan lokasi yang cerdik (tidak ditandai sebagai tiruan) dan (2) cepat catat logika Anda untuk menghilangkannya (abaikan dalam jarak 1 km dari tiruan)
AjahnCharles
Oke, mengerti. Saya pikir dalam konteks OP, secara spesifik mengapa .isFromMockProvider () tidak dapat diandalkan tidak terlalu relevan. Tetapi saya akan mencoba menambahkan detail yang Anda sebutkan untuk gambaran yang lebih besar. Terima kasih untuk umpan baliknya!
KlaasTidak Ditemukan
1
Bagaimana jika pengguna tidak menginstal Layanan Google Play?
Yuriy Chernyshov
6

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.

Stephen Schrauger
sumber
1
Terima kasih, itu ide yang cukup bagus. Saya mungkin harus memeriksanya. Terima kasih
Chrispix
3

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;
    }
Mostafa Pirhayati
sumber
Ini adalah versi yang jauh lebih baik dari metode isMockLocationEnabled di atas.
setzamora
AppOpsManager.checkOp () memunculkan SecurityException Jika aplikasi telah dikonfigurasi untuk mogok pada operasi ini. Seperti: java.lang.SecurityException: nama paket dari uid 11151 tidak diizinkan untuk melakukan MOCK_LOCATION. Metode ini akan mendeteksi "jika aplikasi Anda dapat memalsukan lokasi". Tapi tidak "jika menerima lokasi diejek".
Sergio
@Sergio dengan "jika aplikasi Anda dapat meniru lokasi" yang Anda maksud jika aplikasi saat ini memiliki izin untuk meniru lokasi, bukan?
Victor Laerte
@VictorLaerte Saya telah bertahan dalam konteks topik: / Benar. Tapi pertanyaannya adalah: "bagaimana mendeteksi jika lokasi yang diterima diejek atau dari penyedia palsu". Atau cara mengabaikan lokasi palsu.
Sergio
2

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
    }
Ali
sumber
1

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();
}
yoAlex5
sumber