本文介绍了如何混淆使用Kotlin编码的sdk(并摆脱元数据)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个SDK(Android库),并且我不得不混淆我的大部分代码,以便客户可能不会尝试使用内部代码.我的库是用kotlin编码的,我使用了proguard来混淆代码.问题是,编译和混淆后,代码中仍然有@ kotlin.Metadata(运行时)批注.有了这些注释,就可以很容易地检索起源于此(不是很模糊)"字节码的java代码.

I'm developing a SDK (Android library), and I have to obfuscate a large part of my code so the customer may not try and play with internal code.My lib is coded in kotlin, and I used proguard to obfuscate the code. Problem is that there are still @kotlin.Metadata (runtime) annotations inside the code after compile and obfuscation. With those annotations, it's really easy to retrieve the java code that originated this "(not-so-)obfuscated" bytecode.

我首先以为是我的错,并且我的项目中有太多的熵源可能导致这种行为,所以我制作了一个样本项目来证明问题并非来自于我的sdk实现.我用AS创建了一个新项目,然后用2个文件创建了一个lib模块:

I first thought it was my fault, and my project had too many entropy sources that might have induced this behaviour, so I made a sample project to prove that the problem does not come from my sdk implementation.I created a new project with AS, then a lib module with 2 files:

  • facade.kt是我的门面类,我不想混淆它,因此客户可以使用它:

  • facade.kt is my facade class, the one that I do not wish to obfuscate, so the customer may use it:

package com.example.mylibrary

class MyFacade(val internalClass:InternalClass) {

   fun doSomething() {
      internalClass.doSomething(
             firstArgument=1,
             secondArgument=2
      )
    }
 }

  • ,在此示例中,internal.kt包含我要混淆的类:

  • and in this sample, internal.kt holds the classes that I want to obfuscate:

    package com.example.mylibrary
    
    class InternalClass {
        fun doSomething(firstArgument: Int, secondArgument: Int) {
            System.out.println("Arguments are : $firstArgument, $secondArgument")
        }
    }
    

  • 在此发行版关闭后,将proguard规则注入gradle项目中:

    The proguard rules are injected into gradle project with this release closure:

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles 'proguard-rules.pro'
        }
    }
    

    这是proguard-rules.pro(仅一行,仅此而已):

    And here is proguard-rules.pro (only one line, nothing more) :

    -keep class com.example.mylibrary.MyFacade {*;}
    

    结果:当我./gradlew clean myLib:assembleRelease时,我确实获得了一个保留我的门面的aar,并且我的内部类已使用一种方法"a"重命名为"a",但该类仍被注释使用kotlin @Metadata,其中包含有助于反编译器检索原始类名称,方法,属性和参数名称等的所有信息.所以我的代码一点也不被混淆...

    The result: when I ./gradlew clean myLib:assembleRelease, I do obtain an aar in which my facade is kept, and my internal class has been renamed in 'a', with one method 'a', except that the class is still annotated with kotlin @Metadata, which holds every information that helps the decompiler retrieve the original class name, the method, attribute and argument names, etc...So my code is not so obfuscated at all...

    @Metadata(
       mv = {1, 1, 7},
       bv = {1, 0, 2},
       k = 1,
       d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\b\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0016\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\u0006\u0010\u0007\u001a\u00020\u0006¨\u0006\b"},
       d2 = {"Lcom/example/mylibrary/InternalClass;", "", "()V", "doSomething", "", "firstArgument", "", "secondArgument", "mylibrary_release"}
    )
    public final class a {
        ...
    }
    

    所以我的问题是:是否有可能摆脱这些注释,我是唯一面临此问题的人,还是错过了某些东西?

    So my question: is it possible to get rid of those annotations, am I the only one facing this problem, or have I missed something?

    推荐答案

    最后,我找到了一种删除Kotlin元数据注释的方法.

    Finally, I found a way to delete Kotlin metadata annotations.

    要隐藏Kotlin元数据注释,您需要启用R8完整模式.

    In order to hide Kotlin metadata annotations, you need to enable R8 full mode.

    以下是有关我的环境的信息.

    Here is the information about my environment.

    OS: macOS 10.15.1
    Android Studio: 3.5.1
    Gradle: 5.4.1
    Android Gradle Tool: 3.5.2
    

    您要做的只是向gradle.properties添加属性,如下所示:

    What you have to do is just add properties to gradle.properties like below

    android.enableR8.fullMode=true
    

    这是我的Proguard规则

    And here is my Proguard Rules

    -dontwarn kotlin.**
    -assumenosideeffects class kotlin.jvm.internal.Intrinsics {
        static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
    }
    

    仅供参考,R8完整模式目前仍在测试中,因此有时效果不佳.但是,对我而言,它目前可以完美运行.

    FYI, R8 full mode is still testing now, so sometimes it doesn't work well. However, for me, it works perfectly for now.

    这篇关于如何混淆使用Kotlin编码的sdk(并摆脱元数据)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-23 01:41