モックの場所を無効化/確認します(gpsスプーフィングを防止します)


90

AndroidでGPSスプーフィングを防止/検出するための最良の方法を探しています。これがどのように達成されるか、そしてそれを止めるために何ができるかについての提案はありますか?GPSをスプーフィングするには、ユーザーがモックロケーションをオンにする必要があると思います。これを行うと、GPSをスプーフィングできますか?

モックロケーションが有効になっているかどうかを検出する必要があると思いますか?他に何か提案はありますか?


2
彼はEclipseのDDMSビューで利用できるロケーションスプーフィング機能について質問していると思います。
ショーンウォルトン

2
私は人をだましてほしくないロケーションベースのゲームを持っているので、なりすましをブロックしたいのですが、2つの方法のいずれかで発生する可能性があることを理解しています。モックロケーションを有効にし、低レベルのなりすましを行うカスタムイメージを構築します。設定アプリのなりすまし設定は無視します。MockLocationsのSettings.Systemプロバイダーを見つけようとするか、それが有効になっているかどうかを確認します(アプリの中央にリスナーがあります)。
Chrispix 2011

回答:


125

私はここでいくつかの調査と結果の共有を行いました。これは他の人にも役立つかもしれません。

まず、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;
}

上記の両方の方法(1番目と2番目)が当てはまる場合、その場所がなりすましまたは偽物である可能性が高くなります。

これで、Location Managerの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(〜)は、JellyBean以降のバージョンで非常にうまく機能することを確認しました。このAPIは、Ice CreamSandwichまで信頼できないようでした。


非常に興味深い観察。特にこれを共有するための最後の+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

2
@Blackkaraやっぱり使わなかった。私は、カスタマイズの組み合わせを使用しisMockSettingsON()Location.isFromMockProvider()そしてareThereMockPermissionApps()アプリケーションのブラックリストを持ちます。ACCESS_MOCK_LOCATION HTCやSamsungデバイスなど、許可を得たプリインストールされたシステムアプリがたくさんあります。すべての正当なアプリのホワイトリストの方が良いでしょうが、私の場合、最も人気のあるロケーションスプーフィングアプリのブラックリストがうまく機能しました。また、デバイスがルート化されているかどうかも確認しました。
Timur_C

45

API 18以降、オブジェクトLocationにはメソッド.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");
}

2番目の式が逆方向であると確信しています(falseを返す必要がある場合はtrueを返します)。私はそれがすべきだと思います:isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
AjahnCharles 2016

3
どういたしまして。より現代的な答えを投稿してくれてありがとう!本当にこれが今日の正解です。
AjahnCharles 2016

1
18を超えるSDKの「location」オブジェクトなしでそれを行うにはどうすればよいですか?
アジートシャルマ2017年

35

これを行う唯一の方法は、ロケーションスプーフィングがMockLocationsを防ぐことを防ぐことだと思われます。欠点は、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
さらに、偽のGPSは、ルート化されたデバイスのモックロケーション設定を必要としません。
Paul Lammertsma 2012年

fake.gpsアプリがインストールされていないことを常に確認できます:)
Chrispix 2012年

11
return !x代わりに使用できますif(x) return false; else return true
CodesInChaos 2014

実際、偽の場所は、ルート化されたデバイスでもモックの場所の設定を変更します。
PageNotFound 2014

25

数年後、このスレッドに出くわしました。2016年には、ほとんどのAndroidデバイスのAPIレベルが18以上になるため、Fernandoが指摘しているようにLocation.isFromMockProvider()に依存する必要があります。

私はさまざまなAndroidデバイスとディストリビューションで偽の/モックの場所を広範囲に実験しました。残念ながら、.isFromMockProvider()は100%信頼できるわけではありません。たまに、偽の場所がモックとしてラベル付けされないことがあります。これは、Google LocationAPIの誤った内部融合ロジックが原因のようです。

詳細を知りたい場合は、これについて詳細なブログ投稿を書きました。要約すると、Location APIから位置情報の更新をサブスクライブし、偽のGPSアプリをオンにして、各Location.toString()の結果をコンソールに出力すると、次のように表示されます。

ここに画像の説明を入力してください

場所の更新のストリームで、1つの場所が他の場所と同じ座標を持っているが、モックとしてフラグが付けられておらず、場所の精度がはるかに低いことに注意してください。

この問題を解決するには、私は、ユーティリティクラスを書いただろう確実にすべての現代のAndroidのバージョン(APIレベル15以上)を越えモック場所を抑制します:

LocationAssistant-Androidでの手間のかからない位置更新

基本的に、最後に認識されたモックロケーションから1 km以内にある非モックロケーションを「不信」にし、モックとしてラベル付けします。これは、モックではない場所がかなりの数到着するまで行われます。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 2016

@ CodeConfident-発言ありがとうございます!何を追加すればいいのかわかりません。私の答えの2番目の段落があるブログの記事の要約。.isFromMockProviderは、散発的かつ予期せずに失敗します。この記事では、これを発見して修正するために行った手順について詳しく説明します。
KlaasNotFound 2016

さて、私はあなたの記事にジャンプして、SOの意図に反しているように感じるものを理解することを余儀なくされました。私の最善の提案は次のとおりです:(1)危険な場所(モックとしてフラグが立てられていない)を示す写真を挿入し、(2)それらを排除するためのロジックをすばやくメモします(モックから1km以内を無視します)
AjahnCharles 2016

わかりました。OPのコンテキストでは .isFromMockProvider()が信頼できない理由の詳細はあまり関係がないと思います。しかし、私はあなたが全体像のために言及した詳細を追加しようとします。フィードバックをお寄せいただきありがとうございます!
KlaasNotFound 2016

1
ユーザーがGooglePlay開発者サービスをインストールしていない場合はどうなりますか?
Yuriy Chernyshov 2016

6

セルタワーの一般的な場所を知っている場合は、現在のセルタワーが指定された場所と一致するかどうかを確認できます(10マイル以上などの大きなエラーマージン内)。

たとえば、ユーザーが特定の場所(店舗など)にいる場合にのみアプリが機能のロックを解除する場合は、GPSとセルタワーを確認できます。現在、gpsスプーフィングアプリもセルタワーをスプーフィングしていないため、全国の誰かがあなたの特別な機能にスプーフィングしようとしているのかどうかを確認できます(たとえば、Disney Mobile Magicアプリを考えています)。

これは、セルタワーIDのチェックがgpsよりもはるかにバッテリー消費が少ないため、Llamaアプリがデフォルトで場所を管理する方法です。非常に特定の場所には役立ちませんが、自宅と職場が数マイル離れている場合は、2つの一般的な場所を非常に簡単に区別できます。

もちろん、これにはユーザーがセル信号を持っている必要があります。また、エリア内のすべてのセルタワー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()はSecurityExceptionをスローします。例:java.lang.SecurityException:uid11151のpackagenameはMOCK_LOCATIONの実行を許可されていません。このメソッドは、「アプリが場所をモックできるかどうか」を検出しようとしています。しかし、「受け取った場所がモックされている場合」ではありません。
セルジオ

@Sergioは、「アプリが場所をモックできる場合」とは、現在のアプリに場所をモックする権限があるかどうかを意味します。
ビクターレルテ

@VictorLaerte私はトピックのコンテキストを最後に持っています:/そうです。しかし、問題は、「受信した場所がモックされているのか、モックプロバイダーからのものであるのかを検出する方法」でした。または、偽の場所を無視する方法。
セルジオ

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

セルタワーの三角測量またはWifiアクセスポイントの情報に基づいて、次のコマンドを使用してチェックを追加できます。 Google Maps Geolocation APIます

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.