如何以编程方式查找root设备?

时间:2014-07-02 05:39:30

标签: android

在安装我的应用程序之前,我希望它检查设备是否已植根。我使用了以下代码

private static boolean isRooted()

                 return findBinary("su");
        }
    public static boolean findBinary(String binaryName) {

        boolean found = false;
        if (!found) {

            String[] places = {"/sbin/", "/system/bin/", "/system/xbin/", "/data/local/xbin/",
                    "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/"};
            for (String where : places) {
                if ( new File( where + binaryName ).exists() ) {

                    found = true;
                    break;
                }
            }
        }
        return found;
    } 

它工作正常。但我听说过文件名" su"可以更改,也可以更改名为" su"的文件。可以在非根设备中创建。在这种情况下,这个源是不可靠的。所以我想知道一些其他的方法来找到除了搜索" su"以外的有根设备。    我使用了以下代码

   Public static boolean checkRootMethod1()

     {
        String buildTags = android.os.Build.TAGS;

        if (buildTags != null && buildTags.contains("test-keys")) {

            return true;
        }

        return false;
    }

它无法正常工作。对于root设备,它按预期工作。但对于一些无根设备也显示为rooted.Since输出变化为不同的设备,我找不到解决方案..任何帮助将不胜感激< / p>

3 个答案:

答案 0 :(得分:3)

如果您想限制在根设备上使用应用程序,则必须考虑两点:
1)限制在植根设备中下载
2)限制已植根设备中应用的 sideloading

请按照以下步骤限制从Play商店下载:
1)转到商店控制台。
2)在左侧菜单上,转到发布管理。
3)然后,转到设备目录。
4)然后,您将获得3个选项卡选项,转到“排除的设备”。
5)您将获得一个选项来指定排除规则。点击管理排除规则。
6)您可以看到SafetyNet排除项的选择器。选择选项:排除不通过基本完整性的设备以及未经google认证的设备。

请按照以下步骤限制应用的侧面加载:
1)使用以下命令获取API密钥:https://developer.android.com/training/safetynet/attestation.html#obtain-api-key

2)在gradle文件中添加safetynet依赖项。
implementation 'com.google.android.gms:play-services-safetynet:17.0.0'

3)我在BaseActivity中放置了下面的代码,我的其他活动也在其中进行了扩展,因此,如果拥有根设备的黑客尝试侧重加载并尝试输入任何活动,则将执行下面的代码。

    private void ifGooglePlayServicesValid() {
        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(getApplicationContext())
                == ConnectionResult.SUCCESS) {
            // The SafetyNet Attestation API is available.
            callSafetyNetAttentationApi();

        } else {
            // Prompt user to update Google Play services.
        }
    }

    private void callSafetyNetAttentationApi() {
        SafetyNet.getClient(this).attest(generateNonce(), SAFETY_NET_CHECK_API_KEY)
            .addOnSuccessListener(this,
                response -> {
                    // Use response.getJwsResult() to get the result data.
                    String jwsResponse = decodeJws(response.getJwsResult());
                    try {
                        JSONObject attestationResponse = new JSONObject(jwsResponse);
                        boolean ctsProfileMatch = attestationResponse.getBoolean("ctsProfileMatch");
                        boolean basicIntegrity = attestationResponse.getBoolean("basicIntegrity");
                        if (!ctsProfileMatch || !basicIntegrity) {
                            // this indicates it's rooted/tampered device
                        }
                    } catch (JSONException e) {
                        // json exception
                    }
                })
            .addOnFailureListener(this, e -> {
                // An error occurred while communicating with the service.
            });
    }

    public String decodeJws(String jwsResult) {
        if (jwsResult == null) {
            return null;
        }
        final String[] jwtParts = jwsResult.split("\\.");
        if (jwtParts.length == 3) {
            return new String(Base64.decode(jwtParts[1], Base64.DEFAULT));
        } else {
            return null;
        }
    }

    private byte[] generateNonce() {
        byte[] nonce = new byte[16];
        new SecureRandom().nextBytes(nonce);
        return nonce;
    }
  

SAFETY_NET_CHECK_API_KEY是第一步中获得的密钥。

Attestation API返回一个JWS响应,如下所示:

{
  "timestampMs": 9860437986543,
  "nonce": "R2Rra24fVm5xa2Mg",
  "apkPackageName": "com.package.name.of.requesting.app",
  "apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
                                  certificate used to sign requesting app"],
  "ctsProfileMatch": true,
  "basicIntegrity": true,
}

JWS响应包含指示设备状态的 ctsProfileMatch basicIntegrity

enter image description here
参考:https://developer.android.com/training/safetynet/attestation.html

答案 1 :(得分:0)

尝试以下代码: -

 /**
   * Checks if the device is rooted.
   *
   * @return <code>true</code> if the device is rooted, <code>false</code> otherwise.
   */
  public static boolean isRooted() {

    // get from build info
    String buildTags = android.os.Build.TAGS;
    if (buildTags != null && buildTags.contains("test-keys")) {
      return true;
    }

    // check if /system/app/Superuser.apk is present
    try {
      File file = new File("/system/app/Superuser.apk");
      if (file.exists()) {
        return true;
      }
    } catch (Exception e1) {
      // ignore
    }

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

  // executes a command on the system
  private static boolean canExecuteCommand(String command) {
    boolean executedSuccesfully;
    try {
      Runtime.getRuntime().exec(command);
      executedSuccesfully = true;
    } catch (Exception e) {
      executedSuccesfully = false;
    }

    return executedSuccesfully;
  }

见以下链接: -

Determine if running on a rooted device

Determining if an Android device is rooted programatically?

答案 2 :(得分:0)

public static boolean checkRooted()
{
    try
    {
        Process p = Runtime.getRuntime().exec("su", null, new File("/"));
        DataOutputStream os = new DataOutputStream( p.getOutputStream());
        os.writeBytes("pwd\n");
        os.writeBytes("exit\n");
        os.flush();
        p.waitFor();
        p.destroy();
    }
    catch (Exception e)
    {
        return false;
    }

    return true;
}