def add(self, filename, raw_data, dx=None): """ Generic method to add a file to the session. It guesses the filetype and calls the correct method. :param filename: filename to load :param raw_data: bytes of the file :param dx: An already exiting :class:`~androguard.core.analysis.analysis.Analysis` object :return: the sha256 of the file or None on failure """ ret = androconf.is_android_raw(raw_data) if not ret: return None self.analyzed_files[filename] = [] if ret == "APK": digest, apk = self.addAPK(filename, raw_data) dx = self.analyzed_vms.get(digest) for dex in apk.get_all_dex(): _, d, dx = self.addDEX(filename, dex, dx) elif ret == "DEX": digest, d, _ = self.addDEX(filename, raw_data) dx = self.analyzed_dex.get(digest) elif ret == "DEY": digest, d, _ = self.addDEY(filename, raw_data, dx) dx = self.analyzed_dex.get(digest) else: return None return digest
def worker(idx, q): log.debug("Running worker-%d" % idx) while True: a, d, dx, axmlobj, arscobj = None, None, None, None, None try: filename, fileraw = q.get() id_file = zlib.adler32(fileraw) log.debug("(worker-%d) get %s %d" % (idx, filename, id_file)) log = self.settings["log"](id_file, filename) is_analysis_dex, is_analysis_adex = True, True log.debug("(worker-%d) filtering file %d" % (idx, id_file)) filter_file_ret, filter_file_type = myandro.filter_file( log, fileraw) if filter_file_ret: log.debug("(worker-%d) analysis %s" % (id_file, filter_file_type)) if filter_file_type == "APK": a = myandro.create_apk(log, fileraw) is_analysis_dex = myandro.analysis_apk(log, a) fileraw = a.get_dex() filter_file_type = androconf.is_android_raw( fileraw) elif filter_file_type == "AXML": axmlobj = myandro.create_axml(log, fileraw) myandro.analysis_axml(log, axmlobj) elif filter_file_type == "ARSC": arscobj = myandro.create_arsc(log, fileraw) myandro.analysis_arsc(log, arscobj) if is_analysis_dex and filter_file_type == "DEX": d = myandro.create_dex(log, fileraw) is_analysis_adex = myandro.analysis_dex(log, d) elif is_analysis_dex and filter_file_type == "DEY": d = myandro.create_dey(log, fileraw) is_analysis_adex = myandro.analysis_dey(log, d) if is_analysis_adex and d: dx = myandro.create_adex(log, d) myandro.analysis_adex(log, dx) myandro.analysis_app(log, a, d, dx) myandro.finish(log) except Exception as why: myandro.crash(log, why) myandro.finish(log) del a, d, dx, axmlobj, arscobj q.task_done()
def __init__(self, dex): """Create an APK object from a dex object.""" filetype = is_android_raw(dex) if filetype not in ["DEX", "ODEX"]: raise InvalidDVM("Not a valid filetype: {0}".format(filetype)) self.filetype = filetype self._dvm = AndroDVM.DalvikVMFormat(dex)
def _patch_magic(self, buffer, orig): if ("Zip" in orig) or ("DBase" in orig): val = androconf.is_android_raw(buffer) if val == "APK": return "Android application package file" elif val == "AXML": return "Android's binary XML" return orig
def patch_magic(self, buffer, orig) : if ("Zip" in orig) or ("DBase" in orig) : val = androconf.is_android_raw( buffer ) if val == "APK" : return "Android application package file" elif val == "AXML" : return "Android's binary XML" return orig
def worker(idx, q): debug("Running worker-%d" % idx) while True: a, d, dx, axmlobj, arscobj = None, None, None, None, None try: filename, fileraw = q.get() id_file = zlib.adler32(fileraw) debug("(worker-%d) get %s %d" % (idx, filename, id_file)) log = self.settings["log"](id_file, filename) is_analysis_dex, is_analysis_adex = True, True debug("(worker-%d) filtering file %d" % (idx, id_file)) filter_file_ret, filter_file_type = myandro.filter_file( log, fileraw) if filter_file_ret: debug("(worker-%d) analysis %s" % (id_file, filter_file_type)) if filter_file_type == "APK": a = myandro.create_apk(log, fileraw) is_analysis_dex = myandro.analysis_apk(log, a) fileraw = a.get_dex() filter_file_type = androconf.is_android_raw(fileraw) elif filter_file_type == "AXML": axmlobj = myandro.create_axml(log, fileraw) myandro.analysis_axml(log, axmlobj) elif filter_file_type == "ARSC": arscobj = myandro.create_arsc(log, fileraw) myandro.analysis_arsc(log, arscobj) if is_analysis_dex and filter_file_type == "DEX": d = myandro.create_dex(log, fileraw) is_analysis_adex = myandro.analysis_dex(log, d) elif is_analysis_dex and filter_file_type == "DEY": d = myandro.create_dey(log, fileraw) is_analysis_adex = myandro.analysis_dey(log, d) if is_analysis_adex and d: dx = myandro.create_adex(log, d) myandro.analysis_adex(log, dx) myandro.analysis_app(log, a, d, dx) myandro.finish(log) except Exception, why: myandro.crash(log, why) myandro.finish(log) del a, d, dx, axmlobj, arscobj q.task_done()
def filter_file(self, log, fileraw): """ This method is called in order to filer a specific app :param log: an object which corresponds to a unique app :param bytes fileraw: the raw file as bytes :rtype: a tuple with 2 elements, the return value (boolean) if it is necessary to continue the analysis and the file type """ file_type = androconf.is_android_raw(fileraw) if file_type in ["APK", "DEX", "DEY", "AXML", "ARSC"]: return True, file_type return False, None
def filter_file(self, log, fileraw): """ This method is called in order to filer a specific app :param log: an object which corresponds to a unique app :param fileraw: the raw app (a string) :rtype: a set with 2 elements, the return value (boolean) if it is necessary to continue the analysis and the file type """ file_type = androconf.is_android_raw(fileraw) if file_type == "APK" or file_type == "DEX" or file_type == "DEY" or file_type == "AXML" or file_type == "ARSC": return True, file_type return False, None
def _patch_magic(self, buffer, orig): """ Overwrite some probably wrong detections by mime libraries :param buffer: bytes of the file to detect :param orig: guess by mime libary :return: corrected guess """ if ("Zip" in orig) or ("DBase" in orig): val = androconf.is_android_raw(buffer) if val == "APK": return "Android application package file" elif val == "AXML": return "Android's binary XML" return orig
def add(self, filename, raw_data, dx=None): ret = androconf.is_android_raw(raw_data) digest = None if not ret: return None self.analyzed_files[filename] = [] if ret == "APK": digest, apk = self.addAPK(filename, raw_data) dex_files = list(apk.get_all_dex()) dx = self.analyzed_vms.get(digest) for dex in dex_files: _, d, dx = self.addDEX(filename, dex, dx) elif ret == "DEX": digest, d, _ = self.addDEX(filename, raw_data) dx = self.analyzed_dex.get(digest) elif ret == "DEY": digest, d, _ = self.addDEY(filename, raw_data, dx) dx = self.analyzed_dex.get(digest) else: return None return digest
def add(self, filename, raw_data=None, dx=None): """ Generic method to add a file to the session. This is the main method to use when adding files to a Session! If an APK file is supplied, all DEX files are analyzed too. For DEX and ODEX files, only this file is analyzed (what else should be analyzed). Returns the SHA256 of the analyzed file. :param filename: filename to load :param raw_data: bytes of the file, or None to load the file from filename :param dx: An already exiting :class:`~androguard.core.analysis.analysis.Analysis` object :return: the sha256 of the file or None on failure """ if not raw_data: log.debug("Loading file from '{}'".format(filename)) with open(filename, "rb") as fp: raw_data = fp.read() ret = androconf.is_android_raw(raw_data) log.debug("Found filetype: '{}'".format(ret)) if not ret: return None if ret == "APK": digest, _ = self.addAPK(filename, raw_data) elif ret == "DEX": digest, _, _ = self.addDEX(filename, raw_data, dx) elif ret == "DEY": digest, _, _ = self.addDEY(filename, raw_data, dx) else: return None return digest
def add(self, filename, raw_data, dx=None): ret = androconf.is_android_raw(raw_data) if ret: self.analyzed_files[filename] = [] digest = hashlib.sha256(raw_data).hexdigest() if ret == "APK": apk_digest, apk = self.addAPK(filename, raw_data) dex_files = list(apk.get_all_dex()) if dex_files: dex_digest, _, dx = self.addDEX(filename, dex_files[0], dx) self.analyzed_apk[digest].append(dex_digest) for i in range(1, len(dex_files)): dex_digest, _, _ = self.addDEX(filename, dex_files[i], dx) self.analyzed_apk[digest].append(dex_digest) elif ret == "DEX": self.addDEX(filename, raw_data, dx) elif ret == "DEY": self.addDEY(filename, raw_data, dx) else: return False return True return False
def run(self): if androconf.is_android_raw(self.raw) == "DEY": dex_object = dvm.DalvikOdexVMFormat(self.raw) else: dex_object = dvm.DalvikVMFormat(self.raw) ana_object = analysis.uVMAnalysis(dex_object) gvm_object = ganalysis.GVMAnalysis(ana_object, None) dex_object.set_vmanalysis(ana_object) dex_object.set_gvmanalysis(gvm_object) for i in androconf.CONF: if is_setting(i): androconf.CONF[i] = get_setting(i) decompiler_option = get_setting("DEFAULT_DECOMPILER", "dad") if decompiler_option == "dex2jad": dex_object.set_decompiler(decompiler.DecompilerDex2Jad( dex_object, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_option == "ded": dex_object.set_decompiler(decompiler.DecompilerDed( dex_object, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) else: dex_object.set_decompiler(decompiler.DecompilerDAD(dex_object, ana_object)) dex_object.create_xref() dex_object.create_dref() self.view.set_name("%s.ag" % (self.filename)) self.view.set_scratch(True) edit = self.view.begin_edit() self.view.sel().clear() self.view.set_syntax_file("Packages/ag-st/ag.tmLanguage") by_package = {} for current_class in dex_object.get_classes(): name = current_class.get_name() try: by_package[os.path.dirname(name)].append(current_class) except KeyError: by_package[os.path.dirname(name)] = [] by_package[os.path.dirname(name)].append(current_class) b_buffer = "" line = 0 AG_METHODS_LINE[self.view.id()] = {} AG_CLASSES_LINE[self.view.id()] = {} AG_FIELDS_LINE[self.view.id()] = {} for key in sorted(by_package.iterkeys()): b_buffer += "%s\n" % key line += 1 for c_class in sorted(by_package[key], key=lambda k: k.get_name()): b_buffer += "\t%s extends %s\n" % (c_class.get_name()[1:-1], c_class.get_superclassname()[1:-1]) AG_CLASSES_LINE[self.view.id()][line] = c_class line += 1 for j in c_class.get_methods(): b_buffer += "\t\tmethod: %s %s [%s] size:%d\n" % (j.get_name(), j.get_descriptor(), j.get_access_flags_string(), j.get_length()) AG_METHODS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 for j in c_class.get_fields(): b_buffer += "\t\tfield: %s %s [%s %s]" % (j.get_name(), j.get_descriptor(), j.get_access_flags_string(), dvm.get_type(j.get_descriptor())) init_value = j.get_init_value() if init_value != None: b_buffer += " (%s)" % repr(str(init_value.get_value())) b_buffer += "\n" AG_FIELDS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 l = dex_object.print_classes_hierarchy() h_buffer = "" for i in l: h_buffer += i + "\n" b_buffer += h_buffer self.view.replace(edit, sublime.Region(0, self.view.size()), b_buffer) self.view.end_edit(edit) self.view.set_read_only(True) AG_DEX_VIEW[self.view.id()] = (dex_object, ana_object) FILENAMES[self.view.id()] = hashlib.sha1(dex_object.get_buff()).hexdigest()
def worker(idx, q): """ Worker Thread """ l.debug("Running worker-%d" % idx) while True: a, d, dx, axmlobj, arscobj = None, None, None, None, None try: filename, fileraw = q.get() id_file = zlib.adler32(fileraw) l.debug("(worker-%d) get %s %d" % (idx, filename, id_file)) # FIXME: If the try/catch crashes before this line, there # will be no logf to put into finish. logf = self.settings["log"](id_file, filename) is_analysis_dex, is_analysis_adex = True, True l.debug("(worker-%d) filtering file %d" % (idx, id_file)) # TODO: This information should probably also go into the logf? filter_file_ret, filter_file_type = myandro.filter_file( logf, fileraw) if filter_file_ret: l.debug("(worker-%d) analysis %s" % (id_file, filter_file_type)) if filter_file_type == "APK": a = myandro.create_apk(logf, fileraw) is_analysis_dex = myandro.analysis_apk(logf, a) # TODO: Support multidex here fileraw = a.get_dex() filter_file_type = androconf.is_android_raw( fileraw) elif filter_file_type == "AXML": axmlobj = myandro.create_axml(logf, fileraw) # TODO: the return value of analysis_axml is not checked myandro.analysis_axml(logf, axmlobj) elif filter_file_type == "ARSC": arscobj = myandro.create_arsc(logf, fileraw) # TODO: the return value of analysis_arsc is not checked myandro.analysis_arsc(logf, arscobj) if is_analysis_dex and filter_file_type == "DEX": d = myandro.create_dex(logf, fileraw) is_analysis_adex = myandro.analysis_dex(logf, d) elif is_analysis_dex and filter_file_type == "DEY": d = myandro.create_dey(logf, fileraw) is_analysis_adex = myandro.analysis_dey(logf, d) if is_analysis_adex and d: # TODO: Support multidex here dx = myandro.create_adex(logf, d) # TODO: The return value of analysis_adex is not checked myandro.analysis_adex(logf, dx) # TODO: this is called also if AXML or ARSC is set... myandro.analysis_app(logf, a, d, dx) myandro.finish(logf) except Exception as why: myandro.crash(logf, why) # FIXME: finish is called here in any case of an exception # but is only called if filter_file_ret is true above. myandro.finish(logf) del a, d, dx, axmlobj, arscobj q.task_done()
def run(self): if androconf.is_android_raw(self.raw) == "DEY": dex_object = dvm.DalvikOdexVMFormat(self.raw) else: dex_object = dvm.DalvikVMFormat(self.raw) ana_object = analysis.uVMAnalysis(dex_object) gvm_object = ganalysis.GVMAnalysis(ana_object, None) dex_object.set_vmanalysis(ana_object) dex_object.set_gvmanalysis(gvm_object) for i in androconf.CONF: if is_setting(i): androconf.CONF[i] = get_setting(i) decompiler_option = get_setting("DEFAULT_DECOMPILER", "dad") if decompiler_option == "dex2jad": dex_object.set_decompiler( decompiler.DecompilerDex2Jad(dex_object, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_option == "ded": dex_object.set_decompiler( decompiler.DecompilerDed(dex_object, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) else: dex_object.set_decompiler( decompiler.DecompilerDAD(dex_object, ana_object)) dex_object.create_xref() dex_object.create_dref() self.view.set_name("%s.ag" % (self.filename)) self.view.set_scratch(True) edit = self.view.begin_edit() self.view.sel().clear() self.view.set_syntax_file("Packages/ag-st/ag.tmLanguage") by_package = {} for current_class in dex_object.get_classes(): name = current_class.get_name() try: by_package[os.path.dirname(name)].append(current_class) except KeyError: by_package[os.path.dirname(name)] = [] by_package[os.path.dirname(name)].append(current_class) b_buffer = "" line = 0 AG_METHODS_LINE[self.view.id()] = {} AG_CLASSES_LINE[self.view.id()] = {} AG_FIELDS_LINE[self.view.id()] = {} for key in sorted(by_package.iterkeys()): b_buffer += "%s\n" % key line += 1 for c_class in sorted(by_package[key], key=lambda k: k.get_name()): b_buffer += "\t%s extends %s\n" % (c_class.get_name( )[1:-1], c_class.get_superclassname()[1:-1]) AG_CLASSES_LINE[self.view.id()][line] = c_class line += 1 for j in c_class.get_methods(): b_buffer += "\t\tmethod: %s %s [%s] size:%d\n" % ( j.get_name(), j.get_descriptor(), j.get_access_flags_string(), j.get_length()) AG_METHODS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 for j in c_class.get_fields(): b_buffer += "\t\tfield: %s %s [%s %s]" % ( j.get_name(), j.get_descriptor(), j.get_access_flags_string(), dvm.get_type(j.get_descriptor())) init_value = j.get_init_value() if init_value != None: b_buffer += " (%s)" % repr(str(init_value.get_value())) b_buffer += "\n" AG_FIELDS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 l = dex_object.get_classes_hierarchy() h_buffer = "" for i in l: h_buffer += i + "\n" b_buffer += h_buffer self.view.replace(edit, sublime.Region(0, self.view.size()), b_buffer) self.view.end_edit(edit) self.view.set_read_only(True) AG_DEX_VIEW[self.view.id()] = (dex_object, ana_object) FILENAMES[self.view.id()] = hashlib.sha1( dex_object.get_buff()).hexdigest()
def worker(idx, q): """ Worker Thread """ l.debug("Running worker-%d" % idx) while True: a, d, dx, axmlobj, arscobj = None, None, None, None, None try: filename, fileraw = q.get() id_file = zlib.adler32(fileraw) l.debug("(worker-%d) get %s %d" % (idx, filename, id_file)) # FIXME: If the try/catch crashes before this line, there # will be no logf to put into finish. logf = self.settings["log"](id_file, filename) is_analysis_dex, is_analysis_adex = True, True l.debug("(worker-%d) filtering file %d" % (idx, id_file)) # TODO: This information should probably also go into the logf? filter_file_ret, filter_file_type = myandro.filter_file(logf, fileraw) if filter_file_ret: l.debug("(worker-%d) analysis %s" % (id_file, filter_file_type)) if filter_file_type == "APK": a = myandro.create_apk(logf, fileraw) is_analysis_dex = myandro.analysis_apk(logf, a) # TODO: Support multidex here fileraw = a.get_dex() filter_file_type = androconf.is_android_raw(fileraw) elif filter_file_type == "AXML": axmlobj = myandro.create_axml(logf, fileraw) # TODO: the return value of analysis_axml is not checked myandro.analysis_axml(logf, axmlobj) elif filter_file_type == "ARSC": arscobj = myandro.create_arsc(logf, fileraw) # TODO: the return value of analysis_arsc is not checked myandro.analysis_arsc(logf, arscobj) if is_analysis_dex and filter_file_type == "DEX": d = myandro.create_dex(logf, fileraw) is_analysis_adex = myandro.analysis_dex(logf, d) elif is_analysis_dex and filter_file_type == "DEY": d = myandro.create_dey(logf, fileraw) is_analysis_adex = myandro.analysis_dey(logf, d) if is_analysis_adex and d: # TODO: Support multidex here dx = myandro.create_adex(logf, d) # TODO: The return value of analysis_adex is not checked myandro.analysis_adex(logf, dx) # TODO: this is called also if AXML or ARSC is set... myandro.analysis_app(logf, a, d, dx) myandro.finish(logf) except Exception as why: myandro.crash(logf, why) # FIXME: finish is called here in any case of an exception # but is only called if filter_file_ret is true above. myandro.finish(logf) del a, d, dx, axmlobj, arscobj q.task_done()