# coding:utf8 import os import logging import re import glob import shutil import distutils.dir_util import gw_file_system import xml.etree.ElementTree as ET ANDROID_NS = 'http://schemas.android.com/apk/res/android' def script(workspace_sdk_dir, extract_dir, channel_sdk_info, new_game_channel_info, game_info): logging.info('game_pack_info: ' + str(channel_sdk_info)) # 逆向渠道id if channel_sdk_info['id'] == "323": fixLifecycleMethod(extract_dir) return def script_pre(workspace_sdk_dir, extract_dir, channel_sdk_info, new_game_channel_info, game_info): if channel_sdk_info['SDKName'] == 'x7sy': logging.info('workspace_sdk_dir: ' + str(workspace_sdk_dir)) s1 = os.path.join(workspace_sdk_dir, 'x7sy/ForRes/drawable') x7_bg_female_pink_7_xml = os.path.join(s1, "x7_bg_female_pink_7.xml") x7_bg_female_pink_right_7 = os.path.join(s1, "x7_bg_female_pink_right_7.xml") if os.path.exists(x7_bg_female_pink_7_xml): os.remove(x7_bg_female_pink_7_xml) if os.path.exists(x7_bg_female_pink_right_7): os.remove(x7_bg_female_pink_right_7) s1 = os.path.join(workspace_sdk_dir, 'x7sy/ForRes/values/public.xml') handle_public_xml(s1) return def script_last(workspace_sdk_dir, extract_dir, channel_sdk_info, new_game_channel_info, game_info): logging.info('game_pack_info: ' + str(channel_sdk_info)) fix_android_manifest(extract_dir) if channel_sdk_info['id'] == "512": s1 = os.path.join(extract_dir, "smali_classes4", "com/netease") smali_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_dir, "com/netease") list_package = ["androidcrashhandler","autotext","environment","godlikeshare","htprotect","neox","ngpush","ntunisdk"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) replace_kf_application(extract_dir) if channel_sdk_info['id'] == "323": change_smali(extract_dir) s1 = os.path.join(extract_dir, "smali", "androidx") s3 = os.path.join(extract_dir, "smali_classes3", "androidx") if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package_one(s1, s3) s1 = os.path.join(extract_dir, "smali_classes3", "androidx") s3 = os.path.join(extract_dir, "smali_classes4", "androidx") list_package = ["a", "appcompat", "b", "c", "coordinatorlayout", "customview", "activity", "asynclayoutinflater", "browser", "cardview", "cor"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) if channel_sdk_info['SDKName'] == 'smallsheep': move_package_for_small_sheep(extract_dir) if channel_sdk_info['SDKName'] == 'x7sy': s1 = os.path.join(extract_dir, "smali_classes2", "com") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "com") list_package = ["a", "adjust", "alipayx", "cloudplay", "google", "heepay", "helpshift", "iapppay", "ipaynow"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) s1 = os.path.join(extract_dir, "smali_classes3", "androidx") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "androidx") list_package = ["core", "d", "drawerlayout", "e", "f", "fragment", "legacy", "lifecycle", "loader", "media", "multidex"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) if channel_sdk_info['SDKName'] == 'jolo': s1 = os.path.join(extract_dir, "smali_classes3", "androidx") s3 = os.path.join(extract_dir, "smali_classes5", "androidx") list_package = ["core", "d", "drawerlayout", "e", "f", "fragment", "legacy", "lifecycle", "loader"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) if channel_sdk_info['SDKName'] == 'sogou': rm_wechatpay(extract_dir) if channel_sdk_info['SDKName'] == 'xxzhushou': rm_alipay(extract_dir) if channel_sdk_info['id'] == "389": s1 = os.path.join(extract_dir, "smali", "com") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "com") list_package = ["smwl", "netease"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) if channel_sdk_info['id'] == "549" or channel_sdk_info['id'] == "591": s1 = os.path.join(extract_dir, "smali_classes5", "com") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "com") list_package = ["netease"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) if channel_sdk_info['id'] == "591" or channel_sdk_info['id'] == "549" : s1 = os.path.join(extract_dir, "smali_classes4", "com") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "com") list_package = ["netease"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) return def fix_android_manifest(decompile_dir): manifest_file = decompile_dir + '/AndroidManifest.xml' ET.register_namespace('android', ANDROID_NS) key_android_name = '{' + ANDROID_NS + '}authorities' target_tree = ET.parse(manifest_file) target_root = target_tree.getroot() manifest_node = target_root.get("package") application_node = target_root.find('application') if application_node is None: return if application_node is not None: activity_list_node = application_node.findall('provider') if activity_list_node is None: return for activityNode in activity_list_node: node_name_str = activityNode.attrib[key_android_name] if node_name_str == 'com.netease.onmyoji.coolpad111': activityNode.set(key_android_name, manifest_node + '111') target_tree.write(manifest_file) def create_mutil_smali(decompileDir): f_idx = 5 while True: tmp = gw_file_system.get_full_path(os.path.join(decompileDir, 'smali_classes%d' % f_idx)) tmp = tmp.replace('\\', '/') tmp = re.sub('/+', '/', tmp) if os.path.exists(tmp): f_idx += 1 else: smali_classes2_dir = tmp break # endwhile os.mkdir(smali_classes2_dir) return smali_classes2_dir def move_package(s1, s3, list_package): for d in list_package: src = os.path.join(s1, d) if os.path.exists(src): dst = os.path.join(s3, d) distutils.dir_util.copy_tree(src, dst) distutils.dir_util.remove_tree(src) def move_package_one(src, dst): if os.path.exists(src): distutils.dir_util.copy_tree(src, dst) distutils.dir_util.remove_tree(src) def rm_alipay(extract_dir): delet_file = os.path.join(extract_dir, 'smali/org/json') print delet_file logging.info('delet_file: ' + delet_file) shutil.rmtree(delet_file) def rm_wechatpay(extract_dir): delet = os.path.join(extract_dir, 'smali_classes2/com/ipaynow') print delet logging.info(delet) shutil.rmtree(delet) def change_smali(fooDir): for smali_flie in glob.glob(fooDir + "/" + "smali*/com/kunlun/platform/android/KunlunApplication.smali"): print smali_flie if os.path.isfile(smali_flie): with open(smali_flie, 'r+') as f: cont = f.read() change_str = 'invoke-virtual {p0}, Lcom/kf/framework/KFApplication;->onCreate()V' str = 'invoke-virtual {p0}, Landroid/app/Application;->onCreate()V' print len(change_str) print len(str) change_str2 = 'invoke-virtual {v0, p1}, Lcom/kf/framework/KFApplication;->onConfigurationChanged(Landroid/content/res/Configuration;)V' str2 = 'invoke-virtual {v0, p1}, Landroid/app/Application;->onConfigurationChanged(Landroid/content/res/Configuration;)V' cont = cont.replace(change_str, str) cont = cont.replace(change_str2, str2) with open(smali_flie, 'w') as tf: tf.write(cont) def intoFirstLine(target, repl, cont): # srcStr = "onBackPressed" # regexp = '.method (?:public|protected) +?'+target+"\([^.]+?\.locals +[0-9]{1,2}" regexp = '.method (?:public|protected) +?' + target + "\([^.]+?\.locals +([0-9]{1,2})" # print(regexp) reObj = re.compile(regexp) matchO = reObj.search(cont) if matchO: # print(matchO.group(0)) methodHead = matchO.group(0) if matchO.group(1) == "0": methodHead = re.sub("locals +0", "locals 1", methodHead) repl = methodHead + r'\n\n ' + repl + r'\n\n' cont = reObj.sub(repl, cont) else: # todo call .super method cont += r'.method protected ' + target + r'()V\n\n .locals 0\n\n ' + repl + r'\n\n .end method\n' return cont def fixLifecycleMethod(preDir): for tfile in glob.glob(preDir + "/" + "smali*/com/supercell/titan/kunlun/GameAppKunlun.smali"): if os.path.isfile(tfile): with open(tfile, 'r+') as f: cont = f.read() changes = { "onPause": "invoke-static {}, Lcom/qihoo/gamecenter/sdk/matrix/Matrix;->onPause()V", "onResume": "invoke-static {}, Lcom/qihoo/gamecenter/sdk/matrix/Matrix;->onResume()V", "onDestroy": "invoke-static {p0}, Lcom/qihoo/gamecenter/sdk/matrix/Matrix;->destroy(Landroid/content/Context;)V", "onStop": "invoke-static {}, Lcom/qihoo/gamecenter/sdk/matrix/Matrix;->onStop()V" } for k, v in changes.iteritems(): cont = intoFirstLine(k, v, cont) f.seek(0) f.write(cont) f.close() def handle_public_xml(public_xml_path): if not os.path.exists(public_xml_path): logging.info('public_xml is null: ' + public_xml_path) return new_lines = [] with open(public_xml_path, 'r+') as f: for line in f.readlines(): # l = line.strip() if line.find("x7_bg_female_pink_7") > -1: continue if line.find("x7_icon_female_pink") > -1: continue if line.find("x7_bg_female_pink_right_7") > -1: continue new_lines.append(line) f.seek(0) f.truncate() f.writelines(new_lines) return def move_package_for_small_sheep(extract_dir): s1 = os.path.join(extract_dir, "smali_classes4", "com/netease") smali_classes2_dir = create_mutil_smali(extract_dir) s3 = os.path.join(smali_classes2_dir, "com/netease") list_package = ["mpay", "neox", "ngpush", "ntunisdk", "onmyoji", "pharos", "tryautotext2", "unisdk", "xyqa"] if not os.path.exists(s3): distutils.dir_util.mkpath(s3) move_package(s1, s3, list_package) lines = ['invoke-virtual {p3}, Lcom/kf/framework/KFApplication;->getApplicationInfo()Landroid/content/pm/ApplicationInfo;', 'invoke-virtual {v0}, Lcom/kf/framework/KFApplication;->onCreate()V'] def replace_kf_application(extract_dir): # goal_file = glob.glob(os.path.join(extract_dir, 'smali*/com/netease/ntunisdk/unifix_hotfix_library/proxyApplication/UFProxyApplication.smali'))[0] goal_file_list = glob.glob(os.path.join(extract_dir, 'smali*/com/netease/ntunisdk/unifix_hotfix_library/proxyApplication/UFProxyApplication.smali')) if len(goal_file_list)==0: logging.info("没有UFPROXYAPPlication") return goal_file=goal_file_list[0] print(os.path.isfile(goal_file)) if os.path.isfile(goal_file): logging.info('method_proceed: ' + 'goal_file') print(goal_file) with open(goal_file, 'r+') as f: cont = f.read() for line in lines: change_line = line.replace('Lcom/kf/framework/KFApplication', 'Landroid/app/Application') cont = cont.replace(line, change_line) logging.info('replace_str: ' + cont) with open(goal_file, 'w+') as tf: tf.write(cont) if __name__ == '__main__': replace_kf_application("D:\\work\\yys")