Android studio 混淆插件

1 正常混淆

2 对自定义插件的混淆

插件方式:

Gradle 的插件有三种打包方式,主要是按照复杂程度和可见性来划分:

Build script

把插件写在 build.gradle 文件中,一般用于简单的逻辑,只在该 build.gradle 文件中可见,笔者常用来做原型调试,本文将简要介绍此类。

buildSrc 项目

将插件源代码放在 rootProjectDir/buildSrc/src/main/groovy 中,只对该项目中可见,适用于逻辑较为复杂,但又不需要外部可见的插件,本文不介绍,有兴趣可以参考此处

独立项目

一个独立的 Groovy 和 Java 项目,可以把这个项目打包成 Jar 文件包,一个 Jar 文件包还可以包含多个插件入口,将文件包发布到托管平台上,供其他人使用。本文将着重介绍此类。

 这里独立插件中既有groovy代码,又有java代码,而本文目标是为了混淆插件中的java代码,groovy代码编译成class文件后,不混淆也不易读,且groovy代码混淆后,插件使用会出问题。

2.1 插件混淆方式

借鉴:https://studiofreya.com/2016/03/20/how-to-obfuscate-a-package-with-gradle-maven-and-proguard/

import proguard.gradle.ProGuardTask

apply plugin: 'groovy'
apply plugin: 'maven'

version = '1.0.0'
group = 'com.xx.xxGradlePlugin'
archivesBaseName = 'xxxgradleplugin'

dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:2.3.3'
}


repositories {
    mavenCentral()
    jcenter()
}

def javaName = archivesBaseName + '-java'
def fullJavaName = archivesBaseName + '-full'

sourceSets {
    main {
        java {
            srcDir 'src/main/java'
        }
    }
}

jar {
    baseName = javaName
    manifest {
        attributes "Implementation-Title": javaName
        attributes "Implementation-Version": version
    }

}

task fullJavaJar(type: Jar) {
    baseName = fullJavaName
    manifest {
        attributes "Implementation-Title": baseName
        attributes "Implementation-Version": version
    }
    from sourceSets.main.output
    artifacts {
        archives fullJavaJar
    }
}

buildscript {

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:5.2.1'
    }
}

task proguard(type: ProGuardTask, dependsOn: 'fullJavaJar') {
    configuration 'proguard-rules.pro'

    injars "$buildDir/libs/${fullJavaName}-${version}.jar"
    outjars "$buildDir/libs/${javaName}-${version}.jar"
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
}

task obfuscate(dependsOn: tasks.withType(ProGuardTask)) << {}

编译时用命令行,./gradlew clean obfuscate 即可编译成功,混淆前文件*-full*.jar,  混淆后*-java*.jar

2.2 遇到的问题

P1:

Caused by: java.lang.VerifyError: Expecting a stackmap frame at branch target 237
Exception Details:
  Location:
    com/xx/xx/gradle/xx/xxGradlePlugin.apply(Lorg/gradle/api/Project;)V @177: ifeq
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: b800 3b4d 2c12 0132 1228 1214 b900 4d03
    0x00000c0: 0200 1220 b900 4d03 003a 0519 0557 2c12
0x00000e0: 120e 3219 0519 06b9 004d 0300 57b1

F1:原因是项目启动时,JVM 会对字节码进行校验,校验不通过会导致该错误。
解决办法是是在启动时添加参数 :-Xverify:none 再启动即可。(在gradle.properties 文件中添加,如下所示)

org.gradle.jvmargs=-Xmx2048m -XX\:MaxPermSize\=512m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8
 -Xverify:none

但是这个选项显然去掉了jvm加载类前的验证环节,并不妥当。

递进,在proguard-rules.pro文件中,proguard配置中,-dontpreverify命令会在插件编译过程前关闭校验,从而使验证问题后移到了在宿主使用该插件进行编译的环节。如果去掉这句话,就可以把校验提前到插件编译环节,并能发现具体导致验证失败的细节原因。

-dontpreverify #不预校验

去掉-dontpreverify后,问题P2:

Caused by: java.lang.IllegalArgumentException: Can't find common super class of [pkg/logging/SpecificLog] (with 1 known super classes) and [pkg/logging/SystemPrintLog] (with 1 known super classes)
at proguard.evaluation.value.TypedReferenceValue.findCommonClass(TypedReferenceValue.java:441)
at proguard.evaluation.value.TypedReferenceValue.generalize(TypedReferenceValue.java:277)
at proguard.evaluation.value.TypedReferenceValue.generalize(TypedReferenceValue.java:201)
at proguard.evaluation.value.ReferenceValue.generalize(ReferenceValue.java:298)
at proguard.evaluation.Stack.generalize(Stack.java:143)
at proguard.evaluation.TracedStack.generalize(TracedStack.java:148)
at proguard.optimize.evaluation.PartialEvaluator.evaluateSingleInstructionBlock(PartialEvaluator.java:691)
at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlock(PartialEvaluator.java:609)
at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(PartialEvaluator.java:567)
at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute0(PartialEvaluator.java:271)
at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute(PartialEvaluator.java:188)
at proguard.optimize.evaluation.LivenessAnalyzer.visitCodeAttribute(LivenessAnalyzer.java:205)
at proguard.preverify.CodePreverifier.visitCodeAttribute0(CodePreverifier.java:109)
at proguard.preverify.CodePreverifier.visitCodeAttribute(CodePreverifier.java:82)
at proguard.classfile.attribute.CodeAttribute.accept(CodeAttribute.java:101)
at proguard.classfile.ProgramMethod.attributesAccept(ProgramMethod.java:81)
at proguard.classfile.attribute.visitor.AllAttributeVisitor.visitProgramMember(AllAttributeVisitor.java:95)
at proguard.classfile.util.SimplifiedVisitor.visitProgramMethod(SimplifiedVisitor.java:92)
at proguard.classfile.ProgramMethod.accept(ProgramMethod.java:73)
at proguard.classfile.ProgramClass.methodsAccept(ProgramClass.java:516)
at proguard.classfile.visitor.AllMethodVisitor.visitProgramClass(AllMethodVisitor.java:47)
at proguard.classfile.visitor.ClassVersionFilter.visitProgramClass(ClassVersionFilter.java:76)
at proguard.classfile.ProgramClass.accept(ProgramClass.java:358)
at proguard.classfile.ClassPool.classesAccept(ClassPool.java:124)
at proguard.preverify.Preverifier.execute(Preverifier.java:60)
at proguard.ProGuard.preverify(ProGuard.java:403)
at proguard.ProGuard.execute(ProGuard.java:162)
at proguard.gradle.ProGuardTask.proguard(ProGuardTask.java:1074)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:141)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:123)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:632)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:615)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:95)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:76)
... 70 more

 

Unexpected error while performing partial evaluation:
  Class       = [pkg/RewriterAgent]
  Method      = [init(Ljava/lang/String;)V]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [pkg/logging/SpecificLog] (with 1 known super classes) and [compile/logging/SystemPrintLog] (with 1 known super classes))
Unexpected error while preverifying:
  Class       = [pkg/RewriterAgent]
  Method      = [init(Ljava/lang/String;)V]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [pkg/logging/SpecificLog] (with 1 known super classes) and [compile/logging/SystemPrintLog] (with 1 known super classes))
:proguard FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':proguard'.
> Can't find common super class of [pkg/logging/SpecificLog] (with 1 known super classes) and [pkg/logging/SystemPrintLog] (with 1 known super classes)

F2:方法1 添加:libraryjars "${System.getProperty('java.home')}/lib/rt.jar"

方法2:在proguard-rules.pro文件中,添加:-libraryjars <java.home>/lib/rt.jar

P3

 No signature of method: static compile.f.getInstance() is applicable for argument types: () values: []

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:transformClassesWithAforDebug'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:84)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecute

F3:这里的 f.getInstance()的对应的类和方法不能混淆, 在proguard-rules.pro文件中添加

-keep class pkg.RAgent {
   pkg.RAgent getInstance();
}

 

posted @ 2017-09-18 21:03  xaf_dfg  阅读(1509)  评论(0)    收藏  举报