微信资源混淆使用

本文探讨了APP资源文件的安全隐患,通过反编译示例展示了资源文件可能带来的风险。文章提到微信和美团的资源保护策略,重点介绍了微信的资源混淆方案,包括通过jar包和gradle配置两种方法。通过配置文件和相关工具,可以实现资源混淆,提高应用的安全性,同时提供了一种在开发过程中便捷测试混淆后apk的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

随着公司上市,我们app在安全方面有更高的要求,目前我们只使用了ProGuard来保护代码的安全,对资源文件的保护力度不大,但是资源文件是存在比较大的安全隐患的。那资源会有哪些安全隐患呢?

通过运行下面命令就能进行反编译;

apktool d -s xxx.apk

                             

通过上图中的目录结构,我们可以看到这个应用的资源文件大概有:anim、drawable、layout、menu、values等等,我们可以通过修改这些文件夹下的资源文件,并通过apktool进行回编译(apktool b 命令)就能创建一个经过修改过的APK应用,例如我们修改下图中红色横线所标示的layout文件,就能往原有APK的支付信息(根据资源名称猜测这个layout的意图)中添加一些我们自己的东西;

 

网上看,微信和美团在资源保护方面都有自己的实现。对比了这两家资源混淆实现方案,发现微信的方案不会影响编译流程,更加简单。所以决定在我们的app中使用微信的资源混淆。

微信资源混淆:

微信资源混淆有两种方案:https://my.oschina.net/bugly/blog/536064

(1)使用jar包

       Java -jar AndResGuard-cli-1.1.16.jar oldapk -config config.xml -out res_proguard -signature release.keystore testres testres testres

      

      --config,指定具体config文件的路径;
      --out,指定生成文件具体的输出路径,其中混淆的mapping会在输出文件夹中以resource_mapping_(输入apk的名称).txt命名。
      --signature,指定签名信息,若在命令行设置会覆盖config.xml中的签名信息,顺序为签名文件路径、storepass、keypass、storealias。  

      --mapping, 指定旧的mapping文件,保证同一资源文件在不同版本混淆后的名称保持一致。若在命令行设置会覆盖config.xml中的信息。
      --7zip,指定7zip的路径,若已添加到环境变量则不需要设置。此处必须为全路径,例如linux: /shwenzhang/tool/7za,Windows需要加上.exe 结尾。
      --zipalign,指定zipalign的路径,若已添加到环境变量则不需要设置。此处必须为全路径,例如linux: /shwenzhang/sdk/tools/zipalign,Windows需要加上.exe结尾。
      --repackage,如果想要出渠道包等需求,我们可能希望利用7zip直接重打包安装包。
 

     如何写config配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<resproguard>
    <!--defaut property to set  -->
    <issue id="property">
        <!--whether use 7zip to repackage the signed apk, you must install the 7z command line version in window -->
        <!--sudo apt-get install p7zip-full in linux -->
        <!--and you must write the sign data fist, and i found that if we use linux, we can get a better result -->
        <seventzip value="false"/>
        <!--the sign data file name in your apk, default must be META-INF-->
        <!--generally, you do not need to change it if you dont change the meta file name in your apk-->
        <metaname value="META-INF"/>
        <!--if keep root, res/drawable will be kept, it won't be changed to such as r/s-->
        <keeproot value="false"/>
    </issue>

    <!--whitelist, some resource id you can not proguard, such as getIdentifier-->
    <!--isactive, whether to use whitelist, you can set false to close it simply-->
    <issue id="whitelist" isactive="true">
        <!--you must write the full package name, such as com.tencent.mm.R -->
        <!--for some reason, we should keep our icon better-->
        <!--and it support *, ?, such as com.tencent.mm.R.drawable.emoji_*, com.tencent.mm.R.drawable.emoji_?-->
        <!--<path value="<your_package_name>.R.drawable.icon"/>-->
        <!--<path value="<your_package_name>.R.string.com.crashlytics.*"/>-->
        <!--<path value="<your_package_name>.R.string.tb_*"/>-->
        <!--<path value="<your_package_name>.R.layout.tb_*"/>-->
        <!--<path value="<your_package_name>.R.drawable.tb_*"/>-->
        <!--<path value="<your_package_name>.R.color.tb_*"/>-->
    </issue>

    <!--keepmapping, sometimes if we need to support incremental upgrade, we should keep the old mapping-->
    <!--isactive, whether to use keepmapping, you can set false to close it simply-->
    <!--if you use -mapping to set keepmapping property in cammand line, these setting will be overlayed-->
    <issue id="keepmapping" isactive="false">
        <!--the old mapping path, in window use \, in linux use /, and the default path is the running location-->
        <path value="{your_mapping_path}"/>
    </issue>

    <!--compress, if you want to compress the file, the name is relative path, such as resources.arsc, res/drawable-hdpi/welcome.png-->
    <!--what can you compress? generally, if your resources.arsc less than 1m, you can compress it. and i think compress .png, .jpg is ok-->
    <!--isactive, whether to use compress, you can set false to close it simply-->
    <issue id="compress" isactive="true">
        <!--you must use / separation, and it support *, ?, such as *.png, *.jpg, res/drawable-hdpi/welcome_?.png-->
        <path value="*.png"/>
        <path value="*.jpg"/>
        <path value="*.jpeg"/>
        <path value="*.gif"/>
        <path value="resources.arsc"/>
    </issue>

    <!--sign, if you want to sign the apk, and if you want to use 7zip, you must fill in the following data-->
    <!--isactive, whether to use sign, you can set false to close it simply-->
    <!--if you use -signature to set sign property in cammand line, these setting will be overlayed-->
    <issue id="sign" isactive="true">
        <!--the signature file path, in window use \, in linux use /, and the default path is the running location-->
        <path value="release.keystore"/>
        <!--storepass-->
        <storepass value="testres"/>
        <!--keypass-->
        <keypass value="testres"/>
        <!--alias-->
        <alias value="release"/>
    </issue>

</resproguard>

 

 

这种方式更适合用在服务器打包apk,我们平时在开发过程中,不可能每次都是用这种方式把apk包进行混淆之后,再安装到手机上进行测试。所以有第二种方式,在gradle中进行配置。

 

(2)gradle中配置资源混淆

在工程根目录下的build.gradle的dependencies中进行如下配置

 

  dependencies {
      
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.8'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        //test git2
    }
 

 

然后在app目录下的build.gradle中进行如下配置

 

apply plugin: 'com.android.application'
apply plugin: 'AndResGuard'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3" //////////需要加入的配置

    defaultConfig {
        applicationId "com.example.annotationtestdemo"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

/////////////需要加入的配置
andResGuard {
    // mappingFile = file("./resource_mapping.txt")
    mappingFile = null
    // 当你使用v2签名的时候,7zip压缩是无法生效的。
    use7zip = true
    useSign = true
    // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
    keepRoot = false
    whiteList = [
            // for your icon
            "R.drawable.icon",
            // for fabric
            "R.string.com.crashlytics.*",
            // for google-services
            "R.string.google_app_id",
            "R.string.gcm_defaultSenderId",
            "R.string.default_web_client_id",
            "R.string.ga_trackingId",
            "R.string.firebase_database_url",
            "R.string.google_api_key",
            "R.string.google_crash_reporting_api_key",
            "R.drawable.umeng*",
            "R.layout.umeng*",
            "R.drawable.umeng*",
            "R.anim.umeng*",
            "R.color.umeng*",
            "R.style.*UM*",
            "R.style.umeng*",
            "R.id.umeng*",
            "R.string.UM*"
    ]
    compressFilePattern = [
            "*.png",
            "*.jpg",
            "*.jpeg",
            "*.gif",
            "resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.2.8'
        //path = "/usr/local/bin/7za"
    }

    /**
     * 可选: 如果不设置则会默认覆盖assemble输出的apk
     **/
   // finalApkBackupPath = "${project.rootDir}/final.apk"

    /**
     * 可选: 指定v1签名时生成jar文件的摘要算法
     * 默认值为“SHA1”
     **/
    digestalg = "SHA256"
}
 

 

加入以上配置以后,sync一下以后,在gradle的task中,可以看到有下面的两个task

 

双击resguardDebug或是resguardRelease即可生成资源混淆后的apk。。。

 

生成的apk的路径是在build/outputs/apk/AndResGuard_xxx-debug目录下,

 

 

但是生成资源混淆以后的apk不会自动安装,这样的话,不利于我们在开发的过程中进行测试,,为了方便测试,我修改了一下gradle的配置,将resguardDebug/resguardRelease放在assemeble之后,这样点击“Run”按钮之后,编译完成之后会自动安装资源混淆之后的apk,这样在测试过程中,如果发现资源混淆导致的问题,可以随时发现。

 

 
 
记:
为了实现上面实现的功:在android studio中我尝试直接使用AndResGuard-cli-1.1.16.jar来对apk进行资源混淆,,主要思路是在assemble之后增加一个task,改task中调用AndResGuard-cli-1.1.16.jar对assemble生成的apk进行资源混淆,,
 
 
 
 
public class ProguardRes {


    //获取apk的名称
    public static void generateResProguardApk(String root) {

        String buildOutput = root+"/build/outputs/apk";
        def buildDirFile = new File(buildOutput);
        buildDirFile.eachFile { file ->
            if (file.getName().contains("debug") || file.getName().contains("release")) {
                println("jtt:    "+file.getName());
                proguardRes(root,file.getName())
                return
            }
        }
    }

    //实用AndResGuard-cli-1.1.16.jar对apk进行资源混淆
    public static void proguardRes(String root,String apkName){

        String buildOutput = root+"/build/outputs/apk/";
        println("java -jar "+root+"/AndResGuard-cli-1.1.16.jar "+buildOutput+apkName+" -config "+root+"/config.xml -out "+buildOutput+"resProguard")

        //资源混淆
        Process p = Runtime.getRuntime().exec("java -jar "+root+"/AndResGuard-cli-1.1.16.jar "+buildOutput+apkName+" -config "+root+"/config.xml -out "+buildOutput+"resProguard")

        try{
            p.waitFor()
        }catch (Exception e){

        }

        File oldApk = new File(buildOutput+apkName);
        String newApkName = getProguardResFileName(apkName);

        File resProguardApk = new File(buildOutput+"resProguard/"+newApkName);
        if(resProguardApk.exists()){
            println("generation res proguard apk success ")
            FileUtils.deleteFile(oldApk)
            FileUtils.copyFile(resProguardApk, oldApk);
        }
    }

    private static String getProguardResFileName(String oldApkName){
        int indexDot = oldApkName.indexOf(".");
        String newName = oldApkName.subSequence(0,indexDot)+"_signed.apk"
        return  newName;
    }

}
AndResGuard 是一款 Android资源混淆工具,资源混淆组件不涉及编译过程,只需输入一个apk(无论签名与否,debug版,release版均可,在处理过程中会直接将原签名删除),可得到一个实现资源混淆后的apk(若在配置文件中输入签名信息,可自动重签名并对齐,得到可直接发布的apk)以及对应资源ID的mapping文件。同时可在配置文件中指定白名单,压缩文件(支持*,?通配符),支持自动签名,保持旧mapping,7z重打包,对齐等功能。 本工具支持 Linux、Window 跨平台使用,但测试表示若使用7z压缩,Linux 下的压缩率更高。示例代码:apply plugin: 'AndResGuard' buildscript {     dependencies {         classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.1.9'     } } andResGuard {     mappingFile = null     use7zip = true     useSign = true     keepRoot = false     whiteList = [         //for your icon         "R.drawable.icon",         //for fabric         "R.string.com.crashlytics.*",         //for umeng update         "R.string.umeng*",         "R.string.UM*",         "R.string.tb_*",         "R.layout.umeng*",         "R.layout.tb_*",         "R.drawable.umeng*",         "R.drawable.tb_*",         "R.anim.umeng*",         "R.color.umeng*",         "R.color.tb_*",         "R.style.*UM*",         "R.style.umeng*",         "R.id.umeng*"         //umeng share for sina         "R.drawable.sina*"     ]     compressFilePattern = [         "*.png",         "*.jpg",         "*.jpeg",         "*.gif",         "resources.arsc"     ]      sevenzip {          artifact = 'com.tencent.mm:SevenZip:1.1.9'          //path = "/usr/local/bin/7za"     } }简单用法:java -jar andresguard.jar input.apk若想指定配置文件或输出目录:java -jar andresguard.jar input.apk -config yourconfig.xml -out output_directory若想指定签名信息或mapping信息:java -jar andresguard.jar input.apk -config yourconfig.xml     -out output_directory -signature signature_file_path storepass_value     keypass_value storealias_value -mapping mapping_file_path若想指定7zip或zipalign的路径(若已设置环境变量,这两项不需要单独设置):java -jar andresguard.jar input.apk  -7zip /shwenzhang/tool/7za  -zipalign /shwenzhang/sdk/tools/zipalign若想用7zip重打包安装包,同时也可指定output路径,指定7zip或zipalign的路径(此模式其他参数都不支持):java -jar andresguard.jar -repackage input.apk -out output_directory  -7zip /shwenzhang/tool/7za  -zipalign /shwenzhang/sdk/tools/zipalign 标签:AndResGuard
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值