Sahte Konum için Devre Dışı Bırak / Kontrol Et (gps sahtekarlığını önleyin)


92

Android'de GPS sahtekarlığını önlemenin / tespit etmenin en iyi yolunu bulmak. Bunun nasıl başarılacağına ve durdurmak için ne yapılabileceğine dair herhangi bir öneriniz var mı? Kullanıcının GPS'i taklit etmek için sahte konumları açması gerektiğini tahmin ediyorum, eğer bu yapılırsa GPS sahtekarlığı yapabilir mi?

Sanırım sadece Sahte Konumların etkin olup olmadığını algılamam gerekiyor? Başka öneriniz var mı?


2
Sanırım Eclipse'deki DDMS görünümünde bulunan Konum Sahtekarlığı işlevini soruyor.
Shawn Walton

2
İnsanların hile yapmasını istemediğim konuma dayalı bir oyunum var, bu yüzden sahtekarlığı engellemek istiyorum, anladığım kadarıyla iki yoldan biri olabilir .. Sahte konumların etkinleştirilmesi ve düşük düzeyde sahtekarlık yapan özel bir görüntü oluşturulması ve ayarlar uygulamasındaki adres sahteciliği ayarını dikkate almaz. MockLocations için Settings.System Provider'ı bulmaya çalışıyorum veya etkinleştirilip etkinleştirilmediğini görmek için (uygulamanın ortasında bir dinleyiciyle).
Chrispix

Yanıtlar:


127

Biraz araştırma yaptım ve sonuçlarımı burada paylaştım, bu diğerleri için faydalı olabilir.

İlk önce MockSetting seçeneğinin AÇIK olup olmadığını kontrol edebiliriz.

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;
}

İkinci olarak, cihazda android.permission.ACCESS_MOCK_LOCATION(Location Spoofing Apps) kullanan başka uygulamalar olup olmadığını kontrol edebiliriz.

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;
}

Yukarıdaki yöntemlerin her ikisi de, birinci ve ikinci doğruysa, konumun sahte veya sahte olma ihtimali yüksektir.

Artık, Konum Yöneticisinin API'sı kullanılarak adres sahteciliği önlenebilir.

Her iki sağlayıcıdan (Ağ ve GPS) konum güncellemelerini talep etmeden önce test sağlayıcısını kaldırabiliriz.

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 (~) uygulamasının Jelly Bean ve sonraki sürümlere göre çok iyi çalıştığını gördüm. Bu API, Ice Cream Sandwich'e kadar güvenilmez görünüyordu.


Çok ilginç gözlemler. Bunu paylaşmak için özellikle son +1 +1.
ar-g

2
RemoveTestProvider yöntemi hakkında not. Konum Yöneticisinin arka planda çalışmasına izin verirseniz, kullanıcı sahte uygulamaya gidebilir ve alay konumunu yeniden başlatabilir. Konum yöneticiniz, yeniden removeTestProvider'ı çağırana kadar sahte konumları almaya başlayacaktır.
Timur_C

4
Ayrıca uygulamanızın çalışma android.permission.ACCESS_MOCK_LOCATIONiznine sahip olması gerekir removeTestProviderki bu bence en büyük dezavantaj.
Timur_C

18
Cevap için teşekkürler! sadece bir nokta: Android 6.0'da ALLOW_MOCK_LOCATION kullanımdan kaldırılmıştır. Ve aslında sahte konum için de onay kutusu yok. Konum nesnesinden konumun sahte olup olmadığı kontrol edilebilir: location.isFromMockProvider ()
Silwester

3
@Blackkara Ne de olsa kullanmadım. Ben özelleştirilmiş bir arada kullanılır isMockSettingsON(), Location.isFromMockProvider()ve areThereMockPermissionApps()uygulamaların kara liste ile. ACCESS_MOCK_LOCATION Örneğin HTC ve Samsung cihazlarında önceden yüklenmiş, izinli çok sayıda sistem uygulaması vardır . Tüm meşru uygulamaların bir beyaz listesi daha iyi olurdu, ancak benim durumumda en popüler konum sahtekarlığı uygulamalarının kara listesi iyi çalıştı. Ayrıca cihazın köklü olup olmadığını da kontrol ettim.
Timur_C

46

API 18'den beri, Konum nesnesi .isFromMockProvider () yöntemine sahiptir, böylece sahte konumları filtreleyebilirsiniz.

18'den önceki sürümleri desteklemek istiyorsanız, bunun gibi bir şey kullanmak mümkündür:

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");
}

İkinci ifadenizin geriye doğru olduğundan oldukça eminim (yanlış döndürmesi gerektiğinde true dönün). Sanırım şöyle olmalı:isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
charles-allen

3
Rica ederim. Daha modern bir cevap gönderdiğiniz için teşekkürler! Gerçekten bugün itibariyle doğru cevap bu.
charles-allen

1
18'in üzerindeki SDK için "konum" nesnesi olmadan bunu nasıl yapabiliriz?
Ajit Sharma

35

Görünüşe göre bunu yapmanın tek yolu, MockLocations'ı engelleyen Konum Sahtekarlığını önlemek. Kötü tarafı, daha iyi bir sinyal almak için Bluetooth GPS cihazlarını kullanan bazı kullanıcılar var, sahte konumları kullanmaları gerektiği için uygulamayı kullanamayacaklar.

Bunu yapmak için şunları yaptım:

// 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;

4
Bu aptalca bir kanıt değil. Köklü olmayan bir cihazdaki kullanıcılar, gelecekte de bir sahte konum ayarlayabilir, ardından sahte konumları devre dışı bırakabilir ve sahte konum hala etkin olur. Daha da kötüsü, sahte konuma Network / Gps ile aynı sağlayıcı adını verebiliyorlar ve görünüşe göre bundan çıkıyor ..
Chrispix

3
Ayrıca, Fake GPS , köklü cihazlarda sahte konum ayarını gerektirmez.
Paul Lammertsma

Fake.gps uygulamasının yüklü olmadığını her zaman kontrol edebilirim :)
Chrispix

11
Bunun return !xyerine kullanabilirsiniz if(x) return false; else return true.
CodesInChaos

Aslında, Sahte konum, köklü cihazlarda bile sahte konum ayarını değiştirecektir.
PageNotFound

26

Birkaç yıl sonra bu konuya tökezledi. 2016'da çoğu Android cihazının API seviyesi> = 18 olacak ve bu nedenle Fernando'nun belirttiği gibi Location.isFromMockProvider () 'a güvenmesi gerekiyor .

Farklı Android cihazlarda ve dağıtımlarda sahte / sahte konumları kapsamlı bir şekilde denedim. Ne yazık ki .isFromMockProvider () % 100 güvenilir değil. Arada bir, sahte bir konum sahte olarak etiketlenmez . Bu, Google Konum API'sindeki bazı hatalı dahili füzyon mantığından kaynaklanıyor gibi görünüyor.

Daha fazlasını öğrenmek isterseniz bunun hakkında detaylı bir blog yazısı yazdım . Özetlemek gerekirse, Konum API'sinden konum güncellemelerine abone olursanız, sahte bir GPS uygulaması açarsanız ve her Location.toString () sonucunu konsola yazdırırsanız, şunun gibi bir şey göreceksiniz:

görüntü açıklamasını buraya girin

Konum güncellemeleri akışında, bir konumun diğerleriyle aynı koordinatlara sahip olduğunu, ancak sahte olarak işaretlenmediğini ve çok daha zayıf bir konum doğruluğuna sahip olduğuna dikkat edin.

Bu sorunu çözmek için, bir yardımcı sınıf yazdı olacak tüm modern Android sürümleri (yukarı API seviyesi 15 ve üzeri) arasında güvenilir bastırmak Mock yerleri:

LocationAssistant - Android'de sorunsuz konum güncellemeleri

Temel olarak, bilinen son sahte konumun 1 km yakınında bulunan sahte olmayan konumlara "güvenmez" ve bunları sahte olarak etiketler. Bunu, sahte olmayan önemli sayıda konum gelene kadar yapar. Konum Yardımcısı Sahte konumlara reddetmek değil, aynı zamanda kurulumu ve konum güncellemelerine abone karmaşası çoğundan sizi unburdens olabilir sadece.

Yalnızca gerçek konum güncellemelerini almak için (yani taklitleri bastırmak), aşağıdaki şekilde kullanın:

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()artık yalnızca gerçek konum bilgileriyle çağrılacak. Uygulamanız gereken daha fazla dinleyici yöntemi vardır, ancak sorunuz bağlamında (GPS sahtekarlığını nasıl önleyebilirsiniz) temelde budur.

Tabii ki, köklü bir işletim sistemi ile, normal uygulamaların algılaması imkansız olan konum bilgisi sahteciliği yollarını yine de bulabilirsiniz.


Bağlantılı blog gönderisini kısaca özetlemelisiniz (isFromMockProvider nerede başarısız olur).
charles-allen

@CodeConfident - yorum için teşekkürler! Yine de ne eklemem gerektiğinden emin değilim. Benim cevabın ikinci paragraf olan blog yayınının özeti. .isFromMockProvider zaman zaman ve tahmin edilemeyecek şekilde başarısız olur. Makalede bunu keşfetmek ve düzeltmek için attığım adımları daha ayrıntılı olarak anlatıyorum.
KlaasNotFound

Peki, hangisinin benim için SO'nun niyetine aykırı olduğunu düşündüğünü anlamak için makalenize atlamak zorunda kaldım. En iyi önerim şudur: (1) tehlikeli konumu gösteren resminizi ekleyin (sahte olarak işaretlenmemiş) ve (2) bunları ortadan kaldırmak için mantığınızı hızlıca not edin (bir taklidin 1 km içinde göz ardı edin)
charles-allen

Tamam, anladım. Bence OP bağlamında, .isFromMockProvider () neden güvenilmez olduğuna dair ayrıntılar çok alakalı değil. Ama daha büyük resim için bahsettiğiniz detayları eklemeye çalışacağım. Geri dönüşünüz için teşekkür ederiz!
KlaasNotFound

1
Kullanıcıda Google Play Hizmeti yüklü değilse ne olur?
Yuriy Chernyshov

6

Baz istasyonlarının genel konumunu biliyorsanız, mevcut baz istasyonunun verilen konumla eşleşip eşleşmediğini kontrol edebilirsiniz (10 veya daha fazla mil gibi büyük bir şeyin hata payı dahilinde).

Örneğin, uygulamanız yalnızca kullanıcı belirli bir konumdaysa (örneğin, mağazanız) özelliklerin kilidini açarsa GPS'in yanı sıra baz istasyonlarını da kontrol edebilirsiniz. Şu anda, hiçbir gps sahtekarlığı uygulaması hücre kulelerini de yanıltmaz, böylece ülkenin her yerinden birinin sizin özel özelliklerinize kendi yollarını taklit etmeye çalışıp çalışmadığını görebilirsiniz (bir örnek için Disney Mobile Magic uygulamasını düşünüyorum).

Lama uygulaması varsayılan olarak konumu bu şekilde yönetir, çünkü baz istasyonu kimliklerini kontrol etmek gps'den çok daha az pil gerektirir. Çok özel konumlar için kullanışlı değildir, ancak ev ve iş birkaç mil uzaktaysa, iki genel konumu kolayca ayırt edebilir.

Elbette bu, kullanıcının bir hücre sinyaline sahip olmasını gerektirecektir. Ve bölgedeki tüm baz istasyonu kimliklerini bilmeniz gerekir - tüm ağ sağlayıcılarında - yoksa yanlış bir negatif riskiyle karşı karşıya kalırsınız.


1
Teşekkürler, bu oldukça iyi bir fikir. Buna bakmam gerekebilir. Teşekkürler
Chrispix

3

bu kodu deneyin çok basit ve faydalıdır

  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;
    }

Bu, yukarıdaki isMockLocationEnabled yönteminin çok daha iyi bir sürümüdür.
setzamora

AppOpsManager.checkOp () SecurityException atar Uygulama bu operasyonda kilitlenecek şekilde yapılandırılmışsa. Gibi: java.lang.SecurityException: uid 11151'den gelen paket adının MOCK_LOCATION gerçekleştirmesine izin verilmiyor. Bu yöntem, "uygulamanızın konumlarla taklit edip edemediğini" tespit etmek üzere. Ancak "alınan konumlarla alay edildiyse" değil.
Sergio

@Sergio, "Uygulamanız konumlarla dalga geçebiliyorsa", mevcut uygulamanın konumlarla dalga geçme izni olduğunu kastediyorsunuz, değil mi?
Victor Laerte

@VictorLaerte Bir konuyla ilgili son bir bağlam: / Doğru. Ancak soru şuydu: "Alınan bir konumun alay konusu olup olmadığı veya sahte bir sağlayıcıdan olup olmadığı nasıl tespit edilir". Veya sahte konumların nasıl yok sayılacağı.
Sergio

2

Bu komut dosyası tüm android sürümleri için çalışıyor ve birçok aramadan sonra buluyorum

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
    }

1

Google Haritalar Coğrafi Konum API'sini kullanarak baz istasyonu nirengi veya Wifi Erişim Noktaları bilgilerine göre ek kontrol ekleyebilirsiniz.

CellTowers hakkında bilgi almanın en basit yolu

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();

Sonuçlarınızı site ile karşılaştırabilirsiniz

Wifi Erişim Noktaları hakkında bilgi almak için

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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.