123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- # -*- coding:utf-8 -*-
- import file_utils, path_utils, contants
- import os, subprocess, platform, re
- from print_log import printlog
- # decompile apk
- def decompile(origin_apk_full_path, apk_decompile_out_dir):
- printlog("------------------------ start to decompiling -------------------------")
- global SUFFIX_BAT
- if not os.path.exists(origin_apk_full_path):
- printlog("[no such apk]:%s" % origin_apk_full_path)
- return 1
- apktool_path = path_utils.get_apktool_path()
- decompileCmd = " d -f -o %s/ %s" % (apk_decompile_out_dir, origin_apk_full_path)
- ret = exec_jar_cmd(apktool_path, decompileCmd)
- printlog("------------------------ finished decompiling -------------------------")
- return ret
- # recompile fileset to apk
- def recompile(apk_decompile_out_dir, out_put_unsigned_apk_path):
- printlog("------------------------------ start to recompile ------------------------------ ")
- apktool_path = path_utils.get_apktool_path()
- useAppt2 = ''
- if contants.is_use_aapt2:
- useAppt2 = ' --use-aapt2'
- recompileCmd = 'b -f "%s" -o "%s"' % (apk_decompile_out_dir, out_put_unsigned_apk_path)
- ret = exec_jar_cmd(apktool_path, recompileCmd)
- printlog("------------------------------ finished recompile ------------------------------ ")
- return ret
- def V1signer(out_put_unsigned_apk_path, out_put_signed_apk_path, keystore_path, storepass, alias, keypass):
- getKeystoreAlgorithmCmd = "%s -list -v -keystore %s -alias %s -storepass %s" % (
- contants.key_tool_path, keystore_path, alias, storepass)
- ret, result = exec_format_cmd_with_result(getKeystoreAlgorithmCmd)
- regex = re.compile('签名算法名称: (\S+)')
- algorithm_method = regex.findall(result)
- if algorithm_method:
- algorithm_method = algorithm_method[0]
- else:
- regex = re.compile('Signature algorithm name: (\S+)')
- algorithm_method = regex.findall(result)
- if algorithm_method:
- algorithm_method = algorithm_method[0]
- if not algorithm_method:
- printlog("获取签名算法失败,签名失败。")
- return 1
- printlog("签名文件算法为:%s" % algorithm_method)
- resignCmd = "%s -sigalg %s -digestalg SHA1 -storepass %s -keypass %s -keystore %s -signedjar %s %s %s" % (
- contants.jar_signer_tool_path, algorithm_method, storepass, keypass, keystore_path, out_put_signed_apk_path,
- out_put_unsigned_apk_path, alias)
- return exec_format_cmd(resignCmd)
- def signer(out_put_unsigned_apk_path, out_put_signed_apk_path, keystore_path, storepass, alias, keypass):
- """
- 签名apk
- """
- # if game in signConfig:
- # if sdk in signConfig[game]:
- # keystore = signConfig[game][sdk]
- # else:
- # keystore = signConfig['default']
- # else:
- # keystore = signConfig['default']
- apksigner = path_utils.get_apksigner_path()
- # java -jar apksigner.jar sign --ks key.jks --ks-key-alias releasekey --ks-pass pass:pp123456 --key-pass pass:pp123456 --out output.apk input.apk
- useV2sign = ''
- if not contants.is_use_apk_v2_sign:
- useV2sign = ' --v2-signing-enabled=false'
- return exec_jar_cmd(apksigner,
- 'sign%s --ks "%s" --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out "%s" "%s"' % (
- useV2sign, keystore_path, alias, storepass,
- keypass, out_put_signed_apk_path, out_put_unsigned_apk_path))
- def zipalign(out_put_signed_apk_path, out_put_zipalign_apk_path):
- align_apk_tool = path_utils.get_zipalign_path()
- get_exec_permission(align_apk_tool)
- return exec_format_cmd('%s -f -p 4 %s %s' % (align_apk_tool, out_put_signed_apk_path, out_put_zipalign_apk_path))
- def exec_jar_cmd(jar, params):
- cmd = 'java -jar "%s" %s' % (jar, params)
- printlog("[exec_jar_cmd]:%s" % cmd)
- ret, result = exec_common_cmd(cmd)
- return ret
- def exec_format_cmd(cmd):
- ret, result = exec_common_cmd(cmd)
- return ret
- def exec_format_cmd_with_result(cmd):
- ret, result = exec_common_cmd(cmd)
- return ret, result
- def exec_common_cmd(cmd, cd=None):
- """
- 执行cmd命令
- 返回值:None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- """
- '''print(cmd)
- p = os.popen(cmd)
- print(p.read())''
- '''
- try:
- s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cd, encoding='utf-8')
- std_output, err_output = s.communicate()
- if platform.system() == 'Windows':
- std_output = std_output.decode('gbk')
- err_output = err_output.decode('gbk')
- '''
- None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- '''
- ret = s.returncode
- if ret:
- print('*******ERROR*******')
- print(std_output)
- print(err_output)
- print('*******************')
- cmd = 'error::' + cmd + ' !!!exec Fail!!! '
- else:
- print(std_output)
- print(err_output)
- cmd = cmd + ' !!!exec success!!! '
- print(cmd)
- except Exception as e:
- print(e)
- return 1, e
- return ret, std_output
- def create_R_file(apk_decompile_tmp_dir, package_name):
- decomplie_res_path = os.path.join(apk_decompile_tmp_dir, 'res')
- temp_gen_path = os.path.join(apk_decompile_tmp_dir, 'gen')
- if not os.path.exists(temp_gen_path):
- os.mkdir(temp_gen_path)
- temp_manifest_path = os.path.join(apk_decompile_tmp_dir, 'AndroidManifest.xml')
- android_platforms = path_utils.get_android_compile_tool_path()
- if not contants.is_use_aapt2:
- aapt = path_utils.get_aapt_path()
- ret = get_exec_permission(aapt)
- if ret:
- return ret
- createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (
- aapt, temp_gen_path, decomplie_res_path, android_platforms, temp_manifest_path)
- ret = exec_format_cmd(createRCmd)
- if ret:
- return ret
- else:
- aapt2 = path_utils.get_aapt2_path()
- ret = get_exec_permission(aapt2)
- if ret:
- return ret
- complie_res_zip = os.path.join(temp_gen_path, 'resource.zip')
- if os.path.exists(complie_res_zip):
- printlog('resource.zip is exists , No need to compile again ')
- else:
- complieResCmd = '%s compile --dir %s -o %s ' % (
- aapt2, decomplie_res_path, complie_res_zip)
- ret = exec_format_cmd(complieResCmd)
- if ret:
- return ret
- # link
- print('link res ...')
- outApk = os.path.join(temp_gen_path, 'sources.apk')
- linkResCmd = '%s link -o %s -I %s --manifest %s --java %s/ %s --custom-package %s' % (
- aapt2, outApk, android_platforms, temp_manifest_path, temp_gen_path, complie_res_zip,package_name)
- print('link cmd is %s' % linkResCmd)
- ret = exec_format_cmd(linkResCmd)
- if ret:
- return ret
- # 编译R文件
- r_source_pkg_name = package_name.replace(".", "/")
- r_pkg_path = os.path.join(temp_gen_path, r_source_pkg_name)
- r_source_path = os.path.join(r_pkg_path, 'R.java')
- createRClassCmd = '%s -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % (contants.javac_path, r_source_path)
- ret = exec_format_cmd(createRClassCmd)
- if ret:
- return ret
- # 生成dex
- print('dex R.class ...')
- outDex = os.path.join(temp_gen_path, 'classes.dex')
- if not contants.is_use_aapt2:
- dx = path_utils.get_dx_path()
- dexCmd = '--dex --no-warning --output="%s" "%s"' % (
- outDex, temp_gen_path)
- else:
- dx = path_utils.get_d8_path()
- clazz = os.path.join(r_pkg_path, '*.class')
- dexCmd = '--lib "%s" --output "%s" %s' % (
- android_platforms, temp_gen_path, clazz)
- ret = exec_jar_cmd(dx, dexCmd)
- if ret:
- return ret
- # 反向dex生成smali
- # 存放在out目录
- print('baksmali classes.dex ...')
- bak_smali_path = path_utils.get_baksmali_path()
- out_smali_path = os.path.join(temp_gen_path, 'out')
- ret = exec_jar_cmd(
- bak_smali_path, 'd "%s" -o "%s"' % (outDex, out_smali_path))
- if ret:
- return ret
- # 将生成的文件拷贝到目标目录
- print('copy R.smali ...')
- smaliPath = os.path.join(apk_decompile_tmp_dir, 'smali')
- file_utils.copy_file_all_dir(out_smali_path, smaliPath)
- return 0
- def get_exec_permission(file):
- """
- linux下获取执行权限
- """
- if platform.system() == 'Windows':
- return 0
- return exec_format_cmd('chmod +x "%s"' % file)
- if __name__ == "__main__":
- V1signer('/Users/kaiweicai/Documents/Project/PackKit/YYXXPackKit/output/g1_huawei_com.yyxx.qyj2.huawei_Y010402.apk',
- '/Users/kaiweicai/Documents/Project/PackKit/YYXXPackKit/output/g1_huawei_com.yyxx.qyj2.huawei_Y010402_____.apk',
- '/Users/kaiweicai/Documents/Project/PackKit/YYXXPackKit/keystore/ziyun.jks'
- , 'yh1234', 'key0', 'yh1234')
|