禁用/检查模拟位置(防止gps欺骗)

Chr*_*pix 83 gps android spoof

希望找到防止/检测Android上的GPS欺骗的最佳方法.关于如何实现这一点的任何建议,以及可以做些什么来阻止它?我猜测用户必须打开模拟位置欺骗GPS,如果这样做,那么他们可以欺骗GPS吗?

我想我只需要检测是否启用了Mock Locations?还有其他建议吗?

Jam*_*aaz 117

我在这里做了一些调查并分享我的结果,这可能对其他人有用.

首先,我们可以检查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;
}
Run Code Online (Sandbox Code Playgroud)

其次,我们可以检查设备中是否有其他应用程序正在使用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;
}
Run Code Online (Sandbox Code Playgroud)

如果上述两种方法,第一种和第二种方法都属实,则很有可能位置可能是欺骗性的或假的.

现在,使用位置管理器的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);
Run Code Online (Sandbox Code Playgroud)

我已经看到removeTestProvider(〜)在Jelly Bean及其版本上运行良好.直到冰淇淋三明治,这种API似乎不可靠.

  • 谢谢你的回答!只是一点:在Android 6.0中,不推荐使用ALLOW_MOCK_LOCATION.实际上,模拟位置也没有复选框.可以从位置对象检查位置是否是假的:**location.isFromMockProvider()** (17认同)
  • 你的应用程序也必须具有'android.permission.ACCESS_MOCK_LOCATION`权限才能使`removeTestProvider`正常工作,我认为这是最大的劣势. (4认同)
  • 关于removeTestProvider方法的注意事项.如果您允许位置管理器在后台运行,则用户可以转到模拟应用程序并重新启动模拟位置.然后,您的位置管理员将开始接收模拟位置,直到您再次调用removeTestProvider. (2认同)
  • @Blackkara我毕竟没用过。我将“ isMockSettingsON()”,“ Location.isFromMockProvider()”和“ areThereMockPermissionApps()”的自定义组合与应用黑名单结合使用。许多预先安装的系统应用程序都具有“ ACCESS_MOCK_LOCATION”权限,例如在HTC和Samsung设备上。将所有合法应用程序列入白名单可能会更好,但就我而言,最流行的位置欺骗应用程序的黑名单效果很好。我还检查了设备是否已植根。 (2认同)

Fer*_*ndo 36

从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");
}
Run Code Online (Sandbox Code Playgroud)

  • 别客气.感谢您发布更现代的答案!真的,这是今天的正确答案. (2认同)

Chr*_*pix 35

似乎唯一的方法是防止位置欺骗阻止MockLocations.不足之处是有些用户使用蓝牙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;
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用`return!x`而不是`if(x)返回false; 否则返回真实. (11认同)
  • 但这不是万无一失的.非root用户设备上的用户仍然可以设置模拟位置,具有未来的时间,然后禁用模拟位置,并且模拟位置仍处于活动状态.更糟糕的是,他们可以将模拟位置称为与Network/Gps相同的提供商名称,它显然可以从中获取... (4认同)
  • 此外,[假GPS](https://play.google.com/store/apps/details?id=com.lexa.fakegps)不需要在有根设备上进行模拟位置设置. (2认同)

Kla*_*und 23

几年后偶然发现了这个帖子.在2016年,大多数Android设备的API级别> = 18,因此应该依赖于Fernando指出的Location.isFromMockProvider().

我在不同的Android设备和发行版上广泛试验了假/模拟位置.不幸的是.isFromMockProvider()不是100%可靠.每隔一段时间,一个虚假的位置就不会被标记为模拟.这似乎是由于Google Location API中的一些错误的内部融合逻辑.

如果你想了解更多,我写了一篇关于此详细博客文章.总而言之,如果您从Location API订阅位置更新,然后打开假GPS应用程序并将每个Location.toString()的结果打印到控制台,您将看到如下内容:

在此输入图像描述

请注意,在位置更新流中,一个位置与其他位置具有相同的坐标,但未标记为模拟并且位置精度较差.

为了解决这个问题,我编写了一个实用程序类,它可以在所有现代Android版本(API级别15及更高版本)中可靠地抑制Mock位置:

LocationAssistant - Android上的无忧位置更新

基本上,它"不信任"在最后一个已知模拟位置1公里范围内的非模拟位置,并将它们标记为模拟.这样做直到大量的非模拟位置到达.该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
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

onNewLocationAvailable()现在只能使用真实位置信息调用.您需要实现一些更多的侦听器方法,但在您的问题(如何防止GPS欺骗)的背景下,这基本上就是这样.

当然,使用root操作系统,您仍然可以找到欺骗正常应用程序无法检测的位置信息的方法.


Ste*_*ger 6

如果您碰巧知道了蜂窝塔的一般位置,您可以检查当前的蜂窝塔是否与给定的位置匹配(在大的误差范围内,如10英里或更远).

例如,如果您的应用仅在用户位于特定位置(例如您的商店)时解锁功能,您可以检查gps以及手机信号塔.目前,没有gps欺骗应用程序也会欺骗手机信号塔,所以你可以看到全国各地的人是否只是试图欺骗他们的方式进入你的特殊功能(我想的是迪士尼移动魔术应用程序,举个例子).

这是Llama应用程序默认管理位置的方式,因为检查单元塔ID比gps的电池密集程度要低得多.它对于非常特定的位置没有用,但如果家和工作距离几英里,它可以非常容易地区分两个一般位置.

当然,这将要求用户完全具有小区信号.而且你必须知道该地区的所有蜂窝塔ID - 在所有网络提供商 - 或者你会冒错误的风险.