Android apk安全全解

大家都知道我们apk是很容易被有些人破解的,特别是涉及到支付方面的app,如果被有心人换掉支付,二次打包那就是很可怕的事情了。

今天来给大家分享一些关于app安全方面的技术:

1.接口参数加密签名

市面上常用的加密签名方式有两种:MD5,RSA

MD5加密相信大家都已经很熟悉了,这里就不贴代码了。

RSA加密算法代码如下:

public class RSA{
   
   public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
   
   /**
   * RSA签名
   * @param content 待签名数据
   * @param privateKey 商户私钥
   * @param input_charset 编码格式
   * @return 签名值
   */
   public static String sign(String content, String privateKey, String input_charset)
   {
        try 
        {
           PKCS8EncodedKeySpec priPKCS8   = new PKCS8EncodedKeySpec( Base64.decode(privateKey) );
           KeyFactory keyf             = KeyFactory.getInstance("RSA");
           PrivateKey priKey           = keyf.generatePrivate(priPKCS8);

            java.security.Signature signature = java.security.Signature
                .getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update( content.getBytes(input_charset) );

            byte[] signed = signature.sign();
            
            return Base64.encode(signed);
        }
        catch (Exception e)
        {
           e.printStackTrace();
        }
        
        return null;
    }
   
   /**
   * RSA验签名检查
   * @param content 待签名数据
   * @param sign 签名值
   * @param alipay_public_key 支付宝公钥
   * @param input_charset 编码格式
   * @return 布尔值
   */
   public static boolean verify(String content, String sign, String alipay_public_key, String input_charset)
   {
      try 
      {
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           byte[] encodedKey = Base64.decode(alipay_public_key);
           PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
         java.security.Signature signature = java.security.Signature
         .getInstance(SIGN_ALGORITHMS);
         signature.initVerify(pubKey);
         signature.update( content.getBytes(input_charset) );
         boolean bverify = signature.verify( Base64.decode(sign) );
         return bverify;
         
      } 
      catch (Exception e)
      {
         e.printStackTrace();
      }
      return false;
   }

}

2.混淆自己的代码

在proguard-rules.pro文件编写自己的混淆规则,

-keep class com.letui.sdk.base.BaseLeTuiChannelSdk{*; }
-keep class com.letui.sdk.base.BaseLeTuiPluginSdk{*; }
-keep class com.letui.sdk.util.ResUtil{*; }
-keep class com.letui.sdk.view.** {*;}
在gradle照片那个配置如下,执行
gradlew makeJar命令,就可以生成混淆后的jar文件了

task makeJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") {
    // 未混淆的jar路径
    injars 'build/intermediates/intermediate-jars/release/classes.jar'
    // 混淆后的jar输出路径
    outjars 'build/outputs/ltsdk.jar'
    // 混淆协议
    configuration 'proguard-rules.pro'
},
混淆后的文件如下:

3.校验签名文件,大家都知道,如果apk被二次打包,签名文件肯定会不一样,如果我们在代理里面去校验签名文件,判断使我们自己的签名就让程序去运行,如果不是我们的签名就闪退App,就相当于给我们的apk又加了一层保护壳。最好是把校验签名放在c文件里面,可以增加破解难度。代码如下:

JNIEXPORT jstring JNICALL Java_com_letui_sdk_DR_1JNITest_getSuccessKey
        (JNIEnv *env, jclass jclazz, jobject contextObject,jint pid){

    jclass native_class = env->GetObjectClass(contextObject);
    jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
    jobject pm_obj = env->CallObjectMethod(contextObject, pm_id);
    jclass pm_clazz = env->GetObjectClass(pm_obj);
// 得到 getPackageInfo 方法的 ID
    jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jclass native_classs = env->GetObjectClass(contextObject);
    jmethodID mId = env->GetMethodID(native_classs, "getPackageName", "()Ljava/lang/String;");
    jstring pkg_str = static_cast<jstring>(env->CallObjectMethod(contextObject, mId));
// 获得应用包的信息
    jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64);
// 获得 PackageInfo 类
    jclass pi_clazz = env->GetObjectClass(pi_obj);
// 获得签名数组属性的 ID
    jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures", "[Landroid/content/pm/Signature;");
    jobject signatures_obj = env->GetObjectField(pi_obj, signatures_fieldId);
    jobjectArray signaturesArray = (jobjectArray)signatures_obj;
    jsize size = env->GetArrayLength(signaturesArray);
    jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0);
    jclass signature_clazz = env->GetObjectClass(signature_obj);

    //第一种方式--检查签名字符串的方式
    jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;");
    jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id));
    char *c_msg = (char*)env->GetStringUTFChars(str,0);
    LOGD("########## i = %s", c_msg);
    if(strcmp(c_msg,RELEASE_SIGN)==0)//签名一致  返回合法的 api key,否则返回错误
    {
        //这里说明是我们的签名,可以返回我们的key
    }else
    { 
   //这里说明不是我们的签名,可以闪退app
} //第二种方式--检查签名的hashCode的方式 /* jmethodID int_hashcode = env->GetMethodID(signature_clazz, "hashCode", "()I"); jint hashCode = env->CallIntMethod(signature_obj, int_hashcode); if(hashCode == RELEASE_SIGN_HASHCODE) { return (env)->NewStringUTF(AUTH_KEY); }else{ return (env)->NewStringUTF("错误"); } */ }

4.so文件也不是非常安全的,这里附上破解链接:

https://blog.csdn.net/qq591840685/article/details/20869491,我们为了增加破解难度,可以混淆so文件,http://www.liuling123.com/2016/06/so_method_mix.html。


猜你喜欢

转载自blog.csdn.net/qq_37792992/article/details/80487137