Beispiel #1
0
class CFG():
    def __init__(self, filename):
        self.filename = filename
        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.cfg = self.build_cfg()

    def get_cg(self):
        return self.cfg

    def get_cfg(self):
        return self.dx.get_call_graph()

    def build_cfg(self):
        """ Using NX and Androguard, build a directed graph NX object so that:
            - node names are analysis.MethodClassAnalysis objects
            - each node has a label that encodes the method behavior
        """
        cfg = self.get_cfg()  ##/////////My changes///////////////
        for n in cfg.nodes:
            instructions = []
            # print(n)
            try:
                ops = n.get_instructions()
                for i in ops:
                    instructions.append(i.get_name())
                # print(ops)
                encoded_label = self.color_instructions(instructions)
                # print("No Exception")
            except AttributeError:
                encoded_label = np.array([0] * 15)
            cfg.node[n]["label"] = encoded_label
        return cfg

    def color_instructions(self, instructions):
        """ Node label based on coloring technique by Kruegel """

        h = [0] * len(INSTRUCTION_CLASS_COLOR)
        for i in instructions:
            h[INSTRUCTION_SET_COLOR[i]] = 1
        return np.array(h)

    def get_classes_from_label(self, label):
        classes = [
            INSTRUCTION_CLASSES[i] for i in range(len(label)) if label[i] == 1
        ]
        return classes
Beispiel #2
0
    def addDEX(self, filename, data, dx=None, postpone_xref=False):
        """
        Add a DEX file to the Session and run analysis.

        :param filename: the (file)name of the DEX file
        :param data: binary data of the dex file
        :param dx: an existing Analysis Object (optional)
        :param postpone_xref: True if no xref shall be created, and will be called manually
        :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEX:%s" % digest)

        log.debug("Parsing format ...")
        d = DalvikVMFormat(data)
        log.debug("added DEX:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if dx is None:
            dx = Analysis()

        dx.add(d)
        if not postpone_xref:
            dx.create_xref()

        # TODO: If multidex: this will called many times per dex, even if already set
        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)
        self.analyzed_vms[digest] = dx

        if self.export_ipython:
            log.debug("Exporting in ipython")
            d.create_python_export()

        return digest, d, dx
Beispiel #3
0
    def addDEX(self, filename, data, dx=None):
        """
        Add a DEX file to the Session and run analysis.

        :param filename: the (file)name of the DEX file
        :param data: binary data of the dex file
        :param dx: an existing Analysis Object (optional)
        :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEX:%s" % digest)

        log.debug("Parsing format ...")
        d = DalvikVMFormat(data)
        log.debug("added DEX:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if dx is None:
            dx = Analysis()

        dx.add(d)
        dx.create_xref()

        # TODO: If multidex: this will called many times per dex, even if already set
        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)
        self.analyzed_vms[digest] = dx

        if self.export_ipython:
            log.debug("Exporting in ipython")
            d.create_python_export()

        return digest, d, dx
Beispiel #4
0
class PDG():
    def __init__(self, filename):
        """

        :type self: object
        """
        self.filename = filename
        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.fcg = self.dx.get_call_graph()
        self.icfg = self.build_icfg()

    def get_graph(self):
        return self.icfg

    def build_icfg(self):
        icfg = nx.DiGraph()
        methods = self.d.get_methods()
        for method in methods:
            for bb in self.dx.get_method(method).basic_blocks.get():
                children = []
                label = self.get_bb_label(bb)
                children = self.get_children(bb, self.dx)
                icfg.add_node(label)
                icfg.add_edges_from([(label, child) for child in children])
        return icfg

    def get_bb_label(self, bb):
        """ Return the descriptive name of a basic block
        """
        return self.get_method_label(bb.method) + (bb.name, )

    def get_method_label(self, method):
        """ Return the descriptive name of a method
        """
        return (method.get_class_name(), method.get_name(),
                method.get_descriptor())

    def get_children(self, bb, dx):
        """ Return the labels of the basic blocks that are children of the
        input basic block in and out of its method
        """
        return self.get_bb_intra_method_children(
            bb) + self.get_bb_extra_method_children(bb, dx)

    def get_bb_intra_method_children(self, bb):
        """ Return the labels of the basic blocks that are children of the
        input basic block within a method
        """
        child_labels = []
        for c_in_bb in bb.get_next():
            next_bb = c_in_bb[2]
            child_labels.append(self.get_bb_label(next_bb))
        return child_labels

    def get_bb_extra_method_children(self, bb, dx):
        """ Given a basic block, find the calls to external methods and
        return the label of the first basic block in these methods
        """

        call_labels = []
        # iterate over calls from bb method to external methods
        try:
            xrefs = dx.get_method_analysis(bb.method).get_xref_to()
        except AttributeError:
            return call_labels
        for xref in xrefs:
            remote_method_offset = xref[2]
            if self.call_in_bb(bb, remote_method_offset):
                try:
                    remote_method = dx.get_method(
                        self.d.get_method_by_idx(remote_method_offset))
                    if remote_method:
                        remote_bb = next(remote_method.basic_blocks.get())
                        call_labels.append(self.get_bb_label(remote_bb))
                except StopIteration:
                    pass
        return call_labels

    def call_in_bb(self, bb, idx):
        return bb.get_start() <= idx <= bb.get_end()
            if depth == 0:
                print(m.class_name + " -> " + m.name)
            for item in m.XREFfrom.items:
                if item[0].class_name != class_name or item[
                        0].name != method_name:
                    for x in range(1, depth):
                        sys.stdout.write('--')
                    sys.stdout.write('>' + item[0].class_name + "->" +
                                     item[0].name + "\n")
                    XrefTraverse(methods, item[0].class_name, item[0].name,
                                 depth)


if len(sys.argv) > 2:
    filename = sys.argv[1]
    class_name = sys.argv[2]
    class_name = 'L' + class_name.replace(".", "/") + ";"
    #print class_name
    method_name = '<init>'
    d = DalvikVMFormat(APK(filename, False).get_dex())
    d.create_python_export()
    dx = uVMAnalysis(d)
    gx = GVMAnalysis(dx, None)
    d.set_vmanalysis(dx)
    d.set_gvmanalysis(gx)
    d.create_xref()

    XrefTraverse(d.get_methods(), class_name, method_name, 0)
else:
    print "usage: XrefTree.py [filename] [class_name]"
    print "usage: XrefTree.py filename.apk com.xyz.abc"
Beispiel #6
0
class FCG():  ##/////////////Changed for testing/////////////////////
    def __init__(self, filename):
        self.filename = filename
        # print(os.path.exists(filename))
        # a,d,dx = AnalyzeAPK(filename)
        # print(dx.get_call_graph())

        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.fcg = self.build_fcg()

    def get_fcg(self):
        return self.fcg

    def get_lock_graph(self):
        graph_list = []
        # print("LockGraphs", self.dx)
        call_graph = self.dx.get_call_graph()
        # print("Call Graphs")
        for m in (self.dx.find_methods(
                classname='Landroid.os.PowerManager.WakeLock'
        )):  ##//////////Work fine but found 3 method so will use when done
            # print("Method=", m.get_method())
            ancestors = nx.ancestors(call_graph, m.get_method())
            ancestors.add(m.get_method())
            graph = call_graph.subgraph(ancestors)
            graph_list.append(graph)
        wake_graph = nx.compose_all(graph_list)
        return wake_graph

    def build_fcg(self):
        """ Using NX and Androguard, build a directed graph NX object so that:
            - node names are analysis.MethodClassAnalysis objects
            - each node has a label that encodes the method behavior
        """
        fcg = self.get_lock_graph()  ##/////////My changes///////////////

        for n in fcg.nodes:
            instructions = []
            try:
                ops = n.get_instructions()
                for i in ops:
                    instructions.append(i.get_name())
                encoded_label = self.color_instructions(instructions)
            except AttributeError:
                encoded_label = np.array([0] * 15)

            fcg.node[n]["label"] = encoded_label
        return fcg

    def color_instructions(self, instructions):
        """ Node label based on coloring technique by Kruegel """

        h = [0] * len(INSTRUCTION_CLASS_COLOR)
        for i in instructions:
            h[INSTRUCTION_SET_COLOR[i]] = 1
        return np.array(h)

    def get_classes_from_label(self, label):
        classes = [
            INSTRUCTION_CLASSES[i] for i in range(len(label)) if label[i] == 1
        ]
        return classes
def XrefTraverse(methods, class_name, method_name, depth):
    depth += 1
    for m in methods:
        if m.class_name == class_name and m.name == method_name:
            if depth == 0:
                print (m.class_name + " -> " + m.name)
            for item in m.XREFfrom.items:
                if item[0].class_name != class_name or item[0].name != method_name:                    
                    for x in range(1, depth):
                        sys.stdout.write('--')
                    sys.stdout.write ('>' + item[0].class_name + "->" + item[0].name + "\n")
                    XrefTraverse(methods, item[0].class_name, item[0].name, depth)

if len(sys.argv) > 2:
    filename = sys.argv[1]
    class_name = sys.argv[2]
    class_name = 'L' + class_name.replace(".", "/") + ";"
    #print class_name
    method_name = '<init>'
    d = DalvikVMFormat(APK(filename, False).get_dex())
    d.create_python_export()
    dx = uVMAnalysis(d)
    gx = GVMAnalysis(dx, None)
    d.set_vmanalysis(dx)
    d.set_gvmanalysis(gx)
    d.create_xref()

    XrefTraverse(d.get_methods(), class_name, method_name, 0)
else:
    print "usage: XrefTree.py [filename] [class_name]"
    print "usage: XrefTree.py filename.apk com.xyz.abc"