programing

모의 위치 비활성화 / 확인 (gps 스푸핑 방지)

nasanasas 2020. 9. 23. 07:41
반응형

모의 위치 비활성화 / 확인 (gps 스푸핑 방지)


Android에서 GPS 스푸핑을 방지 / 감지하는 가장 좋은 방법을 찾고 있습니다. 이 작업을 수행하는 방법에 대한 제안 사항과이를 중지하기 위해 수행 할 수있는 작업은 무엇입니까? 사용자가 GPS를 스푸핑하려면 모의 위치를 ​​켜야한다고 생각합니다.이 작업이 완료되면 GPS를 스푸핑 할 수 있습니까?

모의 위치가 활성화되어 있는지 감지해야할까요? 다른 제안이 있습니까?


여기에서 조사하고 결과를 공유했습니다. 이것은 다른 사람들에게 유용 할 수 있습니다.

먼저 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를 사용하여 스푸핑을 방지 할 수 있습니다.

공급자 (네트워크 및 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까지 신뢰할 수없는 것으로 보입니다.


이를 수행하는 유일한 방법은 위치 스푸핑이 MockLocation을 방지하는 것을 방지하는 것 같습니다. 단점은 더 나은 신호를 얻기 위해 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;

API 18부터 위치 개체 에는 .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");
}

몇 년 후이 스레드를 우연히 발견했습니다. 2016 년에 대부분의 Android 기기는 API 레벨이 18 이상이므로 Fernando가 지적한대로 Location.isFromMockProvider () 에 의존해야합니다 .

다양한 Android 기기 및 배포판에서 가짜 / 모의 위치를 ​​광범위하게 실험했습니다. 불행히도 .isFromMockProvider () 는 100 % 신뢰할 수 없습니다. 가끔 가짜 위치는 mock로 표시되지 않습니다 . 이는 Google Location API의 잘못된 내부 융합 로직 때문인 것 같습니다.

I wrote a detailed blog post about this, if you want to learn more. To summarize, if you subscribe to location updates from the Location API, then switch on a fake GPS app and print the result of each Location.toString() to the console, you will see something like this:

enter image description here

Notice how, in the stream of location updates, one location has the same coordinates as the others, but is not flagged as a mock and has a much poorer location accuracy.

To remedy this problem, I wrote a utility class that will reliably suppress Mock locations across all modern Android versions (API level 15 and up):

LocationAssistant - Hassle-free location updates on Android

Basically, it "distrusts" non-mock locations that are within 1km of the last known mock location and also labels them as a mock. It does this until a significant number of non-mock locations have arrived. The LocationAssistant can not only reject mock locations, but also unburdens you from most of the hassle of setting up and subscribing to location updates.

To receive only real location updates (i.e. suppress mocks), use it as follows:

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() will now only be invoked with real location info. There are some more listener methods you need to implement, but in the context of your question (how to prevent GPS spoofing) this is basically it.

Of course, with a rooted OS you can still find ways of spoofing location info that are impossible for normal apps to detect.


If you happened to know the general location of cell towers, you could check to see if the current cell tower matches the location given (within an error margin of something large, like 10 or more miles).

For example, if your app unlocks features only if the user is in a specific location (your store, for example), you could check gps as well as cell towers. Currently, no gps spoofing app also spoofs the cell towers, so you could see if someone across the country is simply trying to spoof their way into your special features (I'm thinking of the Disney Mobile Magic app, for one example).

This is how the Llama app manages location by default, since checking cell tower ids are much less battery intensive than gps. It isn't useful for very specific locations, but if home and work are several miles away, it can distinguish between the two general locations very easily.

Of course, this would require the user to have a cell signal at all. And you would have to know all the cell towers ids in the area --on all network providers-- or you would run the risk of a false negative.


try this code its very simple and usefull

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

This scrip is working for all version of android and i find it after many search

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
    }

You can add additional check based on cell tower triangulation or Wifi Access Points info using Google Maps Geolocation API

The simplest way to get info about 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();

You can compare your results with site

To get info about Wifi Access Points

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

참고URL : https://stackoverflow.com/questions/6880232/disable-check-for-mock-location-prevent-gps-spoofing

반응형