#! /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": 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)