def extract_apk(apkPath, outputDir="output", sign=None, key=None): luacFiles = [] soFiles = [] soluaFiles = ['libcocos2dcpp.so', 'libcocos2dlua.so', 'libhellolua.so'] if os.path.exists(apkPath): fileName = os.path.splitext(os.path.basename(apkPath))[0] outputDir = os.path.join(outputDir, fileName) if not os.path.exists(outputDir): os.makedirs(outputDir) zipFile = zipfile.ZipFile(apkPath) for names in zipFile.namelist(): zipFile.extract(names, outputDir) if os.path.splitext(names)[-1] == '.luac': if sign and key: xxtea.decrypt_file(src_file=os.path.join(outputDir, names), key=key, target_file=os.path.join( outputDir, names), sign=sign) luacFiles.append(os.path.join(outputDir, names)) for i in soluaFiles: if i in names: soFiles.append(os.path.join(outputDir, names)) zipFile.close() else: exit(u'apk file not found') return luacFiles, soFiles
def decrypt_dir(dir, sign, key): for root, dirs, files in os.walk(dir): for f in files: if os.path.splitext(f)[-1] == ".luac": xxtea.decrypt_file(src_file=os.path.join(root, f), key=key, target_file=os.path.join(root, f), sign=sign)
def main(): parser = argparse.ArgumentParser( add_help=True, description="cocos2d luac decrypt & encrypt tool", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" example: {prog} -f 1.apk -o output # Y auto parse apk {prog} -f 1.apk -s aaaaaaa -k bbbbbbb # Y {prog} -f 1.apk -o output -s aaaaaaa -k bbbbbbb # Y {prog} -d dir -s aaaaaaa -k bbbbbbb # Y {prog} -d dir -s aaaaaaa -k bbbbbbb -e # encrypt lua""".format( prog=sys.argv[0])) parser.add_argument('-f', dest="apkFile", help='apk file') parser.add_argument('-o', dest="output", default="output", help="output dir") parser.add_argument('-d', dest="dir", help="luac dir") parser.add_argument('-s', dest="sign", default="", help="xxtea sign") parser.add_argument('-k', dest="key", default="", help="xxtea key") parser.add_argument('-e', dest="encrypt", action="store_true", help="encrypt") args = parser.parse_args() import pprint if args.sign and args.key and args.apkFile: extract_apk(args.apkFile, args.output, sign=args.sign, key=args.key) elif args.sign and args.key and args.dir and args.encrypt: pprint.pprint(encrypt_dir(args.dir, args.sign, args.key)) elif args.sign and args.key and args.dir: pprint.pprint(decrypt_dir(args.dir, args.sign, args.key)) elif args.apkFile and (args.sign == ''): sign = '' key = '' luacFiles, soFiles = extract_apk(args.apkFile, args.output) if luacFiles.__len__() > 1: sign = guess_sign(luacFiles) else: exit('not found Luac file') if soFiles.__len__() > 0: for soFile in soFiles: # 一般情况是存在于 strings soFile|grep -i key -A 3 -B 3 key = get_key_list(sign, soFile) for k in key: if xxtea.decrypt_file(luacFiles[0], k, luacFiles[0], sign): for luac in luacFiles[1:]: xxtea.decrypt_file(luac, k, luac, sign) # print '[-] decrypt success : {}'.format(luac) print "[*] sign:{} ,key:{}".format(sign, k) break else: print '[*] not found KEY,sorry' else: exit('not found so file')
def start_decrypt(so_file, src_path): sign = get_sign(src_path) if sign == "": print "error: src_path contains plain text files." return key_list = get_key_list(sign, so_file) if len(key_list) == 0: print "error: no valid key, check it manual." return global OUTPUT_PATH for key in key_list: print "try use key %s to decrypt" % (key) if os.path.exists(OUTPUT_PATH): shutil.rmtree(OUTPUT_PATH) os.mkdir(OUTPUT_PATH) is_right_key = False for parent, folders, files in os.walk(src_path): target_folder = parent.replace(src_path, OUTPUT_PATH) if not os.path.exists(target_folder): os.mkdir(target_folder) for file in files: full_path = os.path.join(parent, file) target_path = full_path.replace(src_path, OUTPUT_PATH) target_path = target_path.replace("luac", "lua") is_right_key = decrypt_file(full_path, key, target_path, sign) if not is_right_key: print "invalid key %s on file %s" % (key, full_path) break if not is_right_key: break if is_right_key: print "success" break