如何防止 Rooted Android 手机安装我的应用程序?

Posted

技术标签:

【中文标题】如何防止 Rooted Android 手机安装我的应用程序?【英文标题】:How to prevent Rooted Android Phones from Installing my app? 【发布时间】:2015-02-16 21:13:07 【问题描述】:

在此上下文中的目的是防止在排行榜中报告虚假的高分(我的应用是游戏)。 Flappy Birds 发生了这种情况 - 请参阅此链接 - http://www.androidpit.com/forum/589832/flappy-bird-high-score-cheat-set-your-own-high-score

由于 root 用户可以用他的手机做任何他想做的事情,我想其他解决方法都不起作用,唯一的解决方案是阻止 root 用户安装应用程序。我对吗?有没有办法做到这一点?

PS:我的游戏并不总是需要互联网连接,因此当它发生在另一台服务器上时报告分数是不可行的。只有当互联网连接可用时,高分才会报告到排行榜。

【问题讨论】:

【参考方案1】:

我也有类似的要求。我无法实现应用程序不应安装在有根设备上,但我使用了一种解决方法:

检查您的设备是否植根于您的活动的onResume。 如果它已root,只需向他显示警报“此设备已root。您无法使用此应用程序。”,然后退出应用程序。

示例:

@Override
protected void onResume() 
    // TODO Auto-generated method stub
    super.onResume();
    if(new DeviceUtils().isDeviceRooted(getApplicationContext()))
        showAlertDialogAndExitApp("This device is rooted. You can't use this app.");
    



public void showAlertDialogAndExitApp(String message) 

    AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
    alertDialog.setTitle("Alert");
    alertDialog.setMessage(message);
    alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
            new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int which) 
                    dialog.dismiss();
                    Intent intent = new Intent(Intent.ACTION_MAIN);
                    intent.addCategory(Intent.CATEGORY_HOME);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    finish();
                
            );

    alertDialog.show();

DeviceUtis.java 是一个实用程序类,它在设备是否被 root 时返回。

public class DeviceUtils 

    public Boolean isDeviceRooted(Context context)
        boolean isRooted = isrooted1() || isrooted2();
        return isRooted;
    

    private boolean isrooted1() 

        File file = new File("/system/app/Superuser.apk");
        if (file.exists()) 
            return true;
        
        return false;
    

    // try executing commands
    private boolean isrooted2() 
        return canExecuteCommand("/system/xbin/which su")
                || canExecuteCommand("/system/bin/which su")
                || canExecuteCommand("which su");
    

我们使用了 5 种方法进行测试,我这里只展示了 2 种。您可以使用任何您认为不错的方法。

希望这会有所帮助。

P.S:我已将此调用放在所有活动的onResume 中,因为用户(有意进行黑客攻击)可以安装应用程序、导航到其他活动,然后是 root 设备。

【讨论】:

你能说,在安装应用程序之前,就像在安卓设备上安装应用程序一样,我们可以检查设备是否已root吗? 但是为什么在 onResume() 中,为什么不在 onCreate() 方法中,我认为如果它在所有活动中 onCreate() 会很好。 用户可以通过按返回按钮绕过警报。【参考方案2】:
private static boolean canExecuteCommand(String command) 
        boolean executedSuccesfully;
        try 
            Runtime.getRuntime().exec(command);
            executedSuccesfully = true;
         catch (Exception e) 
            executedSuccesfully = false;
        

        return executedSuccesfully;
    

【讨论】:

这里的命令是什么?如果你能解释它是如何工作的,那将会被应用。【参考方案3】:

没有必要阻止具有根电话的用户,因为这是正常的用户行为。那么,如果您在游戏中没有在线连接以获取高分、应用内购买等,您会担心什么样的危险或损害?

玩家想通过作弊方式到达最后一关或本地(!)排行榜的顶部?伤害在哪里?

通过阻止您的游戏在有根设备上运行,您只会排斥应用的合法用户。

编辑:

使用云保存服务来保存玩家的高分。如果离线,它将被加密并存储在设备上。下次在线时,您会读取高分并将其发送到播放服务。播放服务提供了您可能还需要的反盗版功能。

【讨论】:

很抱歉让您感到困惑。我已经改写了PS。我的游戏需要互联网连接(向排行榜报告分数)但并非总是如此(因此在游戏结束时检查分数是否“有效与否”总是失败)。 @DroidHeaven 好吧,那我理解错了。您是否使用 Google Play 服务或推出自己的排行榜系统? 我使用 Google Play 服务 @DroidHeaven 那就更简单了。使用云保存服务保存玩家的高分。如果离线,它将被加密并存储在设备上。下次在线时,您会读取高分并将其发送到播放服务。播放服务提供了您可能还需要的反盗版功能。 aah 现在我很困惑我应该接受哪个答案。你的和下面的都是有效的:)【参考方案4】:

使用 Kotlin 扩展,您可以轻松检查设备是否已植根。下面是可以帮助你的代码

DeviceUtils.kt

object DeviceUtils 
    fun isDeviceRooted(context: Context?): Boolean 
        return isRooted1 || isRooted2
    

    private val isRooted1: Boolean
        get() 
            val file = File("/system/app/Superuser.apk")
            return file.exists()
        

    // try executing commands
    private val isRooted2: Boolean
        get() = (canExecuteCommand("/system/xbin/which su")
                || canExecuteCommand("/system/bin/which su")
                || canExecuteCommand("which su"))

    private fun canExecuteCommand(command: String): Boolean 
        return try 
            Runtime.getRuntime().exec(command)
            true
         catch (e: Exception) 
            false
        
    

Extention.kt

fun Activity.checkDeviceRoot(): Boolean 
    return if (DeviceUtils.isDeviceRooted(this)) 
        AlertDialog.Builder(this)
                .setMessage("Your device is rooted. you can not use this app into rooted device.")
                .setCancelable(false)
                .setPositiveButton(R.string.alert_ok)  _, _ ->
                    exitProcess(0)
                .show()
        true
     else 
        false
    

如何使用这个扩展:

class MyActivity : Activity
    ...
    override 
    fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        if(checkDeviceRoot())
            return
        ....
        ....
    

希望这个答案能帮到你。

【讨论】:

【参考方案5】:

我们在 Playstore 控制台中有一个 SafetyNet 排除 选项,我们可以使用它来防止应用出现在 Playstore 中以便在有根设备上下载。 Google play servicesSafety Net Attestation API,我们可以通过该 API 评估设备并确定它是否被植根/篡改。 想要处理root设备的朋友,请看我的回答:https://***.com/a/58304556/3908895

【讨论】:

以上是关于如何防止 Rooted Android 手机安装我的应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

capture.pcap怎么查看

Android - 如何防止按下音量或相机键时手机屏幕打开?

Android App 如何防止抓包

如何防止Android程序被反编译

如何防止应用在android中切换多视图?

我可以防止手机在网页上休眠吗