Source code for androlyze.model.script.ScriptUtil


# encoding: utf-8

__author__ = "Nils Tobias Schmidt"
__email__ = "schmidt89 at informatik.uni-marburg.de"

import sys
from datetime import datetime
import importlib
import json
from os.path import basename

from androlyze.loader.exception import NoAndroScriptSubclass, \
    ModuleNotSameClassNameException
from androlyze.log.Log import log
from androlyze.util import Util


[docs]def import_scripts(script_list, via_package = False, _reload = False, clazz_name = None): ''' Import the scripts (via file path or package name - configurable via `via_pacakge`). Parameters ---------- script_list: list<str> list of script names (absolute path) or package names. via_package : bool, optional (default is False) If true, assume package names are given instead of file paths. _reload : bool, optional (default is False) Reload scripts and delete them from internal cache. Only possible if `via_package`. clazz_name : optional (default is None) The name of the class to import. If none, use the name of the module. Returns ------- list<type<AndroScript>> list of uninstantiated AndroScript classes Raises ------ AnalyzeError If an NoAndroScriptSubclass, IOError or ModuleNotSameClassNameException has been raised. ImportError ''' # late import -> pervent recursive import from androlyze.model.script.AndroScript import AndroScript from androlyze.analyze.exception import AnalyzeError androscripts = [] # reload scripts if wanted if via_package and _reload: for script_package in script_list: log.debug("deleting %s from system modules", script_package) try: del sys.modules[script_package] log.debug("deleted") except KeyError: pass for script in script_list: class_name = clazz_name if not class_name: if via_package: class_name = script.split(".")[-1] else: class_name = basename(script.split(".py")[0]) # class name must be equivalent to the module name! try: module_package = script # get package name from path and cut off file extension if not via_package: module_package = Util.path_2_package_name(script) module = importlib.import_module(module_package) clazz = getattr(module, class_name) # check if class is derived from AndroScript if isinstance(clazz, AndroScript.__class__): androscripts.append(clazz) else: raise NoAndroScriptSubclass(clazz), None, sys.exc_info()[2] except AttributeError as e: raise ModuleNotSameClassNameException(script, class_name), None, sys.exc_info()[2] except IOError as e: e.filename = script raise except (NoAndroScriptSubclass, ModuleNotSameClassNameException, IOError) as e: raise AnalyzeError(e), None, sys.exc_info()[2] return androscripts
[docs]def instantiate_scripts(script_list, script_paths = None, script_hashes = None): ''' Instantiate the `AndroScript`s and return them. Parameters ---------- script_list : list<type<AndroScript>> script_paths : list<str>, optional (default is None) If given, set the path of the `AndroScript` (needed for hashing) script_hashes : list<str>, optional (default is []) If given, set the hash of the `AndroScript` directly (without hashing the file from path) Returns ------- list<AndroScript> Raises ------ AndroScriptError If an error happened while initializing some `AndroScript` ''' from androlyze.analyze.exception import AndroScriptError instantiated_scripts = None try: instantiated_scripts = [s() for s in script_list] # set paths if script_paths is not None or script_hashes is not None: for idx, s in enumerate(instantiated_scripts): # calculate hash from path if script_paths is not None: s.path = script_paths[idx] # set hash directly if script_hashes is not None: s.hash = script_hashes[idx] return instantiated_scripts except Exception as e: raise AndroScriptError(s, e), None, sys.exc_info()[2]
[docs]def get_minimum_script_options(androscripts): ''' Get the maximum script options that any of `androscripts` needs. These are the minimum options needed to run the `androscripts`. Parameters ---------- androscripts : list<AndroScript> Returns ------- tuple<bool> ''' needs_xref, needs_dref, dalvik_vm_format, vm_analysis, gvm_analysis = 5 * [False] for ascript in androscripts: if ascript.needs_xref(): needs_xref = True if ascript.needs_dref(): needs_dref = True if ascript.needs_dalvik_vm_format(): dalvik_vm_format = True if ascript.needs_vmanalysis(): vm_analysis = True if ascript.needs_gvmanalysis(): gvm_analysis = True if gvm_analysis: vm_analysis = True if vm_analysis: dalvik_vm_format = True return dalvik_vm_format, vm_analysis, gvm_analysis, needs_xref, needs_dref
[docs]def androscript_options_descr(androscripts): ''' Format the minimum options to run the `androscripts`. Parameters ---------- androscripts : list<AndroScript> Returns ------- tuple<bool> ''' dalvik_vm_format, vm_analysis, gvm_analysis, needs_xref, needs_dref = get_minimum_script_options(androscripts) return '''Minimum script needs: DalvikVMFormat: %s VMAnalysis: %s GVMAnalysis: %s Create xref: %s Create dref: %s ''' % (dalvik_vm_format, vm_analysis, gvm_analysis, needs_xref, needs_dref)
[docs]def chained_script(androscripts, root_categories = (), name = None, log_chained_script_meta_infos = False, continue_on_script_failure = True, log_script_failure_exception = False): ''' Factory method for creating a `ChainedScript`. Can be used to do further grouping. E.g. group the results of multiple scripts under the given `root_categories` Parameters ---------- androscripts : list<AndroScript>, optional (default is []) List of scripts to use (instantiated classes!) root_categories : tuple<str>, optional (default is ()) Categories under which you want to store the results of the scripts. Empty tuple means no category at all name : str, optional (default is class name)) If given set the name of the created class. log_chained_script_meta_infos : bool, optional (default is False) Will be passed to the `ChainedScript` subclass. Meaning no meta information will be created from it (related to the chained scripts) continue_on_script_failure : bool, optional (default is True) log_script_failure_exception : bool, optional (default is False) Returns ------- ChainedScript ''' from androlyze.model.script.ChainedScript import ChainedScript return ChainedScript(androscripts = androscripts, root_categories = root_categories, name = name, log_chained_script_meta_infos = log_chained_script_meta_infos, continue_on_script_failure = continue_on_script_failure, log_script_failure_exception = log_script_failure_exception )
[docs]def is_result_object(obj): from androlyze.model.analysis.result.ResultObject import ResultObject return isinstance(obj, ResultObject)
[docs]def dict2json(d): ''' Convert the dict `d` to json and convert any datetime object to iso8601. Can also convert `bson.objectid.ObjectId ''' from bson.objectid import ObjectId def converter(obj): if isinstance(obj, datetime): return Util.datetime_to_iso8601(obj) elif isinstance(obj, ObjectId): return str(obj) return json.dumps(d, indent = 4, # use converter default = converter)