| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- # -*- coding:utf-8 -*-
- import os
- import re
- import shutil
- import subprocess
- import sys
- import time
- import win32api
- import win32con
- import yaml
- import xml.etree.ElementTree as ET
- channel_rose = '朱雀'
- channel_coolpad='FAKE'
- channel_xmy = '小绵羊'
- channel_9hgame = '九狐'
- channel_icefoxgame = '冰狐'
- # 测试组游戏地址,需要根据游戏修改
- # 测试组游戏地址,需要根据游戏修改
- # 测试组游戏地址,需要根据游戏修改
- game_dir = r'\\10.8.230.114\public\测试组\20240523\破天一剑Y'
- # 其他情况使用BPM上面的任务名称
- game_channel = '破天一剑Y-朱雀'
- def copy_mommy_for_9hgame(decompile_dir_path):
- htprotect_dir_path = os.path.join(decompile_dir_path, 'smali', 'com', 'ydzs', 'framework')
- if not os.path.exists(htprotect_dir_path):
- os.makedirs(htprotect_dir_path)
- shutil.copy(os.path.join(r'D:\special_problem\九狐', 'MommyUtils.smali'), htprotect_dir_path)
- if ' ' in game_channel:
- game_channel = game_channel.replace(' ', '-')
- print(sys.argv)
- if len(sys.argv) == 3:
- game_dir = sys.argv[1]
- game_channel = sys.argv[2]
- print(game_dir)
- print(game_channel)
- def fix_install_fail_bug(decompile_dir_path):
- namespace = '{http://schemas.android.com/apk/res/android}'
- ET.register_namespace('android', 'http://schemas.android.com/apk/res/android')
- manifest_path = os.path.join(decompile_dir_path, 'AndroidManifest.xml')
- xml_tree = ET.parse(manifest_path)
- xml_root = xml_tree.getroot()
- application_node = xml_root.find('./application')
- etract_value = application_node.get(f'{namespace}extractNativeLibs')
- if etract_value is not None and etract_value == 'false':
- # 修改extractNativeLib
- application_node.set(f'{namespace}extractNativeLibs', 'true')
- xml_tree.write(manifest_path, encoding='utf-8', xml_declaration=True)
- yaml_path = os.path.join(decompile_dir_path, 'apktool.yml')
- file = open(yaml_path, 'r', encoding='utf-8')
- yaml_result = yaml.load(file, Loader=yaml.BaseLoader)
- sdk_info = yaml_result['sdkInfo']
- yaml_result['packageInfo']['renameManifestPackage'] = None
- print(sdk_info)
- if int(sdk_info['targetSdkVersion']) > 29:
- sdk_info['targetSdkVersion'] = '29'
- print(sdk_info)
- file.close()
- with open(yaml_path, 'w', encoding='utf-8') as f:
- yaml.dump(yaml_result, f)
- def rindex(lst, value):
- for i, v in enumerate(reversed(lst)):
- if v == value:
- return len(lst) - i - 1 # return the index in the original list`
- return None
- def move_game_apk_to_work():
- cmd_move_str = f'copy {game_path} {work_path}'
- print(cmd_move_str)
- result = subprocess.getoutput(cmd_move_str)
- print(result)
- def get_decompile_dir_name(apk_path):
- s_index = apk_path.index('.')
- print('s_index', s_index)
- p_index = rindex(apk_path, '\\')
- print('p_index:', p_index)
- dir_name = apk_path[:rindex(apk_path, '\\') + 1] + apk_path[p_index + 1:s_index]
- print('dir_name:', dir_name)
- return dir_name
- def find_r_smali_and_replace(smali_file_path, regex_str):
- with open(smali_file_path, 'r') as f:
- smali_str = f.read()
- pattern = re.compile(regex_str)
- resource_arr = pattern.findall(smali_str)
- if len(resource_arr) > 0:
- print(smali_file_path)
- for r_str in resource_arr:
- virtual_name = r_str[r_str.index(' ') + 1:r_str.index(',')]
- print(virtual_name)
- resource_type = r_str[r_str.index('R$') + 2:r_str.index(';')].capitalize()
- print(resource_type)
- resource_name = r_str[r_str.index('->') + 2:r_str.index(':')]
- print(resource_name)
- new_r_str = "const-string %s, \"%s\"\n\n\tinvoke-static {%s}, Lcom/ydzs/framework/MommyUtils;->get%sId(Ljava/lang/String;)I\n\n\tmove-result %s" % (
- virtual_name, resource_name, virtual_name, resource_type, virtual_name)
- print(new_r_str)
- smali_str = smali_str.replace(r_str, new_r_str)
- with open(smali_file_path, 'w') as f:
- f.write(smali_str)
- def replace_rose_resource(d_dir):
- r_regex_str = r'sget[^\n]*R\$layout[^\n]*I|sget[^\n]*R\$id[^\n]*I|sget[^\n]*R\$drawable[^\n]*I|sget[^\n]*R\$string[^\n]*I|sget[^\n]*R\$array[^\n]*I|sget[^\n]*R\$bool[^\n]*I|sget[^\n]*R\$integer[^\n]*I'
- for dirpath, dirnames, filenames in os.walk(d_dir):
- if r'com\wanwu' in dirpath or r'com\ydzs' in dirpath:
- for smali_file in filenames:
- smali_file_path = os.path.join(dirpath, smali_file)
- # print(smali_file_path)
- find_r_smali_and_replace(smali_file_path, r_regex_str)
- def fix_coolpad_version_3_method_name_change_bug(decompile_dir):
- is_version_3_sdk = False
- is_new_sdk_and_version_lt_version_3 = False
- for dirpath, dirnames, filenames in os.walk(decompile_dir):
- if r'com\yulong\sdk\promoter' in dirpath and 'OnGameAuthListener.smali' in filenames:
- auth_listener_path = os.path.join(dirpath, 'OnGameAuthListener.smali')
- with open(auth_listener_path, 'r', encoding='utf-8') as f:
- smali_str_arr = f.read()
- if 'onSuccess' in smali_str_arr:
- is_version_3_sdk = True
- if 'onResult' in smali_str_arr:
- is_new_sdk_and_version_lt_version_3 = True
- break
- for dirpath, dirnames, filenames in os.walk(decompile_dir):
- if r'com\yulong\sdk\promoter' in dirpath and 'PromoterGameAuthApi$1.smali' in filenames:
- smali_path = os.path.join(dirpath, 'PromoterGameAuthApi$1.smali')
- print(smali_path)
- with open(smali_path, 'r', encoding='utf-8') as f:
- smali_str_arr = f.readlines()
- index_str = r'onSuccess'
- if is_new_sdk_and_version_lt_version_3:
- index_str = r'onSuccess'
- elif is_version_3_sdk:
- index_str = r'onResult'
- for line in smali_str_arr:
- if index_str in line:
- print(line)
- index = smali_str_arr.index(line)
- if is_new_sdk_and_version_lt_version_3:
- smali_str_arr[index] = line.replace(index_str, 'onResult')
- elif is_version_3_sdk:
- smali_str_arr[index] = line.replace(index_str, 'onSuccess')
- print(smali_str_arr[index])
- break
- with open(smali_path, 'w', encoding='utf-8') as f:
- f.write(''.join(smali_str_arr))
- break
- return is_version_3_sdk
- def fix_coolpad_version_3_login_fail_bug(decompile_dir_path):
- insert_str_list = [
- '\n\t.locals 0\n\n',
- '\treturn-void\n\n']
- for dirpath, dirnames, filenames in os.walk(decompile_dir_path):
- if r'com\yulong\account\auth' in dirpath and 'AuthCodeApiImpl.smali' in filenames:
- smali_path = os.path.join(dirpath, 'AuthCodeApiImpl.smali')
- with open(smali_path, 'r', encoding='utf-8') as f:
- smali_str_arr = f.readlines()
- index_str = '.method private returnAuthError(Lcom/yulong/account/common/info/ErrorInfo;)V'
- end_method_str = '.end method'
- insert_str = ''.join(insert_str_list)
- on_create_index = 0
- insert_index = 0
- for line in smali_str_arr:
- if index_str in line:
- on_create_index = smali_str_arr.index(line)
- print('on_create_index', on_create_index, line)
- break
- for index, value in enumerate(smali_str_arr):
- if index > on_create_index and end_method_str in value:
- insert_index = index
- print('insert_index', index)
- break
- print(on_create_index, insert_index)
- del smali_str_arr[on_create_index + 1:insert_index]
- smali_str_arr.insert(on_create_index + 1, insert_str)
- with open(smali_path, 'w', encoding='utf-8') as f:
- f.write(''.join(smali_str_arr))
- break
- start_time = int(time.time())
- # 判断游戏是否需要修复并且是否是朱雀游戏,不需要修复就只需要拷贝arm64
- script_dir_list = os.listdir(r'F:\python_learn\day_1\script')
- is_need_fix = False
- for py_name in script_dir_list:
- if game_channel in py_name:
- is_need_fix = True
- break
- print("aaaaaaaaaaaaaaa", is_need_fix)
- game_path = 'game_path is empty'
- for game_name in os.listdir(game_dir):
- if ((channel_rose in game_channel or '青雀' in game_channel) and channel_rose in game_name) \
- or ((channel_coolpad in game_channel or 'fake' in game_channel) and channel_coolpad in game_name)\
- or ((channel_icefoxgame in game_channel or '冰狐' in game_channel) and channel_icefoxgame in game_name)\
- or (channel_9hgame in game_channel and channel_9hgame in game_name)\
- or (channel_xmy in game_channel and channel_xmy in game_name)\
- or ('遥望' in game_channel and '遥望' in game_name):
- game_path = os.path.join(game_dir, game_name)
- break
- print('game_path:', game_path)
- work_path = r"D:\work"
- apk_file_path = f'{work_path}' + game_path[rindex(game_path, "\\"):]
- apk_file_path_copy = os.path.join(work_path, 'copy_'+game_path[rindex(game_path, "\\")+1:])
- print(apk_file_path_copy)
- if '全民泡泡' in game_channel:
- if channel_rose in game_channel:
- decompile_dir_name = os.path.join(work_path, 'qmpp_rose')
- elif channel_coolpad in game_channel or 'fake' in game_channel:
- decompile_dir_name = os.path.join(work_path, 'qmpp_coolpad')
- elif channel_9hgame in game_channel:
- decompile_dir_name = os.path.join(work_path, 'qmpp_9hgame')
- else:
- decompile_dir_name = os.path.join(work_path, 'qmpp_xmy')
- elif '我的安吉拉2' in game_channel:
- if channel_rose in game_channel:
- decompile_dir_name = os.path.join(work_path, 'wdajl_rose')
- elif channel_coolpad in game_channel or 'fake' in game_channel:
- decompile_dir_name = os.path.join(work_path, 'wdajl_coolpad')
- elif channel_9hgame in game_channel:
- decompile_dir_name = os.path.join(work_path, 'wdajl_9hgame')
- else:
- decompile_dir_name = os.path.join(work_path, 'wdajl_xmy')
- else:
- decompile_dir_name = get_decompile_dir_name(apk_file_path)
- kfzs_sign = "kfzs_sign"
- kfzs_sign_youliang = "kfzs_sign_youliang"
- ydzs_sign = "ydzs_sign"
- # 签名文件,需要根据游戏修改
- # 签名文件,需要根据游戏修改
- # 签名文件,需要根据游戏修改
- current_sign = kfzs_sign
- if channel_rose in game_path or channel_coolpad in game_path or channel_9hgame in game_path:
- current_sign = ydzs_sign
- elif channel_xmy in game_path:
- current_sign = kfzs_sign
- # 修复脚本文件名,需要根据游戏修改
- # 修复脚本文件名,需要根据游戏修改
- # 修复脚本文件名,需要根据游戏修改
- if is_need_fix:
- fix_python_path = os.path.join(r'F:\python_learn\day_1\script', f'{game_channel}.py')
- print('fix_python_path', fix_python_path)
- # # 拷贝游戏包
- move_game_apk_to_work()
- # 复制一个原始包,只第一次复制
- if apk_file_path_copy[rindex(apk_file_path, '\\')+1:] not in os.listdir(work_path):
- print("执行拷贝原始游戏包")
- copy_origin_game_apk = f'copy {apk_file_path} {apk_file_path_copy}'
- subprocess.getoutput(copy_origin_game_apk)
- else:
- print("不执行拷贝原始游戏包")
- # # 解包
- cmd_decompile_str = rf'apktool d {apk_file_path} -f -o {decompile_dir_name} --only-main-classes'
- print(cmd_decompile_str)
- os.system(cmd_decompile_str)
- if channel_9hgame in game_path or channel_icefoxgame in game_path:
- copy_mommy_for_9hgame(decompile_dir_name)
- #朱雀包拷贝arm64
- if (channel_rose in game_path or channel_coolpad in game_path or channel_9hgame in game_path or channel_icefoxgame in game_path) and 'arm64-v8a' in os.listdir(os.path.join(decompile_dir_name, 'lib')):
- print('朱雀拷贝arm64')
- arm64_path = os.path.join(decompile_dir_name, 'lib', 'arm64-v8a')
- cmd_copy_arm64 = rf'copy D:\special_problem\朱雀arm64\libydzs.so {arm64_path}'
- os.system(cmd_copy_arm64)
- cmd_copy_arm64 = rf'copy D:\special_problem\朱雀arm64\libwanwusdk.so {arm64_path}'
- os.system(cmd_copy_arm64)
- #朱雀包拷贝x86
- if (channel_rose in game_path or channel_coolpad in game_path or channel_9hgame in game_path or channel_icefoxgame in game_path) and 'x86' in os.listdir(os.path.join(decompile_dir_name, 'lib')):
- print('朱雀拷贝x86')
- x86_path = os.path.join(decompile_dir_name, 'lib', 'x86')
- cmd_copy_x86 = rf'copy D:\special_problem\朱雀x86\libydzs.so {x86_path}'
- os.system(cmd_copy_x86)
- #朱雀包修改资源获取方式
- if channel_rose in game_path or channel_coolpad in game_path or channel_9hgame in game_path or channel_icefoxgame in game_path:
- print('执行朱雀包修改资源脚本')
- replace_rose_resource(decompile_dir_name)
- for dirpath, dirnames, filenames in os.walk(decompile_dir_name):
- if r'com\ydzs\framework\java' in dirpath and 'YDZSSDKUser.smali' in filenames:
- smali_path = os.path.join(dirpath, 'YDZSSDKUser.smali')
- print(smali_path)
- with open(smali_path, 'r', encoding='utf-8') as f:
- smali_str_arr = f.readlines()
- index_str = 'invoke-static {}, Lcom/ydzs/framework/SDKNativeWrapper;->nativeGetRealnameStatus()Ljava/lang/String;'
- index_str2 = 'invoke-static {p1}, Lcom/ydzs/framework/SDKNativeWrapper;->nativeEnterGame(Ljava/util/HashMap;)Ljava/lang/String;'
- replace_str = '\tinvoke-static {}, Lcom/ydzs/framework/SDKNativeWrapper;->nativeGetRealnameStatus()V\n'
- replace_str2 = '\tinvoke-static {p1}, Lcom/ydzs/framework/SDKNativeWrapper;->nativeEnterGame(Ljava/util/HashMap;)V\n'
- for line in smali_str_arr:
- if index_str in line:
- smali_str_arr[smali_str_arr.index(line)] = replace_str
- if index_str2 in line:
- smali_str_arr[smali_str_arr.index(line)] = replace_str2
- with open(smali_path, 'w', encoding='utf-8') as f:
- f.write(''.join(smali_str_arr))
- if r'com\ydzs\framework' in dirpath and 'SDKNativeWrapper.smali' in filenames:
- smali_path = os.path.join(dirpath, 'SDKNativeWrapper.smali')
- print(smali_path)
- with open(smali_path, 'r', encoding='utf-8') as f:
- smali_str_arr = f.readlines()
- index_str = '.method public static native nativeGetRealnameStatus()Ljava/lang/String;'
- index_str2 = '.method public static native nativeEnterGame(Ljava/util/HashMap;)Ljava/lang/String;'
- replace_str = '.method public static native nativeGetRealnameStatus()V\n'
- replace_str2 = '.method public static native nativeEnterGame(Ljava/util/HashMap;)V\n'
- for line in smali_str_arr:
- if index_str in line:
- smali_str_arr[smali_str_arr.index(line)] = replace_str
- if index_str2 in line:
- smali_str_arr[smali_str_arr.index(line)] = replace_str2
- with open(smali_path, 'w', encoding='utf-8') as f:
- f.write(''.join(smali_str_arr))
- # # 修复脚本
- if is_need_fix:
- os.system(f'python {fix_python_path} {decompile_dir_name} {game_dir}')
- #修复酷派新sdk 3.0接口方法名改变登录后闪退bug
- is_version_3_sdk = fix_coolpad_version_3_method_name_change_bug(decompile_dir_name)
- print('is_version_3_sdk: ', is_version_3_sdk)
- if is_version_3_sdk:
- fix_coolpad_version_3_login_fail_bug(decompile_dir_name)
- fix_install_fail_bug(decompile_dir_name)
- # # 合包
- if '全民泡泡' in game_channel or '我的安吉拉2' in game_channel:
- cmd_build_str = f'apktool b {decompile_dir_name} -f -o {apk_file_path} --use-aapt2'
- elif '乱世终结' in game_channel:
- cmd_build_str = f'apktool b {decompile_dir_name} -f -o {apk_file_path} -api 29'
- else:
- cmd_build_str = f'apktool b {decompile_dir_name} -f -o {apk_file_path}'
- print('cmd_build_str:', cmd_build_str)
- os.system(cmd_build_str)
- # 签名
- if '极无双' in game_channel or '终末阵线' in game_channel\
- or '灌篮高手' in game_channel or '炼仙传说' in game_channel\
- or '生死狙击' in game_channel or '全明星激斗' in game_channel\
- or '弹弹堂大冒险' in game_channel or '勇者秘境' in game_channel:
- current_sign = kfzs_sign_youliang
- if '航海王启航D' in game_channel:
- current_sign = ydzs_sign
- if '我叫MT:经典再现Y' in game_channel:
- current_sign = kfzs_sign
- cmd_sign_str = rf'{current_sign} {apk_file_path}'
- print(cmd_sign_str)
- cmd_result = subprocess.getoutput(cmd_sign_str)
- print(cmd_result)
- # 拷贝回测试组
- cmd_move_back_to_test_public = f'copy {apk_file_path} {game_dir}'
- print(cmd_move_back_to_test_public)
- cmd_result = subprocess.getoutput(cmd_move_back_to_test_public)
- print(cmd_result)
- end_time = int(time.time())
- print('执行时间s:', end_time-start_time)
- print('执行时间m:', (end_time-start_time)/60)
- win32api.MessageBox(0, "游戏修复完毕", "提醒", win32con.MB_OK)
|