Code Monkey home page Code Monkey logo

xmlclassguard's Introduction

加我微信 ljx-studio 拉你进微信群(备注XmlClassGuard,否则不通过)

声明

时常会有人给我提需求,问我怎么用,不看文档直接提问题,着实没法应付,免费提供服务不该如此践踏,无奈,出此下策。

  • 加我微信,请不要提XmlClassGuard怎么用等很伤(绝对是暴击)作者心的问题,也不要给我提需求,这本身就是一个慈善项目,帮大家节省大量时间,开源真滴不易,如果有好的想法,欢迎提PR

  • 遇问题,请先翻阅文档、更新日志、Issue列表、常见问题列表,什么?这些都不喜欢看?ok,我提供收费服务,200元/小时(不满一小时按一小时算)

  • 想咨询Google上架相关问题,500元/小时(不满一小时按一小时算)

  • 功能满足不了你?想深度定制?ok,也提供收费服务,价格视需求而定(5000元起)

  • 本人提供aab混淆服务,彻底解决关联问题,价格私聊

  • 第二、第三条,如果你之前有打赏过,打6折,提过PR者,免费

  • 有问题欢迎提Issue,有想法欢迎提PR或与我交流

TODO (欢迎提PR)

  • 混淆xml文件中用到的系统类,如TextView/Button等,用自定义View替代

XmlClassGuard 简介

  • XmlClassGuard是一个可混淆Android 4大组件、自定义View等任意类的插件

  • XmlClassGuard可以看作是ProGuard的一个补充,跟ProGuard没有任何关系,也不会有任何冲突

  • 可快速更改manifest文件里的package属性,并同步到其他文件中

  • 可快速移动n个目录到其他目录中,并同步到其他文件中

  • 可查找constraint_referenced_ids属性的值,并自动添加到AabResGuard的白名单中

  • 可查找constraint_referenced_ids属性的值,并自动添加到AndResGuard的白名单中

  • XmlClassGuard最主要的功能是混淆xml文件用到的类,故取名为XmlClassGuard,与AndResGuardAabResGuard对应

有什么用?

  • 弥补ProGuard不混淆4大组件等类问题

  • 增加aab、apk反编译的难度

  • 极大降低aab包查重率,避免上架Google Play因查重率过高,导致下架或封号问题

关于第三点,有过上架Google Play 商店的同学应该知道,如果之前的包被下架或封号,想要同套代码再次上架,那99%概率是再次封号,很大一部分原因就是以上说到的类未被混淆,很容易被Google断定为包重复,从而导致再次封号,因此,如果想要再次上架,就必须要更改四大组件、自定义View等的包名+类名以降低查重率,然而,如果手动去完成这项任务,估计会累死一个程序员,于是乎,就有了XmlClassGuard,通过插件去完成手工的活,一个任务便可搞定

原理

XmlClassGuard不同于AndResGuard(apk资源混淆)、AadResGuard(aab资源混淆)侵入打包流程的方案,XmlClassGuard 需要在打包前执行xmlClassGuard任务,该任务会检索AndroidManifest.xmlnavigation、layout、xml 文件夹下的xml文件,找出xml文件中引用的类,如4大组件及自定义View等,更改其包名+类名,并将更改后的内容同步到其他文件中,说直白点,就是在打包前,在本地更改包名+类名

警告警告⚠️

由于是在本地操作,任务执行是不可逆的,故务必做好代码备份,否则代码将很难还原

上手

1、在build.gradle(root project)中配置

buildscript {
    repositories {
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath "com.github.liujingxing:XmlClassGuard:1.2.6"
    }
}

2、在 build.gradle(application) 中配置

apply plugin: "xml-class-guard"

//以下均为非必须
xmlClassGuard {
    /*
     * 是否查找约束布局的constraint_referenced_ids属性的值,并添加到AabResGuard的白名单中,
     * 是的话,要求你在XmlClassGuard前依赖AabResGuard插件,默认false
     */
    findAabConstraintReferencedIds = false

    /*
     * 是否查找约束布局的constraint_referenced_ids属性的值,并添加到AndResGuard的白名单中,
     * 是的话,要求你在XmlClassGuard前依赖AndResGuard插件,默认false
     */
    findAndConstraintReferencedIds = false
    //用于增量混淆的 mapping 文件
    mappingFile = file("xml-class-mapping.txt")
    //更改manifest文件的package属性,即包名
    packageChange = ["com.ljx.example": "ab.cd"]
    //移动目录
    moveDir = ["com.ljx.example": "ef.gh"]
}

此时就可以在Gradle栏中,找到以下4个任务

image.png

任务介绍

XmlClassGuard插件共有5个任务,分别是findAabConstraintReferencedIdsfindAndConstraintReferencedIdsmoveDirpackageChangexmlClassGuard,这5个任务之间没有任何关系,下面将一一介绍

1、findAabConstraintReferencedIds/findAndConstraintReferencedIds

findAabConstraintReferencedIds需配合AabResGuard插件使用,如果你未使用AabResGuard插件,可忽略。 findAndConstraintReferencedIds需配合AndResGuard插件使用,如果你未使用AndResGuard插件,可忽略。

下面仅介绍findAabConstraintReferencedIds任务,findAndConstraintReferencedIds任务同理

由于约束布局constraint_referenced_ids属性的值,内部是通过getIdentifier方法获取具体的id,这就要求我们把constraint_referenced_ids属性的值添加进AabResGuard的白名单中,否则打包时,id会被混淆,打包后,constraint_referenced_ids属性会失效,UI将出现异常。

然而,项目中可能很多地方都用到constraint_referenced_ids属性,并且值非常多,要一个个找出来并手动添加到AabResGuard的白名单中,无疑是一项繁琐的工作,于是乎,findAabConstraintReferencedIds任务就派上用场了,它是在打包时,自动查找constraint_referenced_ids属性并添加进AabResGuard的白名单中,非常实用的功能,你仅需要在XmlClassGurad的配置findAabConstraintReferencedIds为true即可,如下:

//以下均为非必须
xmlClassGuard {
    /*
     * 是否查找约束布局的constraint_referenced_ids属性的值,并添加到AabResGuard的白名单中,
     * true的话,要求你在XmlClassGuard前依赖AabResGuard插件,默认false
     */
    findAabConstraintReferencedIds = true
}

findConstraintReferencedIds任务不需要手动执行,打包(aab)时会自动执行

2、moveDir

moveDir是一个移动目录的任务,它支持同时移动任意个目录,它会将原目录下的所有文件(包括子目录)移动到另外一个文件夹下,并将移动的结果,同步到其他文件中,配置如下:

xmlClassGuard {
    //移动目录
    moveDir = ["com.ljx.example": "ef.gh",
               "com.ljx.example.test": "ff.gg"]
}

上面代码中moveDir是一个Map对象,其中key代表要移动的目录,value代表目标目录; 上面任务会把com.ljx.example目录下的所有文件,移动到ef.gh 目录下,将com.ljx.example.test目录下的所有文件移动到ff.gg目录下

3、packageChange

packageChange是一个更改manifest文件里package属性的任务,也就是更改app包名的任务(不会更改applicationId) ,改完后,会将更改结果,同步到其他文件中(不会更改项目结构),配置如下:

xmlClassGuard {
    //更改manifest文件的package属性,即包名
    packageChange = ["com.ljx.example": "ab.cd"]
}

以上packageChange是一个Map对象,key为原始package属性,value为要更改的package属性,原始package属性不匹配,将更改失败

4、xmlClassGuard

xmlClassGuard是一个混淆类的任务,该任务会检索AndroidManifest.xmlnavigation、layout 文件夹下的xml文件,找出xml文件中引用到的类,如4大组件及自定义View等,更改其包名+类名,并将更改的结果,同步到其他文件中,最后会将混淆映射写出到mapping文件中,配置如下:

xmlClassGuard {
    //用于增量混淆的 mapping 文件
    mappingFile = file("xml-class-mapping.txt")
}

上面配置的mappingFile可以是一个不存在的文件,混淆结束后,会将混淆映射写出到该文件中,如下:

dir mapping:
    com.ljx.example -> e
    com.ljx.example.activity -> dh

class mapping:
    com.ljx.example.AppHolder -> e.B
    com.ljx.example.activity.MainActivity -> dh.C

dir mapping是混淆的目录列表,class mapping是具体类的混淆列表

5、混淆任意类

xmlClassGuard任务是支持增量混淆的,如果你需要混淆指定的类com.ljx.example.test.Test,便可以在dir mapping下写入com.ljx.example.test -> h, 此时再次执行xmlClassGuard任务,便会将com.ljx.example.test目录下的所有类(不包含子目录下的类) 移动到h文件夹中,并将所有类名混淆,再次混淆的后mapping文件如下:

dir mapping:
    com.ljx.example -> e
    com.ljx.example.activity -> dh
    com.ljx.example.test -> h

class mapping:
    com.ljx.example.AppHolder -> e.B
    com.ljx.example.activity.MainActivity -> dh.C
    com.ljx.example.test.Test -> h.D

手动输入混淆规则,需要注意以下几条规则

mapping_rule.jpg

6、每次混淆产生不一样的结果

默认情况下,每次混淆,都将产生一样的结果,混淆的包名根据哈希算法得出,混淆的类名,从大写字母A开启,依次递增,如:A B C ... Y Z BA BB .. ZY ZZ BAA...

如果你需要每次混淆产生不一样的结果,只需做两步

  • 对于包名,需要你配置每一个

  • 对于类名,可以每一个都去配置,但类太多时,配置每一个,就显得繁琐,此时仅需要配置一个即可

如我们修改一下上面的mapping文件,如下

dir mapping:
    com.ljx.example -> hh
    com.ljx.example.activity -> jk
    com.ljx.example.test -> et

class mapping:
    com.ljx.example.AppHolder -> hh.Z

此时执行xmlClassGuard任务,就会产生不一样的结果,如下:

dir mapping:
	com.ljx.example -> hh
	com.ljx.example.activity -> jk
	com.ljx.example.test -> et

class mapping:
	com.ljx.example.AppHolder -> hh.Z
	com.ljx.example.activity.MainActivity -> jk.BA
	com.ljx.example.test.Test -> et.BC

可以看到,包名完全是根据自定义生成的结果,而类名便从Z开始,依次递增Z BA BC ..., 这里可以把类名看成26进制的字符串依次递增

注意事项⚠️

  • 要混淆的类,要避免与其他类同名,否则类名替换时,会出现误杀情况

  • 类混淆后,类的包名(路径)也会被混淆,所以,如果你用到一些三方库,有配置包名的地方,记得手动更改

  • XmlClassGuard不会更改proguard-rules.pro文件的内容,所以,类混淆后,如果该文件内容有混淆前的类或目录,也记得手动更改

  • XmlClassGuard只会帮你更改包名+类名,并同步到其它文件中,不会更改你的任何代码逻辑,如混淆后,出现部分功能不正常问题,需要你自己查找原因,如果是XmlClassGuard的问题,欢迎提issuePR

Donations

如果它对你帮助很大,并且你很想支持库的后续开发和维护,那么你可以扫下方二维码随意打赏我,就当是请我喝杯咖啡或是啤酒,开源不易,感激不尽

donations.png

xmlclassguard's People

Contributors

dakun666 avatar freesith avatar liujingxing avatar xujiaji avatar ztwave avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xmlclassguard's Issues

gradle报错

An exception occurred applying plugin request [id: 'xml-class-guard']
> Failed to apply plugin 'xml-class-guard'.
   > Could not create task ':app:moveDir'.
      > Could not create task of type 'MoveDirTask'.
         > groovy/xml/XmlParser

 repositories {
        google()
        mavenCentral()
        jcenter()
        maven { url 'https://jitpack.io' }
    }

    dependencies {
        classpath "com.github.liujingxing:XmlClassGuard:1.0.0"
 }

使用moveDir功能有bug

我的想法是将这5个类移动到screen目录下,但是好像做不到。我使用下面这样的语句:
a6ad2a468c1d09409aa786568ff8e6d

结果是类都给删除了
72eae2702c3ad7f3f0c70ab93500b86

这种需求用该插件能实现吗?

打包找不到R

如果引用R类的文件和R文件一个包,那么转移到其他包后,不会自动import R文件,导致打包的时候找不到R

plugins

plugins {
id 'com.android.application' version '8.0.1' apply false
id 'com.android.library' version '8.0.1' apply false
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
id 'xml-class-guard' version '1.2.3' apply false
}

关于android特殊工程

从unity导出的工程, 目录结构有点不一样, 报错找不到AndroidManifest.xml

报错: xxx\src\main\AndroidManifest.xml (系统找不到指定的路径。)

混淆文件的package都没有修改

就运行xmlClassGuard的时候,发现混淆四大组件或者自定义的类的时候,对应的package属性没有修改为混淆后的路径名

String index out of range: -10

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':xxxx:xmlClassGuard'.
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -10
	at com.xml.guard.tasks.XmlClassGuardTask.guardXml(XmlClassGuardTask.kt:94)
	at com.xml.guard.tasks.XmlClassGuardTask.handleResDir(XmlClassGuardTask.kt:65)
	at com.xml.guard.tasks.XmlClassGuardTask.execute(XmlClassGuardTask.kt:46)

这是什么问题呀,求大佬解答,感激不尽

Should read manifest file path from sourceSets

I got gradle setting like:

sourceSets.main {
        aidl.srcDir "../java/src"
        java.srcDir "../java/src"
        manifest.srcFile "AndroidManifest.xml"
   }

plugin always return error like:
../src/main/AndroidManifest.xml (No such file or directory)

Could not find com.bytedance.android:aabresguard-plugin:0.1.10.

findAabConstraintReferencedIds = true时报错 “AabResGuard plugin required”

AadResGuard 已经配置,可以正常运行
findAabConstraintReferencedIds = false 时,XmlClassGuard也能正常运行。
把findAabConstraintReferencedIds 设置成true后,同步时报错 "AabResGuard plugin required"。

XmlClassGuardPlugin.kt

private fun Project.createAabFindConstraintReferencedIdsTask(variantName: String) {
        val aabResGuardTaskName = "aabresguard$variantName"
        val aabResGuardTask = project.tasks.findByName(aabResGuardTaskName)
            ?: throw GradleException("AabResGuard plugin required")
        val taskName = "aabFindConstraintReferencedIds$variantName"
        val task =
            createTask(taskName, FindConstraintReferencedIdsTask::class, aabResGuard, variantName)
        aabResGuardTask.dependsOn(task)
    }

源码中是找不到 aabResGuardTaskName 任务会抛出这个错误。

Gradle任务列表中,确实是没有找到以"aabresguard"开头的任务名称。请问我是哪里操作有误吗?

执行xmlClassGuard报错

报错信息:

Task :app:xmlClassGuardRelease FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:xmlClassGuardRelease'.

End index (0) is less than start index (340).

我的配置:

xmlClassGuard {
    /*
     * 是否查找约束布局的constraint_referenced_ids属性的值,并添加到AabResGuard的白名单中,
     * 是的话,要求你在XmlClassGuard前依赖AabResGuard插件,默认false
     */
    findAabConstraintReferencedIds = false

    /*
     * 是否查找约束布局的constraint_referenced_ids属性的值,并添加到AndResGuard的白名单中,
     * 是的话,要求你在XmlClassGuard前依赖AndResGuard插件,默认false
     */
    findAndConstraintReferencedIds = false
    //用于增量混淆的 mapping 文件
    mappingFile = file("xml-class-mapping.txt")
    //更改manifest文件的package属性,即包名
    packageChange = ["com.a.b": "ab.cd"]
    //移动目录
    moveDir = ["com.a.b": "ef.gh"]
}

Execution failed for task ':app:moveDir'. (Permission denied)

我在macos 12.6上面遇到了下面的错误导致我全部的Gradle命令(moveDir,packageChange,xmlClassGuard)都无法使用全部报下面的错误。
Execution failed for task ':app:moveDir'.

java.io.FileNotFoundException: /Users/kinsun/Desktop/TestApplication/app/src/main/AndroidManifest.xml (Permission denied)

kt语法上替换类名只替换一半

形如:

for (id in NotificationItem.Notification_Id_Recommend_Func_dlg..NotificationItem.Notification_Id_Recommend_Func_dlg2){
}

只替换成

for (id in CD.Notification_Id_Recommend_Func_dlg..NotificationItem.Notification_Id_Recommend_Func_dlg2){

第二个NotificationItem 没有替换。

ps:
Notification_Id_Recommend_Func_dlg和Notification_Id_Recommend_Func_dlg2都是NotificationItem定义的常量

执行packageChange'报错

Execution failed for task ':app:packageChange'.

'java.lang.String com.android.build.gradle.BaseExtension.getNamespace()'

一定要和aabresguard一起使用吗?

如果项目不需要依赖于aabresguard,构建时会报错:Could not find com.bytedance.android:aabresguard-plugin:0.1.10.

但是项目又不想引入aabresguard。

混淆bug

写法如下:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun test(m:com.ljx.example.activity.MainActivity) {
        Log.d("XXXXXXX", "test: $m.javaClass.simpleName")
    }
}

混淆后的结果如下:

class C : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun test(m:com.ljx.example.activity.MainActivity) {
        Log.d("XXXXXXX", "test: $m.javaClass.simpleName")
    }
}

可以发现方法test的参数没有混淆

BR类冲突

混淆后生成的BR类跟Databinding生成的BR类路径相同时会冲突,应该把BR像R一样跳过一下。

不支持 org.gradle.unsafe.configuration-cache=true

  • Exception is:
    org.gradle.configurationcache.ConfigurationCacheProblemsException: Configuration cache problems found in this build.

1 problem was found storing the configuration cache.

官网建议是
To fix this problem, read Gradle properties using providers.gradleProperty() instead:
def enabled = providers.gradleProperty('some-property').forUseAtConfigurationTime().present

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.