android 加固服务器,Python 脚本构建Android APK 自动加固、打渠道包并上传服务器

Python 脚本构建Android APK 自动加固、打渠道包并上传服务器

常规流程

打出原始apk

使用乐固工具加固并打出响应渠道包

将生成的渠道包上传对应服务器,生成推广链接

因为每一步都需要人工介入,尤其当渠道较多时,相当耗时,且有出错的可能,所以考虑以脚本替代人工执行步骤。

准备工作

qshell 用于上传七牛服务器的命令行工具

VasDolly多渠道打包工具,同时支持基于V1签名和V2签名进行多渠道打包

apksigner.jar 用于为apk进行签名,支持v1+v2签名,这里有个坑,一开始我选择使用的是java包内的jarsigner,后发现只支持v1签名。apksigner.jar位置在android sdk的libs中,可以考虑将其复制到当前工作目录下

脚本编写

初始化

# 初始化环境

def init():

command = './qshell account'

result = os.popen(command).read()

if ('error' in result):

command = './qshell account '

os.popen(command).read()

if not os.path.exists(ORIGIN_APK):

raise RuntimeError('找不到原始 apk 文件')

# 删除临时 apk 文件

if os.path.exists(TEMP_APK):

os.remove(TEMP_APK)

# 删除上传失败日志文件

if os.path.exists(QINIU_FAILED_LIST):

os.remove(QINIU_FAILED_LIST)

# 初始化清缓存文件

fp = open(REFRESH_CONFIG,'w')

fp.write(QINIU_URL+ORIGIN_APK)

fp.close()

os.makedirs(OUTPUT_PATH)

首先我们进行qshell的设置,设置当前用户的AccessKey, SecretKey和Name, Name是用户可以任意取的名字,表示当前在本地记录的账户的名称。

ORIGIN_APK是打包出来的原始apk

TEMP_APK、QINIU_FAILED_LIST、REFRESH_CONFIG 都是运行生成的结果,在下一次运行初期进行一次清理。

上传临时APK文件到七牛中

# 上传临时APK文件到七牛

def uploadApp():

command = './qshell rput --overwrite %s %s %s ' % (

QINIU_BUCKET, ORIGIN_APK, ORIGIN_APK)

uploadResult = os.popen(command).read()

if 'success' not in uploadResult:

raise RuntimeError('上传临时APK文件到七牛失败:'+uploadResult)

refresh()

# 刷新七牛缓存

def refresh():

command = './qshell cdnrefresh -i %s' % (REFRESH_CONFIG)

os.popen(command).read()

将临时文件上传七牛,这样我们能拿到改apk的链接,方便下一步的加固工作

QINIU_BUCKET:七牛空间名称,可以为公开空间或私有空间

使用乐固进行加固并签名

# 使用乐固加固

def legu():

cred = credential.Credential(TENCENT_KEY, TENCENT_SECRET)

httpProfile = HttpProfile()

httpProfile.endpoint = "ms.tencentcloudapi.com"

clientProfile = ClientProfile()

clientProfile.httpProfile = httpProfile

client = ms_client.MsClient(cred, "ap-shanghai", clientProfile)

req = models.CreateShieldInstanceRequest()

params = '''{

"AppInfo":{

"AppUrl":"%s",

"AppMd5":"%s"

},

"ServiceInfo":{

"ServiceEdition":"basic",

"SubmitSource":"api"

}

}''' % (QINIU_URL+ORIGIN_APK, md5_file(ORIGIN_APK))

req.from_json_string(params)

#调用腾讯 API乐固接口加固

resp = client.CreateShieldInstance(req)

itemId = resp.ItemId

if not itemId:

raise RuntimeError('创建乐固实例失败:'+resp)

req = models.DescribeShieldResultRequest()

params = '{"ItemId":"%s"}' % (itemId)

req.from_json_string(params)

#下载加固结果

for num in range(20):

time.sleep(120)

print("查看乐固加固结果,第%d次尝试中..." % num)

resp = client.DescribeShieldResult(req)

if resp.TaskStatus != 2:

break

else:

raise RuntimeError('加固超时')

downloadURL = resp.ShieldInfo.AppUrl

appMD5 = resp.ShieldInfo.ShieldMd5

if downloadURL:

urllib.urlretrieve(downloadURL, TEMP_APK)

if md5_file(TEMP_APK) != appMD5:

raise RuntimeError('下载加固结果失败')

# 签名

command = sign_command(TEMP_APK)

os.popen(command).read()

# 计算文件的 md5值

def md5_file(name):

m = md5()

a_file = open(name, 'rb') # 使用二进制格式读取文件内容

m.update(a_file.read())

a_file.close()

return m.hexdigest()

#使用apksigner进行签名

def sign_command(file):

return 'java -jar apksigner.jar sign --ks %s --ks-key-alias ALIAS --ks-pass pass:PASS --key-pass pass:PASS --out %s %s'% (SIGN_KEY, file,file)

使用乐固API接口进行加固,完成加固后下载至本地并进行md5的验证,确保包的一致性,而后在本地对其进行签名

TENCENT_KEY、TENCENT_SECRET 用于乐固的腾讯key&&secret

ALIAS别名 PASS密码 SIGN_KEY秘钥所在位置

打渠道包

# 打渠道包

def channel():

command = 'java -jar VasDolly.jar put -c %s %s %s' % (

CHANNEL_CONFIG, TEMP_APK, OUTPUT_PATH)

result = os.popen(command).read()

searchObj = re.search(r'total (\d+) channel apk', result, re.M | re.I)

total = int(searchObj.group(1))

channelCount = len(open(CHANNEL_CONFIG, 'rU').readlines())

if total != channelCount:

raise RuntimeError('生成渠道包数量异常:应生成%s,实际生成%s' % (channelCount, total))

rename()

# 重命名

def rename():

files = os.listdir(OUTPUT_PATH)

for file in files:

f = os.path.join(OUTPUT_PATH, file)

#os.popen(sign_command(f))

os.rename(f, f.replace('-'+TEMP_APK, '.apk'))

不同于以往先打渠道包而后进行签名的方式,VasDolly可以让我们在不破坏签名的情况下进行渠道打包。

这边也有个坑,因为原先采用的打渠道包方式是umeng,umeng会直接修改manifest的channel字段,所以我们在包内获取渠道名的方式都是直接读这个字段。VasDolly不会去修改这个字段,因而需要改变项目内所有获取渠道名的方式,这边可以参考VasDolly的说明进行修改。

这样我们的加固及打渠道都完成了,渠道包会输出在你指定的OUTPUT_PATH。

CHANNEL_CONFIG 包含所有渠道名称 换行分隔

上传到七牛

def deploy():

uploadCmd = './qshell qupload2 --overwrite --rescan-local --src-dir=%s --bucket=%s --failure-list %s --check-hash --thread-count 10' % (

QINIU_UPLOAD_PATH, QINIU_BUCKET, QINIU_FAILED_LIST)

os.popen(uploadCmd).read()

if os.path.getsize(QINIU_FAILED_LIST):

raise RuntimeError('上传到七牛失败,失败文件列表见:' + QINIU_FAILED_LIST)

#清缓存

fp = open(REFRESH_CONFIG,'w')

files = os.listdir(OUTPUT_PATH)

fp.writelines([QINIU_URL+QINIU_UPLOAD_SUBPATH+file+'\n' for file in files])

fp.close()

refresh()

# 刷新七牛缓存

def refresh():

command = './qshell cdnrefresh -i %s' % (REFRESH_CONFIG)

os.popen(command).read()

这样就完成了整个加固、打渠道包、上传服务器的过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值