上架谷歌马甲包有这么难?

5,827 阅读7分钟

简介

大家好,我是猪猪侠,是做安卓开发的,将近四年的工作经验。这是我第一次写文章,写得不好希望大家见谅,同时也希望大家给出意见或者建议。开始写文章主要有一下几个目的:一是俗话说好记性不如烂笔头,把自己的学到或者研究出来的写出来,印象会更加深刻。不知道有没有人和我有过同样的感受,就是某一个知识点自己可能“已经”会了,但是当说给别人听或者面试被问到时,就说不出来或者表达不出来。如果能把该知识点写出来,而且别人看了也能看明白,那我觉得才是真正的理解了。第二个目的自己写的文章能被别人指出,提点建议或者意见,会对自己的理解有帮助。当然如果文章能帮到大家在工作中解决问题,拿就更好了。

背景

好了,就也不多bb了,那就开始今天的主题吧。前段时间我们公司上架马甲包到Google Play,结果全军覆没了。老板就“召开”紧急会议,讨论马甲包上架的问题。从运维的账号申请到技术代码编写,一一讨论哪些可能优化的,或者说有可能是因为我们哪一点的不小心触犯了Google审查的规则。会后,猪猪侠也是“积极”的思考啊,思考代码方面能做什么优化。思考了半天啊,终于一种方式,那就是加入混淆的垃圾代码

avatar

如果将垃圾代码集成apk中

下面有几个名词,“混淆”、“拆包”、“重打包”、“Smali”、“签名”。我们都知道,安卓项目开启混淆,就会将我们代码将类和方法名等变成a、b等的名字,同时最重要的是它会把我们没有用到的代码直接移除掉,因为我们加的垃圾代码肯定是不会被调用的,所以打开混淆后我们的垃圾代码肯定是会被移除的。有的同学肯定会说,那我们用keep啊,可以让垃圾代码不要移除。我们的目的是加入混淆的垃圾代码,如果用keep,那垃圾代码是没有被混淆,和我们目的就背道而驰了。那下面介绍流程:

第一步,新建library,然后在build.gradle中加入相关代码,网上有很多关于这方面的文章,我这里就不多说了。

lintOptions {
        abortOnError false
    }
    
def _BASENAME = "rubbish";
def _VERSION = "_v1.0";
def _DestinationPath = "build/outputs/jar"; //生成jar包的位置
def zipFile = file('build/intermediates/aar_main_jar/debug/classes.jar'); //待打包文件位置

task deleteBuild(type:Delete){
    delete _DestinationPath + _BASENAME + _VERSION + ".jar"
}

task makeJar(type:Jar){
    from zipTree(zipFile)
    baseName = _BASENAME + _VERSION
    destinationDir = file(_DestinationPath)
}

makeJar.dependsOn(deleteBuild, build)

需要注意的是zipFile,就是原始jar的目录,不同的AndroidStudio路径可能不一样,这个要注意,还有上面代码开始的地方,要忽略警告,否则可能会报错。

得到jar后,下面我们开始混淆jar包。用的工具是proguardgui,在我们的sdk中就有,在sdk目录的tools\proguard\bin\proguardgui.bat,打开后是如下图所示 使用方法在Input/Output一栏中,添加你要混淆的jar包,然后添加你要输出到那个目录。 下面在Shrinking一栏将所有的勾选全部取消掉,然后在Obfuscation一栏中选项不需要动,直接到Optimization中,将Optimize选项勾选取消 然后关键的一步,在Information一栏中Target选项进项选择低版本的,我一般选择1.6版本,然后下面的Ignore warings一定要勾选,否则会失败的 现在所有选项我们已经勾选完成,最后一步Process一栏点击右下角的Process按钮。 如果最后出现Processing completed successfully,就表明已经成功了,上面可能会有各种警告我们不需要关心

下面我们将混淆后的jar包编译成dex,使用sdk自带的命令dx命令

dx --dex --output=<目标dex> <jar包>

然后需要将dex变成smali,需要一个工具smali.jar, smali下载地址 将我们上一步生成的dex拷贝到smali目录中,使用

java -jar baksmali.jar d <dex文件>

紧接着我们开始对我们打好的apk进行拆包,需要用到apktool工具apktool下载链接,将apk拷贝到apktool目录下,使用命令进行解包,成功后就会得到下面的文件目录结构

java -jar apktool.jar d <需要拆包的apk>

然后将我们刚才生成的smali文件拷贝解包后目录中 注意目录结构啊,要在解包后有个smali文件夹中的包路径下,下面就是进行重打包

java -jar apktool.jar b <拆包目录>

重打包成功后,会在刚才的拆包目录中生成一个dist目录,里面就是我们加入垃圾代码后的apk 紧接着就是对我们重打包的apk进行v1签名、对齐、v2签名。下面这三步我就不详细介绍了,相信大家都应该没问题,如果有不清楚的可以查阅一些资料。

v1签名:jarsigner -verbose -keystore <签名文件> -storepass <密钥密码> -keypass <密钥密码> -signedjar <签名后的apk> <签名前的apk> <密钥别名>
对齐:zipalign -v 4 <原apk> <apk> 
v2对齐:java -jar apksigner.jar sign --ks <签名文件> --ks-key-alias 签名文件别名 --ks-pass pass:密码 --key-pass pass:密码 --out <输出apk> <未签名apk>

如果上面三步都成功的话,使用验证码命令,验证后v1、v2都是true

java -jar apksigner.jar verify -v <apk>

经过已经步骤我们完成了添加混淆垃圾代码后的apk,为了验证我们最后验证我们的apk是否真的成功打入了混淆的垃圾代码,使用安卓逆向助手反编译看一下 这是我们最开始写的垃圾代码,一个Person类 这是混淆后垃圾代码的样子。Ok,大功告成,溜了溜了!!!

这就完了?等一下,这他喵的十几个命令,有的命令还那么长,太麻烦了。那怎么办呢,没错,我要放发招了。使用脚本!!!

@echo off
echo "start"
C:
cd C:\Users\Administrator\Desktop\rebale
::将混淆后的jar包编译成dex
call dx --dex --output=rubbish.dex *.jar
echo "build dex success"
::将dex编译成smali
call java -jar D:\Develop\smali\baksmali.jar d rubbish.dex
echo "build smali success"
::对apk进行解包
call java -jar D:\Develop\apktool\apktool.jar d original.apk
echo "take apart apk success"
echo "please copy smali"
::暂停,将编译成smali的垃圾代码拷贝到解包目录中
pause
::进行重打包
call java -jar D:\Develop\apktool\apktool.jar b original
echo "reuppack success"
::进行v1签名
call jarsigner -verbose -keystore C:\Users\Administrator\Desktop\jks\test.jks -storepass 123456 -keypass 123456 -signedjar signed.apk C:\Users\Administrator\Desktop\rebale\original\dist\original.apk test
echo "v1 sing success"
::进行对齐
call zipalign -v 4 C:\Users\Administrator\Desktop\rebale\signed.apk zipalign.apk
echo "zipalign success"
::进行v2签名
call java -jar D:\Develop\sdk\build-tools\28.0.3\lib\apksigner.jar sign --ks C:\Users\Administrator\Desktop\jks\test.jks --ks-key-alias test --ks-pass pass:123456 --key-pass pass:123456 --out app-release.apk zipalign.apk
echo "v2 sign success"
::验证签名是否正确
call java -jar D:\Develop\sdk\build-tools\28.0.3\lib\apksigner.jar verify -v app-release.apk
pause

怎么使用呢?新建一个xx.bat的脚本文件,然后使用上面的代码,上面的命令根据自己的实际目录进行相应的修改。首先混淆的jar包还是要自己手动生成的,然后将混淆的jar包和生成的apk放在同一目录下。比如上面我在桌面建立一个rebale目录,将jar包和apk放进rebale目录中。 然后开始执行脚本 执行到这里,拆包和垃圾代码生成smali已经完成了,这里在等着将smali拷贝到拆包目录下,拷贝完成后按回车

最后成功之后会出现上面的字样。

总结

这种方法上架Google Play马甲包不一定百分之百有用,因为上架马甲包不单单是代码的问题,还有商务或者运营在申请账号以及服务器的等原因。因为采用这种方式,我们已经成功上架了两款,所以想分享给大家。最后,第一次写文章,说实话有点累,花了半天时间,但是写完之后会很开心。之前一直都有一颗写文章的心,无奈自己太过于懒惰。现在终于迈开了脚步,大家一起加油。