当前位置:   article > 正文

APK解包与修改

apk解包

概述

这是我2018年时,在第一家公司时的需求时,开始研究的。
当需要修改apk内的文件,以此切换不同的渠道。所以需要解包和打包的操作。甚至是还考虑过出包含玩家信息的推广包,所以最后连服务器分包的功能都给做出来了。

不过万变不离其宗,掌握好基础的解包和打包就可以了。

工具

工欲善其事必先利其器,解包与二次打包,我们需要使用以下三种工具:

  1. Apktool
  2. JDK
  3. 压缩解压缩工具

ApkTool用于解包与打包。

JDK在我们重新打包之后的签名环节需要使用到。

由于APK就是个压缩包,所以我们也可以使用解压缩工具进行解压来实现解包。不过使用这种方法无法解密Manifest,需要查看或者修改Manifest还需要使用Apktool来进行实现。

使用压缩解压缩工具修改包内文件

如上一章所说,我们可以使用解压再压缩的方式,对包内添加文件,或者修改我们自身创建的文件。

但是,我们在压缩成新的apk之后,需要对apk进行签名。在文章最后的部分中我们会提到。

Windows压缩解压环境布置

Windows不像Linux系统,会提供压缩与解压命令。如果我们需要使用命令行工具来实现分包,就需要准备Windows的压缩解压环境。

如果你是Linux系统或者Mac系统,则可以跳过这一步。

访问http://stahlworks.com/dev/index.php?tool=zipunzip
可以下载zip与unzip的程序。放到C:/windows目录下,即可在命令行中调用压缩加压指令。

# 压缩
zip -r fileName.apk ./*

# 解压
unzip -o -d /path fileName.apk
  • 1
  • 2
  • 3
  • 4
  • 5

当然,你也可以在命令行中调用第三方压缩工具来实现这一目的。

命令行数组

如果想要生成一批apk,他们中需要修改的位置都是相同的,只有修改的内容不同。第一时间我们会想到字符串数组。

但是在命令行中是没有数组的,有的文章采用本地文件逐行读取的方法来实现。但我们也可以使用下面的方法来对数组进行模拟:

@echo off
set a[0]=1 
set a[1]=2 
set a[2]=3 
echo The first element of the array is %a[0]% 
echo The second element of the array is %a[1]% 
echo The third element of the array is %a[2]%

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意事项

我们对apk直接解压的操作,实际上没有完成解包的过程,只是一种投机取巧的方式。
如果我们没有删除签名相关内容,会在我们二次打包之后,签名时弹出报错:
jarsigner: java.lang.SecurityException:SHA1 digest error for META-INF/CERT.RSA

因此,我们需要在完成自己所需修改之外,还得删除包内的META-INF目录。

参考:https://stackoverflow.com/questions/37513084/jarsigner-java-lang-securityexceptionsha1-digest-error-for-meta-inf-cert-rsa-a

完整工具

@echo off
setlocal enabledelayedexpansion
rem 拖入apk并获取其路径和文件名
echo 请拖入需要处理的apk
set /p input=
set apkUrl=
for /f "delims=" %%i in ('dir /b %input%') do (set apkUrl=!apkUrl!%%i)
set fileName=%apkUrl:.apk=%
rem 解包并删除签名
if exist output rmdir /s/q output
md output
cd output
md %fileName%
unzip -o -d %fileName% %input%
rmdir /s/q %fileName%\META-INF
rem 修改文件打包并签名
for  do (
[这里填写修改操作]
cd !fileName!
zip -r [your file name].apk ./*
cd..
jarsigner -verbose -keystore [keystore path] -signedjar [out apk name].apk [current apk name].apk [alias name] -storepass [password]
)
pause
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

使用apktool进行解包与打包

如果你需要查看或者修改Manifest文件,甚至修改java代码,则需要使用apktool进行解包。

以前会有一个叫做Smali2JavaUI的项目,可以直接解包apk,并将smali文件转换成了java代码。但是由于年久失修,已经无法适用于新版的安卓应用了。因此,这里就不再提及。

安装与使用

Apktool是一个jar文件,官网是https://ibotpeaches.github.io/Apktool/
可以参考它的文档进行使用。

但是下载之后你会发现,如果直接使用命令行调用的它的命令,会单独开一个新的窗口,后面的命令行的代码不会顺利执行。
实际上它的命令其实是执行了同目录下的一个bat脚本文件,而且是加了参数的。
所以,在使用apktool时候,我比较推荐直接调用jar包,以解包为例:


java -jar -Duser.language=zh_cn -Dfile.encoding=UTF-8 apktool.jar d [file name] -o [decode path]

  • 1
  • 2
  • 3

如果是直接下载的jar包可以不用管这一步。

我们常用的命令其实就是解包和打包:


apktool d xxx.apk
apktool b xxx

  • 1
  • 2
  • 3
  • 4

完整工具

#coding=utf-8
 
import os,os.path
from shutil import rmtree
 
def decode_apk(filename, decode_folder):
    if os.path.exists(decode_folder):
        rmtree(decode_folder)
        print "删除已存在的文件夹"+decode_folder
    print "开始解包"+filename+"->"+decode_folder
    apktool_command = "java -jar -Duser.language=zh_cn -Dfile.encoding=UTF8 apktool.jar d " + filename + " -o " + decode_folder
    os.system(apktool_command)
    print "解包成功"+filename+"->"+decode_folder
def build_apk(folder, apk_out):
    if os.access(apk_out,os.R_OK):
        print "删除已存在的"+apk_out
        os.remove(apk_out)
    print "打包中"+apk_out
    apktool_command = "java -jar -Duser.language=zh_cn -Dfile.encoding=UTF8 apktool.jar b " + folder + " -o " + apk_out
    os.system(apktool_command)
    print "打包成功"+apk_out
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

脚本需要和apktool.jar在同一目录下,否则命令中需要指定路径。

签名

二次打包之后的Apk,需要再次签名才能够使用。

签名文件保证

如果你有keystore文件,则可以直接使用。如果是jks文件,可以经过p12文件中转,再转换成keystore文件:


keytool -importkeystore -srckeystore xxx.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore xxx.p12

keytool -v -importkeystore -srckeystore xxx.p12 -srcstoretype PKCS12 -destkeystore xxx.keystore -deststoretype JKS

  • 1
  • 2
  • 3
  • 4
  • 5

如果没有keystore文件,可以使用keytool重新生成。这个工具应该是集成在JDK中的:

keytool -genkeypair -alias serverkey -keypass 111111 -storepass 111111 -dname "C=CN,ST=GD,L=SZ,O=haha,OU=dev,CN=haha.com" -keyalg RSA -keysize 2048 -validity 3650 -keystore server.keystore

  • 1
  • 2

可以以借助Android Studio进行生成。

对apk签名

签名需要使用jarsigner工具:

jarsigner -verbose -keystore [keystore path] -signedjar [out apk name].apk [current apk name].apk [alias name] -storepass [password]
  • 1

签名结束之后,也可以进行验证:

jarsigner -verify [out apk name].apk
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/865865
推荐阅读
相关标签
  

闽ICP备14008679号