android 安全防护

一.混淆

之前的文章有介绍

二.配置防止抓包

  okHttpClient = new OkHttpClient.Builder()
                            //防止抓包设置
                            .proxySelector(new ProxySelector() {
                                @Override
                                public List<Proxy> select(URI uri) {
                                    return Collections.singletonList(Proxy.NO_PROXY);
                                }

                                @Override
                                public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {

                                }
                            })

三.加固

四.判断证书正确性

4.1 获取当前证书sha

 /**
     * 获取应用的签名
     *
     * @return
     */
    public static String getCertificateSHA1Fingerprint() {
        String hexString = "";


        //获取包管理器
        PackageManager pm = TUILogin.getAppContext().getPackageManager();

        //获取当前要获取 SHA1 值的包名,也可以用其他的包名,但需要注意,
        //在用其他包名的前提是,此方法传递的参数 Context 应该是对应包的上下文。
        String packageName = TUILogin.getAppContext().getPackageName();

        //签名信息
        Signature[] signatures = null;

        try {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                PackageInfo packageInfo = TUILogin.getAppContext().getPackageManager().getPackageInfo(TUILogin.getAppContext().getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES);
                SigningInfo signingInfo = packageInfo.signingInfo;
                signatures = signingInfo.getApkContentsSigners();
            } else {
                //获得包的所有内容信息类
                PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
                signatures = packageInfo.signatures;
            }


//        Signature[] signatures = packageInfo.signatures;
            byte[] cert = signatures[0].toByteArray();

            //将签名转换为字节数组流
            InputStream input = new ByteArrayInputStream(cert);

            //证书工厂类,这个类实现了出厂合格证算法的功能
            CertificateFactory cf = CertificateFactory.getInstance("X509");

            //X509 证书,X.509 是一种非常通用的证书格式
            X509Certificate c = null;
            c = (X509Certificate) cf.generateCertificate(input);


            //加密算法的类,这里的参数可以使 MD4,MD5 等加密算法
            MessageDigest md = MessageDigest.getInstance("SHA1");

            //获得公钥
            byte[] publicKey = md.digest(c.getEncoded());

            //字节到十六进制的格式转换
            hexString = byte2HexFormatted(publicKey);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (CertificateEncodingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hexString.trim();
    }

4.2 调用so包中方法去判断是否正确

extern "C"
JNIEXPORT jboolean JNICALL Java_com_tencent_qcloud_tuicore_util_EnvironmentUtil_isCertificate
        (JNIEnv *env, jobject thiz, jstring input) {
    char *out = jstringToChar(env, input);
    //hash为保存到so包中的证书sha1值 与获取到的值就行比较
    if (strcmp(hash, out) == 0) {
        return true;
    } else {
        return false;
    }
}

char *jstringToChar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

五.判断当前环境

5.1 判断当前环境是否root

  //判断设备是否已经被root
    public static boolean isDeviceRooted() {

        return checkRootMethod1() || checkRootMethod2() || checkRootMethod3();

    }

    private static boolean checkRootMethod1() {

        String buildTags = android.os.Build.TAGS;

        return buildTags != null && buildTags.contains("test-keys");

    }

    private static boolean checkRootMethod2() {

        String[] paths = {

                "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"

        };

        for (String path : paths) {

            if (new File(path).exists())

                return true;

        }

        return false;

    }

    private static boolean checkRootMethod3() {

        Process process = null;
        try {

            process = Runtime.getRuntime().exec(new String[]{

                    "/system/xbin/which", "su"

            });

            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));

            if (in.readLine() != null) return true;
            return false;

        } catch (Throwable t) {

            return false;

        } finally {
            if (process != null) process.destroy();

        }

    }

5.2 判断当前环境中是否存在xposed等app

   //判断设备中是否有xposed,易开发,root应用
    public static boolean isSafe() {
        PackageManager pm = TUILogin.getAppContext().getPackageManager();
        List<PackageInfo> list = pm
                .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
        for (PackageInfo packageInfo : list) {
            // 获取到应用所在包的名字,即在AndriodMainfest中的package的值。
            String packageName = packageInfo.packageName;
            //存在xposed框架
            if (packageName.equals("de.robv.android.xposed.installer")) {
                return false;
            } else if (packageName.equals("com.wrbug.developerhelper")) {
                //存在易开发
                return false;
            } else if (packageName.equals("formatfa.xposed.Fdex2")) {
                //存在Fdex2
                return false;
            } else if (packageName.equals("com.topjohnwu.magisk")) {
                //存在magisk
                return false;
            }else if (packageName.equals("com.topjohnwu.magisk")){
                return false;
            }else if (packageName.equals("eu.chainfire.supersu")){
                //存在supersu
                return false;
            }
        }
        return true;
    }

4.3 退出程序

extern "C"
JNIEXPORT void JNICALL
Java_com_tencent_qcloud_tuicore_util_EnvironmentUtil_exit(JNIEnv *env, jclass clazz) {
    exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值