Android加固和签名的那些坑(防掉坑技巧)

上个月公司一个项目突然要找第三方进行安全漏洞的检测,于是打包了一个apk文件,发到第三方结构进行了安全检测,这项目我入职前就已经快完成的阶段,我后面基本是维护和小更新.比较坑的是之前的哥们连混淆都没有,更不要说加固了,最后扫出了30多个漏洞,看到检测报告都懵逼了.

自己对混淆和加固之前也只是知道皮毛没有深究,这次修复漏洞踩了不少坑,都是边上网搜资料边踩坑,总算搞定了,写出来防止后人踩坑,这里主要讲加固签名的坑,混淆这里不说了(自己对混淆还不熟)


混淆签名导出

  • Q: 进行混淆,怎么混淆?

    A: 我也是不太熟简单说一下自己的做法,先google一下常用的第三方框架的混淆代码找到自己需用的,剩下不常用的就上项目引用的框架对应的github项目地址找对应的混淆代码.

  • Q: 导出的时候怎么选v1和v2?区别在哪?

    A: 我自己是把v1和v2都勾上,区别是v1是7.0之前就存在的签名方式,v1相比v2安全系数要低,建议打包的时候v1和v2都勾上,只勾其中一个有可能会出现兼容问题,具体自己上网查

加固

  • Q: 怎么加固?

    A: 网上很多加固方式 (360,爱加密,梆梆..)都是傻瓜式的操作,可以找自己合适的.

  • Q:加固有哪些坑?

    A: apk进行加固之后签名信息都会丢失,加固完成之后要对apk重新进行签名,没有签名的apk是不能在手机上跑的

    A: 我开始用的是某数字公司的加固,加固完重新签名就发给第三方机构检测了,报告说我没有进行v2签名,一直很懵逼,明明勾了v2的签名为什么一直说我没进行v2签名,最后发现原来有些公司的提供的签名工具不支持v2签名,你用了他的签名工具他会说你签名成功,但实际上他只进行了v1的签名,真的很蛋疼,也不说明一下.

自己进行签名检查和加固后重新对apk进行签名

检查是否签名成功:

方法1:利用android sdk自带的工具

  • 用命令行进入本地的Android sdk目录(我用的是mac) 地址如下 cd /Users/用户名/sdk/build-tools/27.0.3/lib

    • 27.0.3是你的自己的sdk版本,不一定和我一样
  • 检查是否签名成功 java -jar apksigner.jar verify -v my.apk (my.apk为本地安装包的路径)

    • 如果出现:mac 下终端访问文件出现“Permission Denied”解决方案的话:

    • 一个文件有3种权限,读、写、可执行,你这个文件没有可执行权限,需要加上可执行权限。

    • 终端下先cd到该文件的目录下,执行命令 chmod a+x ./apksigner.jar(文件名)

    • 重新执行步骤2检查是否有签名,会出现下面类似的结果:

      • Verifies
      • Verified using v1 scheme (JAR signing): true //已进行v1签名
      • Verified using v2 scheme (APK Signature Scheme v2): false //没有进行v2签名

很容易理解,ture是已签名,false是未签名,都为true的话说明v1,v2都成功签名了.

方法2:

  • 下载GetApkInfo.jar

  • 用命令行进入GetApkInfo.jar文件目录 cd /Users/xxxx/GetApkInfo.jar

  • 执行 java -jar GetApkInfo.jar my.apk检查是否有v2签名

    • 如果出现:mac 下终端访问文件出现“Permission Denied”解决方案的话:

    • 一个文件有3种权限,读、写、可执行,你这个文件没有可执行权限,需要加上可执行权限。

    • 先cd到该文件的目录下,执行命令 chmod a+x ./apksigner.jar(文件名)

    • 再次执行 java -jar GetApkInfo.jar my.apk

         执行结果: 成功
         应用信息: 
         包名: com.xxx.xx.xx
         版本名: 2.0.1
         版本号: 2
         签名文件MD5: e093xxxb53xxxxxf5bxxxe17xxx7d
         V1签名验证通过: true
         使用V2签名: true
         V2签名验证通过: true
      
  • 如果你要确保自己没用错签名文件(虽然一般不会这么智障)这种方法比较适合你,能看到已签名的md5值

  • keytool -v -list -keystore /Users/xxxx/MyAPP/test.jks(路径是你的进行签名的秘钥路径)

      有效期开始日期: Mon May 08 09:35:21 CST 2017, 截止日期: Fri May 02 09:35:21 CST 2042
      证书指纹:
           MD5: E0:93:xx:xx:xx:22:xx:xx:xx:5F:xx:xx:xx:xx:15:7D
           SHA1: xx:xx:xx:xx:xx:xx:C0:A4:xx:33:6Exx02:80:xx:DA:xx:xx:5F:xx:C3
           SHA256: 39:xx:3A:xx:xx:BA:xx:A8:6C:xx:D0:C6:xx:BC:xx:76:25:xx:xx:A3:86:xx:xx:A0:xx:E8:xx:xx:4F:xx:xx:9C
           签名算法名称: SHA256withRSA
           版本: 3 
    

然后把两个md5的值进行比对,如果一致说明你的签名没用错秘钥 - -||

4.手动进行签名操作:

  • 进入本地的sdk目录 cd /Users/xxxx/sdk/build-tools/27.0.3/lib
  • 执行签名操作:

java -jar apksigner.jar sign --ks /Users/xxxx/Desktop/key.jks --ks-key-alias test --ks-pass pass:123456 --key-pass pass:123456 --out /Users/xxxx/Desktop/签名后的安装包.apk /Users/xxxx/Desktop/需要进行签名的安装包.apk

上面的命令会执行同时执行v1,v2签名

注意仔细看上的命令行:进了黑色加粗的文字需要替换成实际的信息

  • 第一个加粗的是秘钥的路径
  • 第二个是秘钥的别名
  • 第三个是秘钥的密码
  • 第四个是秘钥的密码
  • 第五个是进行了签名的安装包保存的路径
  • 第六个是需要进行签名的安装包路径

说个小插曲,我们的项目找的是一个规模很大的公司进行检测,开始用了网上的免费的加固工具加固拿去检测,别人拿去测试之后全部都脱壳了,说这种免费的加固安全没有保障,要用他们的加固服务可以解决,要收费..呵呵,因为项目比较特殊只能答应了,打包签名了apk,发到他们那边进行了加固后他们把apk发回来让我重新签名,签名后apk用不了,闪退....老板说别人大公司应该不会出现这种小问题,是我的问题.恩,自己也怀疑是我的错. 当天折腾到凌晨才下班,经历了上面的一顿折腾后发现v1,v2都签名了,并且md5值也没问题. 这时就有底气的去质问那家公司,最后发现是他们的加固出问题.

一般来说进行了上面的方法重新签名并且检查md5值没错,应该不会出问题了这时候可以去质疑一下加固方的问题.

github参考链接1

github参考链接2

先写这些记录一下,后面有需要再更新,有什么问题可以在下面留言讨论.