def reload_java_sources(self): """Reload completely the sources by asking Androguard to decompile it again. Useful when: - an element has been renamed to propagate the info - the current tab is changed because we do not know what user did since then, so we need to propagate previous changes as well """ androconf.debug("Getting sources for %s" % self.current_class) lines = [] lines.append( ( "COMMENTS", [("COMMENT", "/*\n * filename:%s\n * digest:%s\n */\n" % (self.current_filename, self.current_digest))], ) ) lines.extend(self.current_class.get_source_ext()) # TODO: delete doc when tab is closed? not deleted by "self" :( if hasattr(self, "doc"): del self.doc self.doc = SourceDocument(parent=self, lines=lines) self.setDocument(self.doc) # No need to save hightlighter. highlighBlock will automatically be called # because we passed the QTextDocument to QSyntaxHighlighter constructor if PYGMENTS: PygmentsHighlighter(self.doc, lexer=JavaLexer()) else: androconf.debug("Pygments is not present !")
def __init__(self, parent=None, win=None, current_class=None, current_title=None, current_filename=None, current_digest=None, session=None): super(SourceWindow, self).__init__(parent) androconf.debug("New source tab for: %s" % current_class) self.mainwin = win self.session = session self.current_class = current_class self.current_title = current_title self.current_filename = current_filename self.current_digest = current_digest self.title = current_title self.setReadOnly(True) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.CustomContextMenuHandler) self.cursorPositionChanged.connect(self.cursor_position_changed)
def reload_java_sources(self): '''Reload completely the sources by asking Androguard to decompile it again. Useful when: - an element has been renamed to propagate the info - the current tab is changed because we do not know what user did since then, so we need to propagate previous changes as well ''' androconf.debug("Getting sources for %s" % self.current_class) lines = [] lines.append(("COMMENTS", [("COMMENT", "/*\n * filename:%s\n * digest:%s\n */\n" % (self.current_filename, self.current_digest))])) lines.extend(self.current_class.get_source_ext()) #TODO: delete doc when tab is closed? not deleted by "self" :( if hasattr(self, "doc"): del self.doc self.doc = SourceDocument(parent=self, lines=lines) self.setDocument(self.doc) #No need to save hightlighter. highlighBlock will automatically be called #because we passed the QTextDocument to QSyntaxHighlighter constructor if PYGMENTS: PygmentsHighlighter(self.doc, lexer=JavaLexer()) else: androconf.debug("Pygments is not present !")
def __init__( self, parent=None, win=None, current_class=None, current_title=None, current_filename=None, current_digest=None, session=None, ): super(SourceWindow, self).__init__(parent) androconf.debug("New source tab for: %s" % current_class) self.mainwin = win self.session = session self.current_class = current_class self.current_title = current_title self.current_filename = current_filename self.current_digest = current_digest self.title = current_title self.setReadOnly(True) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.CustomContextMenuHandler) self.cursorPositionChanged.connect(self.cursor_position_changed)
def actionGoto(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Goto asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus("Goto not available. No info for: '%s'." % selection) return t = self.doc.binding[start] if t[0] == "NAME_METHOD_INVOKE": class_, method_ = t[2].split(" -> ") if class_ == "this": class_ = self.path else: class_ = classdot2class(class_) else: self.mainwin.showStatus("Goto not available. Info ok: '%s' but object not supported." % selection) return androconf.debug("Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.path)) if not self.mainwin.doesClassExist(class_): self.mainwin.showStatus("Goto not available. Class: %s not in database." % class_) return self.mainwin.openSourceWindow(class_, method=method_)
def addAPK(self, filename, data): digest = hashlib.sha256(data).hexdigest() androconf.debug("add APK:%s" % digest) apk = APK(data, True) self.analyzed_apk[digest] = apk self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename androconf.debug("added APK:%s" % digest) return (digest, apk)
def addAPK(self, filename, data): digest = hashlib.sha256(data).hexdigest() androconf.debug("add APK:%s" % digest) apk = APK(data, True) self.analyzed_apk[digest] = [apk] self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename androconf.debug("added APK:%s" % digest) return (digest, apk)
def actionInfo(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() androconf.debug("actionInfo asked for (%d, %d)" % (start, end)) if start in self.doc.binding.keys(): self.mainwin.showStatus("%s at position: (%d, %d)" % (str(self.doc.binding[start]), start, end)) else: self.mainwin.showStatus("No info available.")
def itemDoubleClickedHandler(self, item, column): '''Signal sent by PySide when a tree element is clicked''' androconf.debug("item %s has been double clicked at column %s" % (str(item), str(column))) if item.childCount() != 0: self.mainwin.showStatus("Sources not available. %s is not a class" % path) return current_class, current_filename, current_digest = self._reverse_cache[item] self.mainwin.openSourceWindow(current_class)
def actionInfo(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() androconf.debug("actionInfo asked for (%d, %d)" % (start, end)) if start in self.doc.binding.keys(): self.mainwin.showStatus('%s at position: (%d, %d)' % (str(self.doc.binding[start]), start, end)) else: self.mainwin.showStatus("No info available.")
def get_xrefs_list(cls, class_item, method=None): '''Static method called before creating a XrefDialog to check if there are xrefs to display method (optional): method of the class we are looking xref from ''' androconf.debug("Getting XREF for %s" % class_item) item = class_item if method: item = method return XrefDialog.get_xrefs_list_from_element(item)
def runAnalysis(self, d, dx=None): androconf.debug("VMAnalysis ...") if dx is None: dx = newVMAnalysis(d) else: dx.add(d) dx.create_xref() d.set_decompiler(DecompilerDAD(d, dx)) return dx
def actionRename(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Rename asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus( "Rename not available. No info for: '%s'." % selection) return # Double check if we support the renaming for the type of # object before poping a new window to the user t = self.doc.binding[start] if t[0] == 'NAME_METHOD_PROTOTYPE': class_ = self.current_class method_ = t[1] if method_ == self.title: method_ = 'init' androconf.debug( "Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.current_filename)) elif t[0] == 'NAME_METHOD_INVOKE': class_, method_ = t[2].split(' -> ') if class_ == 'this': class_ = self.current_class androconf.debug( "Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.current_filename)) elif t[0] == 'NAME_PROTOTYPE': class_ = t[2] + '.' + t[1] androconf.debug( "Found corresponding class: %s in source file: %s" % (class_, self.current_filename)) elif t[0] == 'NAME_FIELD': field_ = t[1] androconf.debug( "Found corresponding field: %s in source file: %s" % (field_, self.current_filename)) else: self.mainwin.showStatus( "Rename not available. Info ok: '%s' but object not supported." % selection) return rwin = RenameDialog(parent=self, win=self.mainwin, element=selection, info=(start, end)) rwin.show()
def browse_to_method(self, method): """Scroll to the right place were the method is. TODO: implement it, because does not work for now. """ # TODO: we need to find a way to scroll to the right place because # moving the cursor is not enough. Indeed if it is already in the window # it does not do nothing # TODO: idea, highlight the method in the screen so we do not have to search for it androconf.debug("Browsing to %s -> %s" % (self.current_class, method))
def itemDoubleClickedHandler(self, item, column): '''Signal sent by PySide when a tree element is clicked''' androconf.debug("item %s has been double clicked at column %s" % (str(item), str(column))) if item.childCount() != 0: self.mainwin.showStatus( "Sources not available. %s is not a class" % path) return current_class, current_filename, current_digest = self._reverse_cache[ item] self.mainwin.openSourceWindow(current_class)
def browse_to_method(self, method): '''Scroll to the right place were the method is. TODO: implement it, because does not work for now. ''' #TODO: we need to find a way to scroll to the right place because # moving the cursor is not enough. Indeed if it is already in the window # it does not do nothing #TODO: idea, highlight the method in the screen so we do not have to search for it androconf.debug("Browsing to %s -> %s" % (self.current_class, method))
def addDEY(self, filename, data, dx=None): digest = hashlib.sha256(data).hexdigest() androconf.debug("add DEY:%s" % digest) d = DalvikOdexVMFormat(data) dx = self.runAnalysis(d, dx) androconf.debug("added DEY:%s" % digest) self.analyzed_dex[digest] = (d, dx) self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename return (digest, d, dx)
def cursor_position_changed(self): """Used to detect when cursor change position and to auto select word underneath it""" androconf.debug("cursor_position_changed") cur = self.textCursor() androconf.debug(cur.position()) androconf.debug(cur.selectedText()) if len(cur.selectedText()) == 0: cur.select(QtGui.QTextCursor.SelectionType.WordUnderCursor) self.setTextCursor(cur) androconf.debug("cursor: %s" % cur.selectedText()) else: androconf.debug("cursor: no selection %s" % cur.selectedText())
def cursor_position_changed(self): '''Used to detect when cursor change position and to auto select word underneath it''' androconf.debug("cursor_position_changed") cur = self.textCursor() androconf.debug(cur.position()) androconf.debug(cur.selectedText()) if len(cur.selectedText()) == 0: cur.select(QtGui.QTextCursor.SelectionType.WordUnderCursor) self.setTextCursor(cur) androconf.debug("cursor: %s" % cur.selectedText()) else: androconf.debug("cursor: no selection %s" % cur.selectedText())
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 AnalyzeAPK(filename, raw=False, decompiler="dad"): """ Analyze an android application and setup all stuff for a more quickly analysis ! :param filename: the filename of the android application or a buffer which represents the application :type filename: string :param raw: True is you would like to use a buffer (optional) :type raw: boolean :param decompiler: ded, dex2jad, dad (optional) :type decompiler: string :rtype: return the :class:`APK`, :class:`DalvikVMFormat`, and :class:`VMAnalysis` objects """ androconf.debug("APK ...") a = APK(filename, raw) d, dx = AnalyzeDex(a.get_dex(), raw=True, decompiler=decompiler) return a, d, dx
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 run(self): if self.incoming_file: try: file_path, file_type = self.incoming_file if file_type in ["APK", "DEX", "DEY"]: ret = self.session.add(file_path, open(file_path, 'r').read()) self.emit(QtCore.SIGNAL("loadedFile(bool)"), ret) elif file_type == "SESSION": self.session.load(file_path) self.emit(QtCore.SIGNAL("loadedFile(bool)"), True) except Exception as e: androconf.debug(e) androconf.debug(traceback.format_exc()) self.emit(QtCore.SIGNAL("loadedFile(bool)"), False) self.incoming_file = [] else: self.emit(QtCore.SIGNAL("loadedFile(bool)"), False)
def run(self): if self.incoming_file: try: file_path, file_type = self.incoming_file if file_type in ["APK", "DEX", "DEY"]: ret = self.session.add(file_path, open(file_path, 'r').read()) self.emit(QtCore.SIGNAL("loadedFile(bool)"), ret) elif file_type == "SESSION" : self.session.load(file_path) self.emit(QtCore.SIGNAL("loadedFile(bool)"), True) except Exception as e: androconf.debug(e) androconf.debug(traceback.format_exc()) self.emit(QtCore.SIGNAL("loadedFile(bool)"), False) self.incoming_file = [] else: self.emit(QtCore.SIGNAL("loadedFile(bool)"), False)
def fill(self): '''Parse all the paths (['Lcom/example/myclass/MyActivity$1;', ...]) and build a tree using the QTreeWidgetItem insertion method.''' androconf.debug("Fill classes tree") for idx, filename, digest, classes in self.session.get_classes(): for c in sorted(classes, key=lambda c: c.name): sig = Signature(c) path_node = self.root_path_node path = None if sig.class_path == []: path = '.' if path not in path_node[0]: path_node[0][path] = ({}, QtGui.QTreeWidgetItem( path_node[1])) path_node[0][path][1].setText(0, path) path_node = path_node[0][path] else: # Namespaces for path in sig.class_path: if path not in path_node[0]: path_node[0][path] = ({}, QtGui.QTreeWidgetItem( path_node[1])) path_node[0][path][1].setText(0, path) path_node = path_node[0][path] # Class path_node[0][path] = ({}, QtGui.QTreeWidgetItem(path_node[1])) class_name = sig.class_name if idx > 0: class_name += "@%d" % idx c.current_title = class_name self._reverse_cache[path_node[0][path][1]] = (c, filename, digest) path_node[0][path][1].setText(0, class_name)
def get_xrefs_list_from_element(cls, element): '''Helper for get_xrefs_list element is a ClassDefItem or MethodDefItem At the end of the function, we lost if we worked on a class or method but we do not care for now. ''' xref_items = element.XREFfrom.items androconf.debug("%d XREFs found" % len(xref_items)) # print xref_items xrefs = [] for xref_item in xref_items: class_ = xref_item[0].get_class_name() method_ = xref_item[0].get_name() descriptor_ = xref_item[0].get_descriptor() xrefs.append(classmethod2display(class_, method_, descriptor_)) # print xrefs return xrefs
def actionRename(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Rename asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus("Rename not available. No info for: '%s'." % selection) return # Double check if we support the renaming for the type of # object before poping a new window to the user t = self.doc.binding[start] if t[0] == "NAME_METHOD_PROTOTYPE": class_ = self.current_class method_ = t[1] if method_ == self.title: method_ = "init" androconf.debug( "Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.current_filename) ) elif t[0] == "NAME_METHOD_INVOKE": class_, method_ = t[2].split(" -> ") if class_ == "this": class_ = self.current_class androconf.debug( "Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.current_filename) ) elif t[0] == "NAME_PROTOTYPE": class_ = t[2] + "." + t[1] androconf.debug("Found corresponding class: %s in source file: %s" % (class_, self.current_filename)) elif t[0] == "NAME_FIELD": field_ = t[1] androconf.debug("Found corresponding field: %s in source file: %s" % (field_, self.current_filename)) else: self.mainwin.showStatus("Rename not available. Info ok: '%s' but object not supported." % selection) return rwin = RenameDialog(parent=self, win=self.mainwin, element=selection, info=(start, end)) rwin.show()
def fill(self): '''Parse all the paths (['Lcom/example/myclass/MyActivity$1;', ...]) and build a tree using the QTreeWidgetItem insertion method.''' androconf.debug("Fill classes tree") for idx, filename, digest, classes in self.session.get_classes(): for c in sorted(classes, key=lambda c: c.name): sig = Signature(c) path_node = self.root_path_node path = None if sig.class_path == []: path = '.' if path not in path_node[0]: path_node[0][path] = ({}, QtGui.QTreeWidgetItem(path_node[1])) path_node[0][path][1].setText(0, path) path_node = path_node[0][path] else: # Namespaces for path in sig.class_path: if path not in path_node[0]: path_node[0][path] = ({}, QtGui.QTreeWidgetItem(path_node[1])) path_node[0][path][1].setText(0, path) path_node = path_node[0][path] # Class path_node[0][path] = ({}, QtGui.QTreeWidgetItem(path_node[1])) class_name = sig.class_name if idx > 0: class_name += "@%d" % idx c.current_title = class_name self._reverse_cache[path_node[0][path][1]] = (c, filename, digest) path_node[0][path][1].setText(0, class_name)
def RunDecompiler(d, dx, decompiler): """ Run the decompiler on a specific analysis :param d: the DalvikVMFormat object :type d: :class:`DalvikVMFormat` object :param dx: the analysis of the format :type dx: :class:`VMAnalysis` object :param decompiler: the type of decompiler to use ("dad", "dex2jad", "ded") :type decompiler: string """ if decompiler != None: androconf.debug("Decompiler ...") decompiler = decompiler.lower() if decompiler == "dex2jad": d.set_decompiler(DecompilerDex2Jad(d, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler == "dex2fernflower": d.set_decompiler(DecompilerDex2Fernflower(d, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF["BIN_FERNFLOWER"], androconf.CONF["OPTIONS_FERNFLOWER"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler == "ded": d.set_decompiler(DecompilerDed(d, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) else: d.set_decompiler(DecompilerDAD(d, dx))
def actionGoto(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Goto asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus("Goto not available. No info for: '%s'." % selection) return t = self.doc.binding[start] if t[0] == 'NAME_METHOD_INVOKE': class_, method_ = t[2].split(' -> ') if class_ == 'this': class_ = self.path else: class_ = classdot2class(class_) else: self.mainwin.showStatus( "Goto not available. Info ok: '%s' but object not supported." % selection) return androconf.debug( "Found corresponding method: %s -> %s in source file: %s" % (class_, method_, self.path)) if not self.mainwin.doesClassExist(class_): self.mainwin.showStatus( "Goto not available. Class: %s not in database." % class_) return self.mainwin.openSourceWindow(class_, method=method_)
def addDEX(self, filename, data): digest = hashlib.sha256(data).hexdigest() androconf.debug("add DEX:%s" % digest) d = DalvikVMFormat(data) androconf.debug("VMAnalysis ...") dx = newVMAnalysis(d) dx.create_xref() d.set_decompiler(DecompilerDAD(d, dx)) androconf.debug("added DEX:%s" % digest) self.analyzed_dex[digest] = (d, dx) self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename return (digest, d, dx)
def display_bytecodes(self): androconf.debug("Display bytecodes for %s" % self.current_class) self.mainwin.openBytecodeWindow(self.current_class)
def renameElement(self, oldname, newname, info): """Called back after a user chose a new name for an element. """ androconf.debug("Renaming %s into %s in %s" % (oldname, newname, self.current_filename)) start, end = info try: t = self.doc.binding[start] except: self.mainwin.showStatus("Unexpected error in renameElement") return # Determine type of the to-be-renamed element and Androguard internal objects type_ = None if t[0] == "NAME_METHOD_PROTOTYPE": # method definition in a class method_ = t[1] if method_ == self.title: method_ = "init" proto_ = t[2].method.proto androconf.debug("Found: class=%s, method=%s, proto=%s" % (self.current_class, method_, proto_)) type_ = "METHOD" elif t[0] == "NAME_METHOD_INVOKE": # method call in a method class_, method_ = t[2].split(" -> ") class_ = classdot2class(class_) if class_ == "this": class_ = self.path proto_ = proto2methodprotofunc("".join(t[3]) + t[4]) androconf.debug("Found: class=%s, method=%s, proto=%s" % (class_, method_, proto_)) type_ = "METHOD" elif t[0] == "NAME_PROTOTYPE": # class definition on top of a class class_ = t[2] + "." + t[1] package_ = t[2] androconf.debug("Found: package=%s, class=%s" % (package_, class_)) type_ = "CLASS" elif t[0] == "NAME_FIELD": field_item = t[3] type_ = "FIELD" else: self.mainwin.showStatus("Rename not available. Info found: '%s' but object not supported." % selection) return # Do the actual renaming if type_ == "METHOD": if self.method_name_exist(newname): self.mainwin.showStatus("Method name already exist") return method_class_name = self.current_class.get_name() method_name = method_ method_proto = proto_ current_analysis = self.session.get_analysis(self.current_class) method_item = current_analysis.get_method_by_name(method_class_name, method_name, method_proto) if not method_item: self.mainwin.showStatus("Impossible to find the method") return method_item.set_name(str(newname)) # unicode to ascii elif type_ == "CLASS": newname_class = classdot2class(package_ + "." + newname) self.mainwin.showStatus("New name: %s" % newname_class) class_item = self.current_class # getattr(self.mainwin.d, classdot2func(class_)) class_item.set_name(str(newname_class)) # unicode to ascii self.mainwin.updateDockWithTree() elif type_ == "FIELD": if self.field_name_exist(newname): self.mainwin.showStatus("Field name already exist") return field_item.set_name(str(newname)) else: self.mainwin.showStatus("Unsupported type: %s" % str(type_)) return self.reload_java_sources()
def AnalyzeDex(filename, raw=False, decompiler="dad"): """ Analyze an android dex file and setup all stuff for a more quickly analysis ! :param filename: the filename of the android dex file or a buffer which represents the dex file :type filename: string :param raw: True is you would like to use a buffer (optional) :type raw: boolean :rtype: return the :class:`DalvikVMFormat`, and :class:`VMAnalysis` objects """ androconf.debug("DalvikVMFormat ...") d = None if raw == False: d = DalvikVMFormat(read(filename)) else: d = DalvikVMFormat(filename) androconf.debug("Export VM to python namespace") d.create_python_export() androconf.debug("VMAnalysis ...") dx = uVMAnalysis(d) androconf.debug("GVMAnalysis ...") gx = GVMAnalysis(dx, None) d.set_vmanalysis(dx) d.set_gvmanalysis(gx) RunDecompiler(d, dx, decompiler) androconf.debug("XREF ...") d.create_xref() androconf.debug("DREF ...") d.create_dref() return d, dx
def actionXref(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Xref asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus("Xref not available. No info for: '%s'." % selection) return class_ = None method_ = None t = self.doc.binding[start] print t if t[0] == "NAME_METHOD_PROTOTYPE": method_ = t[1] if method_ == self.title: method_ = "init" proto_ = t[2].method.proto method_class_name = self.current_class.get_name() method_name = method_ method_proto = proto_ current_analysis = self.session.get_analysis(self.current_class) androconf.debug( "Found corresponding method: %s %s %s in source file: %s" % (method_class_name, method_name, method_proto, self.current_filename) ) class_analysis = current_analysis.get_class_analysis(self.current_class.get_name()) if not class_analysis: self.mainwin.showStatus("No xref returned (no class_analysis object).") return method_analysis = class_analysis.get_method_analysis( current_analysis.get_method_by_name(method_class_name, method_name, method_proto) ) print method_analysis if not method_analysis: self.mainwin.showStatus("No xref returned (no method_analysis object).") return xwin = XrefDialogMethod( parent=self.mainwin, win=self.mainwin, current_class=self.current_class, class_analysis=class_analysis, method_analysis=method_analysis, ) xwin.show() elif t[0] == "NAME_FIELD": field_ = t[3] current_analysis = self.session.get_analysis(self.current_class) class_analysis = current_analysis.get_class_analysis(self.current_class.get_name()) if not class_analysis: self.mainwin.showStatus("No xref returned (no class_analysis object).") return field_analysis = class_analysis.get_field_analysis(field_) print field_analysis if not field_analysis: self.mainwin.showStatus("No xref returned (no field_analysis object).") return xwin = XrefDialogField( parent=self.mainwin, win=self.mainwin, current_class=self.current_class, class_analysis=class_analysis, field_analysis=field_analysis, ) xwin.show() else: self.mainwin.showStatus("No xref returned.") return
def analyze_axml(self, a, flags): perms = { "SEND_SMS" : [ "MONEY", "SMS" ], "SEND_SMS_NO_CONFIRMATION" : [ "MONEY", "SMS"], "READ_SMS" : [ "SMS", "PRIVACY" ], "WRITE_SMS" : [ "MONEY", "SMS" ], "RECEIVE_SMS" : [ "SMS", "PRIVACY" ], "RECEIVE_MMS" : [ "SMS", "PRIVACY" ], "PHONE_CALL" : [ "MONEY", "CALL" ], "PROCESS_OUTGOING_CALLS" : [ "MONEY", "CALL" ], "CALL_PRIVILEGED" : [ "MONEY", "CALL" ], "INTERNET" : [ "INTERNET" ], "READ_PHONE_STATE" : [ "PRIVACY" ], "READ_CONTACTS" : [ "PRIVACY" ], "WRITE_CONTACTS" : [ "PRIVACY" ], "READ_HISTORY_BOOKMARKS" : [ "PRIVACY" ], "WRITE_HISTORY_BOOKMARKS" : [ "PRIVACY" ], "READ_PROFILE" : [ "PRIVACY" ], "WRITE_PROFILE" : [ "PRIVACY" ], "READ_SOCIAL_STREAM" : [ "PRIVACY" ], "WRITE_SOCIAL_STREAM" : [ "PRIVACY" ], "READ_CALENDAR" : [ "PRIVACY" ], "WRITE_CALENDAR" : [ "PRIVACY" ], "READ_USER_DICTIONARY" : [ "PRIVACY" ], "WRITE_USER_DICTIONARY" : [ "PRIVACY" ], "SET_ALARM" : [ "PRIVACY" ], "ADD_VOICEMAIL" : [ "PRIVACY" ], "GET_ACCOUNTS" : [ "PRIVACY" ], "MANAGE_ACCOUNTS" : [ "PRIVACY" ], "RECORD_AUDIO" : [ "PRIVACY" ], "CAMERA" : [ "PRIVACY" ], "ACCESS_FINE_LOCATION" : [ "PRIVACY", "GPS" ], "ACCESS_COARSE_LOCATION" : [ "PRIVACY", "GPS" ], "ACCESS_LOCATION_EXTRA_COMMANS" : [ "GPS"], "INSTALL_LOCATION_PROVIDER" : [ "GPS" ], } for i in a.get_permissions(): perm = i.split(".")[-1] try: flags[ DVM_PERMISSIONS["MANIFEST_PERMISSION"][perm][0].upper() ] += 1 for j in perms: if j == perm: for k in perms[j]: flags[k] += 1 except: debug("Unknown permission %s" % perm)
def actionXref(self): cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() selection = cursor.selectedText() androconf.debug("Xref asked for '%s' (%d, %d)" % (selection, start, end)) if start not in self.doc.binding.keys(): self.mainwin.showStatus("Xref not available. No info for: '%s'." % selection) return class_ = None method_ = None t = self.doc.binding[start] print t if t[0] == 'NAME_METHOD_PROTOTYPE': method_ = t[1] if method_ == self.title: method_ = 'init' proto_ = t[2].method.proto method_class_name = self.current_class.get_name() method_name = method_ method_proto = proto_ current_analysis = self.session.get_analysis(self.current_class) androconf.debug( "Found corresponding method: %s %s %s in source file: %s" % (method_class_name, method_name, method_proto, self.current_filename)) class_analysis = current_analysis.get_class_analysis( self.current_class.get_name()) if not class_analysis: self.mainwin.showStatus( "No xref returned (no class_analysis object).") return method_analysis = class_analysis.get_method_analysis( current_analysis.get_method_by_name(method_class_name, method_name, method_proto)) print method_analysis if not method_analysis: self.mainwin.showStatus( "No xref returned (no method_analysis object).") return xwin = XrefDialogMethod(parent=self.mainwin, win=self.mainwin, current_class=self.current_class, class_analysis=class_analysis, method_analysis=method_analysis) xwin.show() elif t[0] == 'NAME_FIELD': field_ = t[3] current_analysis = self.session.get_analysis(self.current_class) class_analysis = current_analysis.get_class_analysis( self.current_class.get_name()) if not class_analysis: self.mainwin.showStatus( "No xref returned (no class_analysis object).") return field_analysis = class_analysis.get_field_analysis(field_) print field_analysis if not field_analysis: self.mainwin.showStatus( "No xref returned (no field_analysis object).") return xwin = XrefDialogField(parent=self.mainwin, win=self.mainwin, current_class=self.current_class, class_analysis=class_analysis, field_analysis=field_analysis) xwin.show() else: self.mainwin.showStatus("No xref returned.") return
def renameElement(self, oldname, newname, info): '''Called back after a user chose a new name for an element. ''' androconf.debug("Renaming %s into %s in %s" % (oldname, newname, self.current_filename)) start, end = info try: t = self.doc.binding[start] except: self.mainwin.showStatus("Unexpected error in renameElement") return # Determine type of the to-be-renamed element and Androguard internal objects type_ = None if t[0] == 'NAME_METHOD_PROTOTYPE': # method definition in a class method_ = t[1] if method_ == self.title: method_ = 'init' proto_ = t[2].method.proto androconf.debug("Found: class=%s, method=%s, proto=%s" % (self.current_class, method_, proto_)) type_ = "METHOD" elif t[0] == 'NAME_METHOD_INVOKE': # method call in a method class_, method_ = t[2].split(' -> ') class_ = classdot2class(class_) if class_ == 'this': class_ = self.path proto_ = proto2methodprotofunc("".join(t[3]) + t[4]) androconf.debug("Found: class=%s, method=%s, proto=%s" % (class_, method_, proto_)) type_ = "METHOD" elif t[0] == 'NAME_PROTOTYPE': # class definition on top of a class class_ = t[2] + '.' + t[1] package_ = t[2] androconf.debug("Found: package=%s, class=%s" % (package_, class_)) type_ = "CLASS" elif t[0] == 'NAME_FIELD': field_item = t[3] type_ = "FIELD" else: self.mainwin.showStatus( "Rename not available. Info found: '%s' but object not supported." % selection) return # Do the actual renaming if type_ == "METHOD": if self.method_name_exist(newname): self.mainwin.showStatus("Method name already exist") return method_class_name = self.current_class.get_name() method_name = method_ method_proto = proto_ current_analysis = self.session.get_analysis(self.current_class) method_item = current_analysis.get_method_by_name( method_class_name, method_name, method_proto) if not method_item: self.mainwin.showStatus("Impossible to find the method") return method_item.set_name(str(newname)) #unicode to ascii elif type_ == "CLASS": newname_class = classdot2class(package_ + '.' + newname) self.mainwin.showStatus("New name: %s" % newname_class) class_item = self.current_class #getattr(self.mainwin.d, classdot2func(class_)) class_item.set_name(str(newname_class)) #unicode to ascii self.mainwin.updateDockWithTree() elif type_ == 'FIELD': if self.field_name_exist(newname): self.mainwin.showStatus("Field name already exist") return field_item.set_name(str(newname)) else: self.mainwin.showStatus("Unsupported type: %s" % str(type_)) return self.reload_java_sources()