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();
}

浙公网安备 33010602011771号