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


90

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

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


2
Eclipse의 DDMS보기에서 사용할 수있는 위치 스푸핑 기능에 대해 묻는 것 같습니다.
Shawn Walton

2
나는 사람들이 속이는 것을 원하지 않는 위치 기반 게임을 가지고 있습니다. 그래서 나는 스푸핑을 차단하고 싶습니다. 두 가지 방법 중 하나가 발생할 수 있습니다. 설정 앱의 스푸핑 설정을 무시합니다. MockLocations에 대한 Settings.System 공급자를 찾거나 활성화되었는지 확인하려고합니다 (앱 중간에 리스너 포함).
Chrispix 2011

답변:


126

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

먼저 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까지 신뢰할 수없는 것처럼 보였습니다.


매우 흥미로운 관찰입니다. 특히 이것을 공유하는 마지막 +1.
ar-g

2
removeTestProvider 메서드에 대한 참고 사항입니다. 위치 관리자가 백그라운드에서 작동하도록 허용하면 사용자는 모의 앱으로 이동하여 모의 위치를 ​​다시 시작할 수 있습니다. 그러면 위치 관리자는 removeTestProvider를 다시 호출 할 때까지 모의 위치 수신을 시작합니다.
Timur_C 2015 년

4
또한 앱 에 작동 android.permission.ACCESS_MOCK_LOCATION권한이 있어야 removeTestProvider하는데 이것이 가장 큰 단점이라고 생각합니다.
Timur_C 2015 년

18
답변 해주셔서 감사합니다! 요점 : Android 6.0에서는 ALLOW_MOCK_LOCATION이 더 이상 사용되지 않습니다. 그리고 실제로 모의 위치에 대한 확인란도 없습니다. 위치 개체에서 위치가 가짜인지 옳지 않은지 확인할 수 있습니다. location.isFromMockProvider ()
Silwester

3
@Blackkara 결국 사용하지 않았습니다. isMockSettingsON(), Location.isFromMockProvider()areThereMockPermissionApps()앱의 블랙리스트 와 함께 사용자 정의 된 조합을 사용했습니다 . ACCESS_MOCK_LOCATION 예를 들어 HTC 및 삼성 장치에 권한 이있는 사전 설치된 시스템 앱이 많이 있습니다. 모든 합법적 인 앱의 화이트리스트가 더 좋을 것이지만 제 경우에는 가장 인기있는 위치 스푸핑 앱의 블랙리스트가 잘 작동했습니다. 그리고 장치가 루팅되었는지도 확인했습니다.
Timur_C

45

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

두 번째 표현이 거꾸로되어 있다고 확신합니다 (false를 반환해야 할 때 true를 반환). 나는 그것이해야한다고 생각 :isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
AjahnCharles

3
천만에요. 더 현대적인 답변을 게시 해 주셔서 감사합니다! 오늘의 정답입니다.
AjahnCharles

1
18 이상의 SDK에 대한 "위치"개체없이 어떻게 할 수 있습니까?
Ajit Sharma

35

이를 수행하는 유일한 방법은 위치 스푸핑이 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;

4
그러나 이것은 바보 증거가 아닙니다. 루팅되지 않은 장치의 사용자는 미래 시간이있는 모의 위치를 ​​설정 한 다음 모의 위치를 ​​비활성화 할 수 있으며 모의 위치는 여전히 활성 상태입니다. 더 나쁜 것은 네트워크 / Gps와 동일한 공급자 이름으로 모의 위치를 ​​호출 할 수 있으며 분명히 그 이름에서 가져옵니다.
Chrispix

3
또한 Fake GPS 는 루팅 된 기기에서 모의 ​​위치 설정이 필요하지 않습니다.
Paul Lammertsma

항상 :)이 fake.gps 응용 프로그램이 설치되지 않았 음을 확인하기 위해 확인 할 수
Chrispix

11
return !x대신 사용할 수 있습니다 if(x) return false; else return true.
CodesInChaos 2014-08-12

실제로 가짜 위치는 루팅 된 기기에서도 모의 위치 설정을 변경합니다.
PageNotFound

26

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

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

자세한 내용 을 알고 싶다면 이에 대한 자세한 블로그 게시물을 작성했습니다 . 요약하면 Location API에서 위치 업데이트를 구독 한 다음 가짜 GPS 앱을 켜고 각 Location.toString () 의 결과를 콘솔에 인쇄하면 다음과 같은 내용이 표시됩니다.

여기에 이미지 설명 입력

위치 업데이트 스트림에서 한 위치가 다른 위치와 동일한 좌표를 가지지 만 모의로 플래그가 지정되지 않고 위치 정확도가 훨씬 떨어지는 것을 확인하십시오.

이 문제를 해결하기 위해, 나는 유틸리티 클래스를 쓴 것이다 현대 안드로이드 버전 (최대 API 레벨 15)에 걸쳐 안정적으로 억제 모의 위치 :

LocationAssistant-Android에서 번거 로움없는 위치 업데이트

기본적으로 마지막으로 알려진 모의 위치에서 1km 이내에있는 모의가 아닌 위치를 "불신"하고이를 모의로 표시합니다. 모의가 아닌 많은 위치가 도착할 때까지이를 수행합니다. LocationAssistant은 모의 위치를 거부 할뿐만 아니라, 설정 및 위치 업데이트에 가입의 번거 로움의 대부분에서 당신을 unburdens 수 있습니다뿐만 아니라.

실제 위치 업데이트 만 수신하려면 (예 : 모의 억제) 다음과 같이 사용하십시오.

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 스푸핑을 방지하는 방법) 기본적으로 이것이 있습니다.

물론, 루팅 된 OS를 사용하면 일반 앱에서 감지 할 수없는 위치 정보를 스푸핑하는 방법을 찾을 수 있습니다.


링크 된 블로그 게시물을 간략히 요약해야합니다 (isFromMockProvider가 실패하는 위치).
AjahnCharles

@CodeConfident-발언에 감사드립니다! 그래도 무엇을 추가 해야할지 모르겠습니다. 내 대답의 두 번째 단락 블로그 게시물의 요약. .isFromMockProvider 가 산발적으로 그리고 예기치 않게 실패합니다. 이 기사에서 나는 이것을 발견하고 해결하기 위해 취한 단계를 더 자세히 설명합니다.
KlaasNotFound 2016-07-20

글쎄, 나는 그것이 SO의 의도에 반하는 것처럼 느껴지는 것을 이해하기 위해 당신의 기사로 넘어 가야했습니다. (1) 쇼 맛없어 위치 (모의로 플래그되지 않음) (2) 신속하게 제거하기위한 로직을 참고 (모의의 1km 이내 무시) 당신의 그림 삽입 : 내 최고의 제안 될 것이다
AjahnCharles

알겠습니다. OP의 맥락에서 .isFromMockProvider () 가 신뢰할 수없는 이유에 대한 세부 사항은 너무 관련이 없다고 생각합니다. 그러나 더 큰 그림을 위해 언급 한 세부 사항을 추가하려고 시도합니다. 피드백을 주셔서 감사합니다!
KlaasNotFound 2016-07-20

1
사용자가 Google Play 서비스를 설치하지 않은 경우 어떻게 되나요?
Yuriy Chernyshov

6

기지국의 일반적인 위치를 알게 된 경우 현재 기지국이 주어진 위치와 일치하는지 확인할 수 있습니다 (10 마일 이상과 같은 큰 오차 범위 내에서).

예를 들어 사용자가 특정 위치 (예 : 상점)에있는 경우에만 앱에서 기능을 잠금 해제하는 경우 GPS와 기지국을 확인할 수 있습니다. 현재는 GPS 스푸핑 앱이 기지국을 스푸핑하지 않으므로 전국의 누군가가 귀하의 특수 기능에 스푸핑을 시도하고 있는지 확인할 수 있습니다 (예를 들어 Disney Mobile Magic 앱을 생각하고 있습니다).

이것은 Llama 앱이 기본적으로 위치를 관리하는 방법입니다. 기지국 ID를 확인하는 것이 GPS보다 배터리 집약적이지 않기 때문입니다. 특정 위치에는 유용하지 않지만 집과 직장이 몇 마일 떨어져 있으면 두 일반 위치를 매우 쉽게 구분할 수 있습니다.

물론 이것은 사용자가 셀 신호를 가지고 있어야합니다. 그리고 모든 네트워크 제공 업체에서 해당 지역의 모든 셀 타워 ID를 알아야합니다. 그렇지 않으면 거짓 음성의 위험이 있습니다.


1
고마워, 꽤 좋은 생각이다. 나는 그것을 조사해야 할 수도 있습니다. 감사합니다
Chrispix 2012

3

이 코드는 매우 간단하고 유용합니다.

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

위의 isMockLocationEnabled 메서드보다 훨씬 더 나은 버전입니다.
setzamora

AppOpsManager.checkOp () throws SecurityException 앱이이 작업에서 충돌하도록 구성된 경우. 좋아요 : java.lang.SecurityException : uid 11151의 packagename에서 MOCK_LOCATION을 수행 할 수 없습니다. 이 메서드는 "앱이 위치를 모의 할 수 있는지 여부"를 감지하려고합니다. 그러나 "수신 된 위치가 조롱 된 경우"는 아닙니다.
Sergio

@Sergio는 "당신의 앱이 위치를 모의 할 수있는 경우"라는 말은 현재 앱이 위치를 모의 할 수있는 권한이 있는지를 의미합니다.
Victor Laerte

@VictorLaerte 마지막으로 주제의 맥락을 살펴 보았습니다 : / 맞습니다. 그러나 질문은 "수신 된 위치가 모의인지 모의 공급자로부터받은 것인지 감지하는 방법"이었습니다. 또는 가짜 위치를 무시하는 방법.
Sergio

2

이 스크립트는 모든 버전의 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
    }

1

Google Maps Geolocation API를 사용하여 기지국 삼각 측량 또는 Wifi 액세스 포인트 정보를 기반으로 추가 검사를 추가 할 수 있습니다.

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

결과를 사이트 와 비교할 수 있습니다.

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();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.