Ejemplo n.º 1
0
    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_)
Ejemplo n.º 2
0
    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 !")
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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.")
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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))
Ejemplo n.º 8
0
    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())
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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()
Ejemplo n.º 15
0
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))
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
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
Ejemplo n.º 18
0
 def display_bytecodes(self):
     androconf.debug("Display bytecodes for %s" % self.current_class)
     self.mainwin.openBytecodeWindow(self.current_class)
Ejemplo n.º 19
0
    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()
Ejemplo n.º 20
0
    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