All Projects → Ivonhoe → Dexguard

Ivonhoe / Dexguard

Android app防dex2jar的gradle插件

Programming Languages

groovy
2714 projects

Projects that are alternatives of or similar to Dexguard

Gradle Eclipse Aar Plugin
Gradle plugin to use Android AAR libraries on Eclipse.
Stars: ✭ 127 (-27.01%)
Mutual labels:  gradle-plugin
Moko Resources
Resources access for mobile (android & ios) Kotlin Multiplatform development
Stars: ✭ 142 (-18.39%)
Mutual labels:  gradle-plugin
Buildkonfig
BuildConfig for Kotlin Multiplatform Project
Stars: ✭ 156 (-10.34%)
Mutual labels:  gradle-plugin
Yguard
The open-source Java obfuscation tool working with Ant and Gradle by yWorks - the diagramming experts
Stars: ✭ 130 (-25.29%)
Mutual labels:  gradle-plugin
Kotlin Gradle Plugin Template
🐘 A template to let you started with custom Gradle Plugins + Kotlin in a few seconds
Stars: ✭ 141 (-18.97%)
Mutual labels:  gradle-plugin
Gradle Aem Plugin
Swiss army knife for Adobe Experience Manager related automation. Environment setup & incremental AEM application build which takes seconds, not minutes.
Stars: ✭ 145 (-16.67%)
Mutual labels:  gradle-plugin
Gradle Css Plugin
Gradle plugin for working with CSS
Stars: ✭ 125 (-28.16%)
Mutual labels:  gradle-plugin
Retropiler
PoC of Java8 Standard Library for Android for API version >= 15
Stars: ✭ 159 (-8.62%)
Mutual labels:  gradle-plugin
Gradle Pitest Plugin
Gradle plugin for PIT Mutation Testing
Stars: ✭ 144 (-17.24%)
Mutual labels:  gradle-plugin
Gradle Android Plugin
[Deprecated] Gradle Android Plugin 中文版使用手册,如有纰漏,望斧正
Stars: ✭ 155 (-10.92%)
Mutual labels:  gradle-plugin
Gson Plugin
辅助 Gson 库的 gradle 插件,防止 Json 数据解析类型异常。
Stars: ✭ 133 (-23.56%)
Mutual labels:  gradle-plugin
Gradle Nexus Staging Plugin
Automatize releasing Gradle projects to Maven Central.
Stars: ✭ 132 (-24.14%)
Mutual labels:  gradle-plugin
Shortbread
Android library that creates app shortcuts from annotations
Stars: ✭ 1,803 (+936.21%)
Mutual labels:  gradle-plugin
Forma
Meta build system with Android and Gradle support.
Stars: ✭ 127 (-27.01%)
Mutual labels:  gradle-plugin
Shipkit
Toolkit for shipping it used by Mockito library
Stars: ✭ 157 (-9.77%)
Mutual labels:  gradle-plugin
Bytex
ByteX is a bytecode plugin platform based on Android Gradle Transform API and ASM. 字节码插件开发平台
Stars: ✭ 2,140 (+1129.89%)
Mutual labels:  gradle-plugin
Android Snapshot Publisher
Gradle plugin to deploy Android Snapshot Versions
Stars: ✭ 145 (-16.67%)
Mutual labels:  gradle-plugin
Vue Kotlin
Libraries and tools supporting the use of Vue.js in Kotlin.
Stars: ✭ 162 (-6.9%)
Mutual labels:  gradle-plugin
Versioning
Gradle plug-in to generate version information from the SCM branch (Git or Svn)
Stars: ✭ 157 (-9.77%)
Mutual labels:  gradle-plugin
Gradle License Report
A plugin for generating reports about the licenses of third party software using Gradle
Stars: ✭ 152 (-12.64%)
Mutual labels:  gradle-plugin

美团如何防dex2jar

如何使用

  • 在root project的build.gradle中添加依赖classpath 'ivonhoe.gradle.dexguard:dexguard-gradle:0.0.4-SNAPSHOT'
buildscript {
    repositories {
        maven { url 'https://raw.githubusercontent.com/Ivonhoe/mvn-repo/master/' }
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'ivonhoe.gradle.dexguard:dexguard-gradle:0.0.4-SNAPSHOT'
    }
}
  • 在app项目的build.gradle中添加插件,map.txt中配置需要保护的方法名
apply plugin: 'ivonhoe.dexguard'
dexguard {
    guardConfig = "${rootDir}/map.txt"
}

一、概述

上一篇文章,我大致分析了美团外卖Android客户端是如何防止其Java代码被dex2jar工具转换,而做的防护,那就是将有语法错误的字节码插入到想要保护的Java函数中中,借助dex2jar的语法检查机制,以达到dex2jar转换出错的目的。这篇文章就大致记录下如何开发Gradle编译插件,在编译过程中实现上述防护思路。

二、思路

先看下Android APK打包流程:

Android apk打包流程

Android APK打包流程如上图所示,Java代码先通过Java Compiler生成.class文件,在通过dx工具生成dex文件,最后使用apkbuilder工具完成代码与资源文件的打包,并使用jarsigner签名,最后可能还有使用zipalign对签名后的apk做对齐处理。

如果需要完成对特定函数的代码注入,可以在Java代码编译生成class文件后,在dex文件生成前,针对class字节码进行操作,以本例为例需要动态生成Exsit类文件的字节码(不清楚Exsit的作用可以看上一篇文章)。

// 动态生成Exist.class
public class Exist {
    public static boolean a() {
        return false;
    }

    public static void b(int test) {
    }
}

动态修改特定方法的字节码,将下列Java代码转换成字节码插入特定的函数中。

// 插入到特定的Java函数内
Exist.b(Exist.a());

并将修改后的.class文件放入dex打包目录中,完成dex打包,具体流程如下图所示:

Gradle提供了叫Transform的API,允许三方插件在class文件转换为dex文件前操作编译好的class文件,这个API的目标就是简化class文件的自定义的操作而不用对Task进行处理,并且可以更加灵活地进行操作。详细的可以参考区长的博客

四、ASM操作Java字节码

ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直 接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。这里推荐一个IDEA插件:ASM ByteCode Outline。可以查看.class文件的字节码,并可以生成成ASM框架代码。安装ASM Bytecode Outline插件后,可以在Intellij IDEA->Code->Show Bytecode Outline查看类文件对应个字节码和ASM框架代码,利用ASM框架代码就可以生成相应的.class文件了。

生成Exist字节码的具体实现,生成Exist.java的构造函数:

ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;

cw.visit(51, ACC_PUBLIC + ACC_SUPER, "ivonhoe/dexguard/java/Exist", null, "java/lang/Object", null);

cw.visitSource("Exist.java", null);

mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(7, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "Livonhoe/dexguard/java/Exist;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
        

声明一个函数名为a,返回值为boolean类型的无参函数:

mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "a", "()Z", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(10, l0);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 0);
mv.visitEnd();

声明一个函数名为b,参数为int型,返回类型为void的函数

MV = CW.VISITmETHOD(acc_public + acc_static, "b", "(i)v", NULL, NULL);
MV.VISITcODE();
L0 = NEW lABEL();
MV.VISITlABEL(L0);
MV.VISITlINEnUMBER(14, L0);
MV.VISITiNSN(return);
L1 = NEW lABEL();
MV.VISITlABEL(L1);
MV.VISITlOCALvARIABLE("TEST", "i", NULL, L0, L1, 0);
MV.VISITmAXS(0, 1);
MV.VISITeND();

在指定函数内,插入Exist.b(Exist.a());对应的字节码的具体实现,绕过Java编译器的语法检查:

//refer hack class when object init
private static byte[] referHackWhenInit(InputStream inputStream, String methodName) {
    ClassReader cr = new ClassReader(inputStream);
    ClassWriter cw = new ClassWriter(cr, 0);

    ClassVisitor cv = new InjectCassVisitor(Opcodes.ASM4, cw, methodName);
    cr.accept(cv, 0);
    return cw.toByteArray();
}
static class InjectClassVisitor extends ClassVisitor {

        private String methodName;

        InjectClassVisitor(int i, ClassVisitor classVisitor, String method) {
            super(i, classVisitor)

            this.methodName = method;
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc,
                                         String signature, String[] exceptions) {

            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            mv = new MethodVisitor(Opcodes.ASM4, mv) {

                @Override
                void visitCode() {
                    // 在方法体开始调用时
                    if (name.equals(methodName)) {
                        mv.visitMethodInsn(INVOKESTATIC, "ivonhoe/dexguard/java/Exist", "a", "()Z", false);
                        mv.visitMethodInsn(INVOKESTATIC, "ivonhoe/dexguard/java/Exist", "b", "(I)V", false);
                    }
                    super.visitCode()
                }

                @Override
                public void visitMaxs(int maxStack, int maxLocal) {
                    if (name.equals(methodName)) {
                        super.visitMaxs(maxStack + 1, maxLocal);
                    } else {
                        super.visitMaxs(maxStack, maxLocal);
                    }
                }
            }
            return mv;
        }
    }

五、源码

详细的Gradle源码和实例可参考https://github.com/Ivonhoe/dexguard

六、参考文档

Android 热修复使用Gradle Plugin1.5改造Nuwa插件

ASM-操作字节码初探

手摸手增加字节码往方法体内插代码

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].