#! /usr/bin/python3 # -*- coding: utf-8 -*- # Author: kelvinBen # Github: https://github.com/kelvinBen/AppInfoScanner import os import re import config import hashlib from queue import Queue import libs.core as cores class AndroidTask(object): def __init__(self, path, package): self.path = path self.package = package self.file_queue = Queue() self.shell_flag = False self.packagename = "" self.comp_list = [] self.file_identifier = [] self.permissions = [] def start(self): # 检查java环境是否存在 if os.system("java -version") != 0: raise Exception("Please install the Java environment!") input_file_path = self.path if os.path.isdir(input_file_path): self.__decode_dir__(input_file_path) else: if self.__decode_file__(input_file_path) == "error": raise Exception( "Retrieval of this file type is not supported. Select APK file or DEX file.") return {"comp_list": self.comp_list, "shell_flag": self.shell_flag, "file_queue": self.file_queue, "packagename": self.packagename, "file_identifier": self.file_identifier, "permissions": self.permissions} def __decode_file__(self, file_path): apktool_path = str(cores.apktool_path) backsmali_path = str(cores.backsmali_path) base_out_path = str(cores.output_path) filename = os.path.basename(file_path) suffix_name = filename.split(".")[-1] if suffix_name == "apk" or suffix_name == "hpk": name = filename.split(".")[0] output_path = os.path.join(base_out_path, name) self.__decode_apk__(file_path, apktool_path, output_path) elif suffix_name == "dex": f = open(file_path, 'rb') md5_obj = hashlib.md5() while True: r = f.read(1024) if not r: break md5_obj.update(r) dex_md5 = md5_obj.hexdigest().lower() self.file_identifier.append(dex_md5) output_path = os.path.join(base_out_path, dex_md5) if not os.path.exists(output_path): os.makedirs(output_path) self.__decode_dex__(file_path, backsmali_path, output_path) else: return "error" def __decode_dir__(self, root_dir): dir_or_files = os.listdir(root_dir) for dir_or_file in dir_or_files: dir_or_file_path = os.path.join(root_dir, dir_or_file) if os.path.isdir(dir_or_file_path): self.__decode_dir__(dir_or_file_path) else: if self.__decode_file__(dir_or_file_path) == "error": continue # 分解apk def __decode_apk__(self, file_path, apktool_path, output_path): cmd_str = ('java -jar "%s" d -f "%s" -o "%s" --only-main-classe') % ( str(apktool_path), str(file_path), str(output_path)) if os.system(cmd_str) == 0: self.__shell_test__(output_path) self.__scanner_file_by_apktool__(output_path) else: print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues") raise Exception(file_path + ", Decompilation failed.") # 分解dex def __decode_dex__(self, file_path, backsmali_path, output_path): cmd_str = ('java -jar "%s" d "%s"') % (str(backsmali_path), str(file_path)) if os.system(cmd_str) == 0: self.__get_scanner_file__(output_path) else: print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues") raise Exception(file_path + ", Decompilation failed.") # 初始化检测文件信息 def __scanner_file_by_apktool__(self, output_path): file_names = os.listdir(output_path) for file_name in file_names: file_path = os.path.join(output_path, file_name) if not os.path.isdir(file_path): continue if "smali" in file_name or "assets" in file_name: scanner_file_suffixs = ["smali", "js", "xml"] if cores.resource_flag: scanner_file_suffixs = ["smali"] self.__get_scanner_file__(file_path, scanner_file_suffixs) def __get_scanner_file__(self, scanner_dir, scanner_file_suffixs=["smali"]): dir_or_files = os.listdir(scanner_dir) for dir_or_file in dir_or_files: dir_file_path = os.path.join(scanner_dir, dir_or_file) if os.path.isdir(dir_file_path): self.__get_scanner_file__(dir_file_path, scanner_file_suffixs) else: if ("." not in dir_or_file) or (len(dir_or_file.split(".")) < 1) or (dir_or_file.split(".")[-1] not in scanner_file_suffixs): continue self.file_queue.put(dir_file_path) for component in config.filter_components: comp = component.replace(".", "/") if(comp in dir_file_path): if(component not in self.comp_list): self.comp_list.append(component) def __shell_test__(self, output): am_path = os.path.join(output, "AndroidManifest.xml") with open(am_path, "r", encoding='utf-8', errors='ignore') as f: am_str = f.read() am_package = re.compile(r'= 1: self.packagename = apackage[0] self.file_identifier.append(apackage[0]) am_name = re.compile(r'') aname = am_name.findall(am_str) if aname and len(aname) >= 1: if aname[0] in config.shell_list: self.shell_flag = True am_permission = re.compile(r'') ampermissions = am_permission.findall(am_str) for ampermission in ampermissions: if ampermission in config.apk_permissions: self.permissions.append(ampermission)