轮子脚本,本质为使用subprocess替代大量无谓的交互command,内部方法自由扩展
呃我是有用AndroidKiller,但耐不住常用到adb自定义的臭长命令,例如经常取httpcanary的hcy回本地分析
代码 usage
通常
路径为apk绝对地址,则解包
路径为目录地址,则尝试打包
自定义
自定义方法与参数
Usage: python dece.py [-i INSTALL] [-e EXTRA] path Integrate decompile related complicated command. Arguments: path program/apk path | special use "http://www.likecs.com/" -i INSTALL, --install INSTALL adb remote install apk -e EXTRA, --extra EXTRA use inner func individually, |adb_install(apk_path) |get_info(apk_path) |jadx(*args) |as_debug Examples: dece.py D:\\com.android.unpack_catalog -i true dece.py / -e func++args1++args2 (params split with ++) Source codedece.py(cmd等实际轮子路径填自己的)
#!/usr/bin/python __author__ = "jsoneri" __version__ = "1.0" import time import os import re import chardet import shutil import argparse import subprocess from loguru import logger keystore = r'D:\xxxxx\my-release-key.keystore' # 签名证书 nickname = 'my_alias' # 签名证书别称 keypwd = b'123456' # 签名证书密码 device = "FA68H0XXXXXX" # 手机设备号 模拟器则IP端口 cmd = { 'aapt': r'D:\xxxxx\aapt', # 看包信息,与get_info关联 'apktool': r'D:\xxxxx\apktool.bat', 'jadx': r'D:\xxxxx\bin\jadx-gui.bat' } bash = { 'aapt': r'/mnt/d/xxxxx/aapt', 'apktool': r'java -jar -Duser.language=en -Dfile.encoding=UTF8 /mnt/d/xxxxx/apktool.jar', 'jadx': ValueError('在WSL上开gui需要vncsever,xhost等操作较麻烦,本人自禁用') # } class DeceUtils: def packapk(self, path, apk): # 回编译 command = f'{cmd["apktool"]} b {path}' subprocess.run(command.split(' ')) return self.signing(path, apk) def unpack(self, path): # 反编译 command = f"{cmd['apktool']} d -f {path}" subprocess.run(command.split(' ')) def jadx(self, *args): ori = f"{cmd['jadx']}" if args: for arg in args: ori += f' {arg}' subprocess.run(ori) @logger.catch def adb_install(self, apk_path): subprocess.run(f'adb -s {device} install {apk_path}', stdout=subprocess.PIPE) logger.debug('-*- apk installation running -*- ') @logger.catch def signing(self, path, apk): """一般签名是在打包时才用的,,所以绑定为pack后使用,通常非单独用""" dist = f'{path}\\dist' name = apk.replace('.apk', '') keyname = keystore.split('\\')[-1] shutil.copy(keystore, dist) command = f'jarsigner -verbose -keystore {keyname} -signedjar {name}_signed.apk {apk} {nickname}' obj = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=dist) obj.communicate(keypwd) obj.terminate() obj.kill() logger.debug('-*- apk signed -*- ') return f'{name}_signed.apk' @logger.catch def as_debug(self): """设备当前窗口进程转发端口给AS的5005调用""" command = 'adb shell dumpsys activity activities|grep Resumed' infos = subprocess.run(command, stdout=subprocess.PIPE) r = re.search(r'u0 ([\w.]+)/[\w.]+ ', infos.stdout.decode(chardet.detect(infos.stdout)['encoding'])).group(1) infos = subprocess.run(f'adb shell ps | grep {r}', stdout=subprocess.PIPE) r = re.search(r' (\d+) ', infos.stdout.decode(chardet.detect(infos.stdout)['encoding'])).group(1) subprocess.run(f'adb forward tcp:5005 jdwp:{r}', stdout=subprocess.PIPE) def get_info(self, apk_path): try: command2 = f'{cmd["aapt"]} dump badging ' infos = subprocess.run(command2 +apk_path, shell=True, stdout=subprocess.PIPE) # infos.stdout.decode(_code) return infos.stdout.decode(chardet.detect(infos.stdout)['encoding']) except Exception as e: logger.error(f"occur exception: {str(type(e))}:: {str(e)}") @staticmethod def get_apk(path): if '.apk' in os.path.split(path)[-1]: logger.info(f'输入为apk绝对地址,准备解包') return 'unpack', '' else: name = path.split("\\")[-1] dist = f'{path}\\dist' apk = f'{name}.apk' if not os.path.exists(f'{dist}\\{apk}'): logger.info(f'输入为目录且未发现打包痕迹,准备打包此目录') return 'pack', apk else: logger.info(f'输入为目录但发现有打包痕迹,请检查/删除再操作') os.startfile(dist) return '', '' def main(self, path, install_flag=False): flag, apk = self.get_apk(path) if flag == 'unpack': self.unpack(path) elif flag == 'pack': apk = self.packapk(path, apk) self.adb_install(f'{path}\\dist\\{apk}') if install_flag else None info = self.get_info(f'{path}\\dist\\{apk}') package = re.search(r'package: name=\'(com\.[\w.]+)\'', info).group(1) mainActivity = re.search(r'activity name=\'(com\.[\w.]+)\'', info).group(1) print(f'>>> {apk} infos: ↓↓ \npackage: [{package}], mainActivity: [{mainActivity}]') if __name__ == '__main__': class ArgParser(argparse.ArgumentParser): def error(self, message): print(f"DecompileUtils v{__version__}\nby {__author__}\n\nError: {message}\n") print(self.format_help().replace("usage:", "Usage:")) self.exit(0) parser = ArgParser( add_help=False, description="Integrate decompile related complicated command.", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=r""" Examples: %(prog)s D:\\com.android.unpack_catalog -i true %(prog)s / -e func++args1++args2 (params split with ++) """) if os.name == 'posix': cmd = bash args = parser.add_argument_group("Arguments") args.add_argument('path', help='program/apk path | special use "http://www.likecs.com/"') args.add_argument('-i', '--install', type=bool, default=False, help='adb remote install apk') args.add_argument('-e', '--extra', type=str, required=False, help=r'use inner func individually, ' r'|adb_install(apk_path) |get_info(apk_path) |jadx(*args) |as_debug') parsed = parser.parse_args() if parsed.extra: _args = parsed.extra.split('++') logger.debug(f'>> extra >> {_args}') ret = getattr(DeceUtils(), _args[0])(*_args[1:]) print(ret) if ret else None time.sleep(0.05) logger.debug(f'func【 {_args[0]} 】 end') else: DeceUtils().main(parsed.path, parsed.install) 其他相关地址
jadx
apktool
芒果Geek大佬的github代下服务