微信资源混淆使用

来源:互联网 发布:淘宝卖otc药品的 编辑:程序博客网 时间:2024/05/22 09:41

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

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

apktool d -s xxx.apk

                             

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


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


微信资源混淆有两种方案:

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

原创粉丝点击