123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- import path_utils, contants, file_utils
- import os, subprocess, platform, zipfile
- from PrintLog 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"%s' % (apk_decompile_out_dir, out_put_unsigned_apk_path, useAppt2)
- ret = exec_jar_cmd(apktool_path, recompileCmd)
- PrintLog("------------------------------ finished recompile ------------------------------ ")
- return ret
- 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 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()
- 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命令
- 返回值:None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- """
- '''print(cmd)
- p = os.popen(cmd)
- print(p.read())'''
- cmd = 'java -jar "%s" %s' % (jar, params)
- PrintLog("[exec_jar_cmd]:%s" % cmd)
- ret = 0
- try:
- s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=None)
- 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('Exception ' + e)
- return 1
- return ret
- def exec_format_cmd(cmd, cd=None):
- """
- 执行cmd命令
- 返回值:None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- """
- '''print(cmd)
- p = os.popen(cmd)
- print(p.read())'''
- ret = 0
- try:
- s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cd)
- 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('Exception ' + e)
- return 1
- return ret
- 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')
- 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' % (
- aapt2, outApk, android_platforms, temp_manifest_path, temp_gen_path, complie_res_zip)
- 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 = 'javac -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % 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__":
- create_R_file('/Users/kaiweicai/Documents/Project/PackKit/YYXXPackKit/game/037848/dcm_tmphuawei',
- 'com.yyxx.qyj2.huawei')
|