Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I obfuscate my sdk coded with kotlin (and get rid of Metadata)

Tags:

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.

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 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       )     }  } 
  • 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")     } } 

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

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

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

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

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?

like image 814
AlexG Avatar asked Sep 14 '17 12:09

AlexG


People also ask

How do you obfuscate codes on Android?

You can obfuscate Android code to provide security against reverse engineering. You can use the Android ProGuard tool to obfuscate, shrink, and optimize your code. Obfuscated code can be more difficult for other people to reverse engineer.

What is metadata in Kotlin?

Metadata annotation is extra information stored in annotations in Java class files produced by the Kotlin JVM compiler. You will see the metadata annotation if you decompiled the java version of the kotlin class source code.

Which of the following is the Android obfuscation tool?

Obfuscapk is an open-source automatic obfuscation tool for Android apps that works in a black-box fashion (i.e., it does not need the app source code). Obfuscapk supports advanced obfuscation features and has a modular architecture that could be straightforwardly extended to support new obfuscation techniques.


1 Answers

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

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

Here is the information about my environment.

Environment

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

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

gradle.properties

android.enableR8.fullMode=true 

And here is my Proguard Rules

proguard-rules.pro

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

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

like image 165
Pemassi Avatar answered Nov 06 '22 14:11

Pemassi