• Android App 签名保护demo


    近来闲的无聊,看了看Android 应用安全防护和逆向分析,里面有个使用apk签名防止反编译的篇章。

    实践了一下。

    有两种方式,

    1. 可在java层判定

    获取签名的java代码

    public static String getSignature(){
            Context context = mContext;
            try{
                PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
                        PackageManager.GET_SIGNATURES);
                Signature[]signatures = packageInfo.signatures;
                StringBuilder stringBuilder = new StringBuilder();
                for(Signature signature : signatures){
                    stringBuilder.append(signature.toCharsString());
                }
                return stringBuilder.toString();
            } catch (PackageManager.NameNotFoundException e){
                e.printStackTrace();
            }
            return "";
        }

    然后简单判定一下:

    private boolean isOwnApp(){
            if (APP_SIGN.equalsIgnoreCase(getSignature())){
                return true;
            }
            return false;
        }

    这种方式比较简单,但也很容易被破解。

    2. 在jni层判断,编译一个so

    调用上面定义的获取签名函数和app_sig对比

    const char *app_sig = "xxx";
    
    JNIEXPORT jboolean JNICALL Java_com_example_signatureprotect_SignatureJni_isEqual
      (JNIEnv *env, jclass jcla, jstring sig)
      {
            char *className = "com/example/signatureprotect/MainActivity";
            jclass clazz = (env)->FindClass(className);
            if (clazz == NULL)
            {
                LOGI("do not find class '%s'", className);
                return false;
            }
            LOGI("find class '%s'", className);
            jmethodID method = (env)->GetStaticMethodID( clazz, "getSignature", "()Ljava/lang/String;");
            if (method == NULL)
            {
                 LOGI("do not find method");
                 return false;
            }
    
            LOGI("find method");
            jstring obj = (jstring)(env)->CallStaticObjectMethod( clazz, method);
            if (obj == NULL){
                LOGI("invoke error: %p", obj);
                return false;
            }
    
            LOGI("invoke method");
            const char *str = (env)->GetStringUTFChars(obj, 0);
            LOGI("str %s", str);
            int cmpval = strcmp(str, app_sig);
            LOGI("strcmp pass");
            if (cmpval == 0)
            {
                LOGI("equal return true");
                return true;
            }
            (env)->ReleaseStringUTFChars(obj,str);
            LOGI("equal return false");
            return false;
      }

    可以在java层调用,但是这样调用跟上面的第一种方法区别不大,可在java层破解。

     private boolean isOwnApp2(){
            if (SignatureJni.isEqual("")){
                return true;
            }
            return false;
        }

    可以在加载so的时候判断,重写JNI_OnLoad函数即可

    jint JNI_OnLoad(JavaVM* vm, void* reserved)
      {
          JNIEnv* env = NULL;
          jint result = -1;
    
        LOGI("JNI_OnLoad");
          if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
              LOGI("ERROR: GetEnv failed
    ");
              goto bail;
          }
          if(env == NULL)
                return result;
    
          /* success -- return valid version number */
          result = JNI_VERSION_1_4;
          if (!Java_com_example_signatureprotect_SignatureJni_isEqual(env, NULL, NULL))
          {
                char *className = "com/example/signatureprotect/MainActivity";
                jclass clazz = (env)->FindClass(className);
                if (clazz == NULL)
                {
                     LOGI("do not find class '%s'", className);
                     return false;
                }
                jmethodID method = (env)->GetStaticMethodID( clazz, "killMyself", "()V");
                if (method == NULL)
                {
                    LOGI("do not find method");
                    return result;
               }
    
               LOGI("find method");
               (env)->CallStaticVoidMethod( clazz, method);
          }

    这样相对会好一些

    源码地址:https://github.com/george-cw/AppAddShellDemo

    这个源码有三个模块,APP模块是签名保护的demo,但是里面的定义的签名字符串不是APP的签名(是加壳app的签名,详细描述见下一篇文章),如果需要单独使用请替换~

    签名的字符串

  • 相关阅读:
    一个接口的性能问题定位和分析过程
    HTTP请求全过程(很全面)
    Linux中查看物理CPU个数、核数、逻辑CPU个数
    linux查看文件大小
    ping不通判断系统是否开机
    ping不通判断系统是否开机
    linux压缩解压文件命令
    python连接redis集群,添加数据
    初学python
    企业级BI为什么这么难做?
  • 原文地址:https://www.cnblogs.com/george-cw/p/10299951.html
Copyright © 2020-2023  润新知