Android Google马甲包处理

这是整理其他人的plugin代码,最后有亮点,耐心看下吧

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'xml-class-guard'
//    id 'AndResGuard'
//    id 'com.bytedance.android.aabResGuard'
//    id 'stringfog'
    id 'android-junk-code'
//    id 'kotlin-android-extensions'
}

gradle文件增加以下代码

/**
 * 第一步执行这个操作,先生成字典,混淆用
 * https://blog.csdn.net/nnmmbb/article/details/129492332
 */
/*** 生成字典Task*/
task geneDictTask {
    doFirst {
        def dictPath = rootDir.getAbsolutePath() + '/app/dict.txt'
        def random = new Random()
        def lowercase = "abcdefghijklmnopqrstuvwxyz"
        def wordList = new HashSet()
        for (int i = 0; i < 1000; i++) {
            def word = new StringBuilder()
            def wordLength = random.nextInt(5) + 4
            for (int j = 0; j < wordLength; j++) {
                word.append(lowercase.charAt(random.nextInt(lowercase.length())))
            }
            wordList.add(word.toString())
        }
        def f = new File(dictPath)
        f.getParentFile().mkdirs()
        f.withWriter("UTF-8") { it.write(wordList.join(System.lineSeparator())) }
    }
}

///批量修改文件名
ext {
    //需要批量重命名的Been路径
    renameBeenPath = "src/main/java/com/mosen/xxx/huawei"
    //如果有productFlavors 就多次执行下
    renameResPath = "src/main/res"
}

/**
 * 第二步修改名字,不然修改包名就不好在改了
 *
 * */
task renameBeenProcesser {
    doLast {
        FileTree beenTree = fileTree(renameBeenPath) {
            include '**/*.java'
            include '**/*.kt'
        }
        def start = System.currentTimeMillis()
        println(">>>>>> renameBeenProcesser start")
        beenTree.each { File beenFile ->
            //println(beenFile.path + " Processing...")
            def sname = beenFile.name
            def fileEx = sname.substring(sname.lastIndexOf("."))
            sname = sname.replace(fileEx, "")

            if (sname == "PrintStream" || sname == "StringFog") {
                return
            }
            def tName = ""
            def random = new Random()

            def lowercase = "abcdefghijklmnopqrstuvwxyz"
            def word = new StringBuilder()
            def wordLength = random.nextInt(5) + 4
            for (int j = 0; j < wordLength; j++) {
                word.append(lowercase.charAt(random.nextInt(lowercase.length())))
            }
            tName = word.toString() + random.nextInt(999)
            beenFile.renameTo(beenFile.parentFile.path + File.separator + tName + fileEx)
            //生成一个文件树,替换import后面的路径
            FileTree processTree = fileTree("src") {
                include '**/*.java'
                include '**/*.kt'
                include '**/layout/*.xml'
                include '**/AndroidManifest.xml'
            }
            processTree.each { File f ->
                ImportBeenReplacer(f.path, sname, tName)
            }
        }
        def cost = (System.currentTimeMillis() - start) / 1000
        println(">>>>>> renameBeenProcesser end(cost:${cost}s)")
    }
}


/**
 * 修改layout,不支持viewbinding和databinding,我谁知道怎么改,有人可以告诉吗
 *
 * */
task renameLayoutProcesser {
    doLast {
        FileTree beenTree = fileTree(renameResPath) {
            include '**/layout/*.xml'
        }
        def start = System.currentTimeMillis()
        println(">>>>>> renameBeenProcesser start")
        beenTree.each { File beenFile ->
            //println(beenFile.path + " Processing...")
            def sname = beenFile.name
            def fileEx = sname.substring(sname.lastIndexOf("."))
            sname = sname.replace(fileEx, "")
            def tName = ""
            def random = new Random()

            def lowercase = "abcdefghijklmnopqrstuvwxyz"
            def word = new StringBuilder()
            def wordLength = random.nextInt(5) + 4
            for (int j = 0; j < wordLength; j++) {
                word.append(lowercase.charAt(random.nextInt(lowercase.length())))
            }
            tName = word.toString() + random.nextInt(999)
            beenFile.renameTo(beenFile.parentFile.path + File.separator + tName + fileEx)
            //生成一个文件树,替换import后面的路径
            FileTree processTree = fileTree("src") {
                include '**/*.java'
                include '**/*.kt'
                include '**/layout/*.xml'
                include '**/AndroidManifest.xml'
            }
            processTree.each { File f ->
                ImportResReplacer(f.path, sname, tName)
            }
        }
        def cost = (System.currentTimeMillis() - start) / 1000
        println(">>>>>> renameBeenProcesser end(cost:${cost}s)")
    }
}

/***
 * 第三步,执行 先执行移动目录在修改包名
 * //以下均为非必须
 */
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.mosen.xxx.huawei": "com.mosen.target.huawei"]
    //移动目录
    moveDir = ["com.mosen.xxx.huawei": "com.mosen.target.huawei"]
}


// 导入RandomKeyGenerator类,如果不使用RandomKeyGenerator,可以删除此行
import com.github.megatronking.stringfog.plugin.kg.RandomKeyGenerator

stringfog {
    // 必要:加解密库的实现类路径,需和上面配置的加解密算法库一致。
    implementation 'com.github.megatronking.stringfog.xor.StringFogImpl'
    // 可选:加密开关,默认开启。
    enable true
    // 可选:指定需加密的代码包路径,可配置多个,未指定将默认全部加密。
    fogPackages = ['com.mosen.xxx.huawei']
    // 可选(3.0版本新增):指定密钥生成器,默认使用长度8的随机密钥(每个字符串均有不同随机密钥),
    // 也可以指定一个固定的密钥:HardCodeKeyGenerator("This is a key")
    kg new RandomKeyGenerator()
    // 可选(4.0版本新增):用于控制字符串加密后在字节码中的存在形式, 默认为base64,
    // 也可以使用text或者bytes
    mode com.github.megatronking.stringfog.plugin.StringFogMode.bytes
    //应用的包名
    packageName = "com.mosen.xxx.huawei"
    //开启调试
    debug false
    //辣鸡代码类
    junkCodeClass = "com.mosen.xxx.huawei.PrintStream"
}

/**
 * 根据第三步定义的名字, 调整辣鸡代码的名字和混淆配置的名字
 * repackageclasses
 */
androidJunkCode {
    //com.mosen.target.huawei
    def config = {
        def random = new Random()
        packageBase = "com.mosen.xxx.huawei.ui"
        packageCount = random.nextInt(5) + 1
        activityCountPerPackage = random.nextInt(5) + 1
        excludeActivityJavaFile = false
        otherCountPerPackage = random.nextInt(1) + 1
        methodCountPerClass = 0
        def lowercase = "abcdefghijklmnopqrstuvwxyz"
        def word = new StringBuilder()
        def wordLength = random.nextInt(5) + 5
        for (int j = 0; j < wordLength; j++) {
            word.append(lowercase.charAt(random.nextInt(lowercase.length())))
        }
        resPrefix = word.toString() + "_"
        drawableCount = random.nextInt(1) + 1
        stringCount = random.nextInt(10) + 1
    }
    variantConfig {
        a1Debug config
        a1Release config
    }
}

//替换有导入目标been的文件内容
def ImportBeenReplacer(String filePath, sourceBeenName, targetBeenName) {
    if (sourceBeenName.equals("PrintStream") || sourceBeenName.equals("StringFog")) {
        return
    }
    def readerString = ""
    def hasReplace = false
    def xml = filePath.endsWith(".xml")
    file(filePath).withReader('UTF-8') { reader ->
        reader.eachLine { String it ->
            if (it.find(sourceBeenName)) {
                if (xml) {
                    //println("###$filePath: $sourceBeenName->$targetBeenName")
                    it = it.replaceAll("(?<![a-zA-Z0-9]+)(?<=[\\.]+)$sourceBeenName(?=[ \"\\./>]*)(?![a-zA-Z0-9]+)", targetBeenName)
                } else {
                    it = it.replaceAll("(?<![a-zA-Z0-9]+)(?<=[ \\.<:\\s\\,(]+)$sourceBeenName(?=[ \"\\.>\\?\\:\\(]*)(?![a-zA-Z0-9]+)", targetBeenName)
                }
                hasReplace = true
            }
            readerString <<= it
            readerString << '\n'
        }
    }
    if (hasReplace) {
        if (readerString.toString().endsWith("\n")) readerString = readerString.subSequence(0, readerString.length() - 1)
        //替换文件
        //println(filePath + " has replace been.")
        file(filePath).withWriter('UTF-8') {
            writer ->
                writer.append(readerString)
        }
    }
}
//替换有导入目标been的文件内容
def ImportResReplacer(String filePath, sourceBeenName, targetBeenName) {
    def readerString = ""
    def hasReplace = false
    def xml = filePath.endsWith(".xml")
    file(filePath).withReader('UTF-8') { reader ->
        reader.eachLine { String it ->
            if (it.find(sourceBeenName)) {
                if (xml) {
                    //println("###$filePath: $sourceBeenName->$targetBeenName")
                    it = it.replaceAll("/$sourceBeenName", "/$targetBeenName")
                } else {
                    it = it.replaceAll("(?<![a-zA-Z0-9]+)(?<=[ \\.<:\\s\\,(]+)$sourceBeenName(?=[ \"\\.>\\?\\:\\(]*)(?![a-zA-Z0-9]+)", targetBeenName)
                }
                hasReplace = true
            }
            readerString <<= it
            readerString << '\n'
        }
    }
    if (hasReplace) {
        if (readerString.toString().endsWith("\n")) readerString = readerString.subSequence(0, readerString.length() - 1)
        //替换文件
        //println(filePath + " has replace been.")
        file(filePath).withWriter('UTF-8') {
            writer ->
                writer.append(readerString)
        }
    }
}

root.gradle

buildscript {
    dependencies {
        //https://github.com/shwenzhang/AndResGuard
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.21'
        //https://github.com/bytedance/AabResGuard
        classpath "com.bytedance.android:aabresguard-plugin:0.1.0"

        classpath "com.github.liujingxing:XmlClassGuard:1.2.3"

        classpath 'com.github.megatronking.stringfog:gradle-plugin:5.0.0'
        // 选用加解密算法库,默认实现了xor算法,也可以使用自己的加解密库。
        classpath 'com.github.megatronking.stringfog:xor:5.0.0'

        //https://github.com/qq549631030/AndroidJunkCode
        classpath 'com.github.qq549631030:android-junk-code:1.2.5'
        //classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3"
    }
}

在人家的基础上

1、我优化了名字的随机性

2、androidJunkCode这个感觉意义不到,基于asm我自己定义了一版逻辑

这是我处理后的结果,插入了很多无用代码在每个方法上

 3、stringfog优化支持了buildConfig的字符混淆

猜你喜欢

转载自blog.csdn.net/moziqi123/article/details/131561011