Esempio n. 1
0
 def do_attacksurface(self, args):
     """
     := attacksurface
     """
     try:
         if self.apk and self.components:
             self.logger.log("info", "Loading attacksurface module ...")
             from core.brains.apk.attacksurface import AttackSurface
             self.attack_surface = AttackSurface(self.apk, self.components)
             self.attack_surface.run()
     except ImportError as e:
         CommandError(e.message)
Esempio n. 2
0
 def do_attacksurface(self, args):
     """
     := attacksurface
     """
     try:
         if self.apk and self.components:
             self.logger.log("info", "Loading attacksurface module ...")
             from core.brains.apk.attacksurface import AttackSurface
             self.attack_surface = AttackSurface(self.apk, self.components)
             self.attack_surface.run()
             # Helps with visual spacing after the results are printed
             print("\n")
     except ImportError as e:
         CommandError(e.message)
Esempio n. 3
0
 def do_attacksurface(self, *args):
     """
     := attacksurface
     """
     try:
         if self.apk and self.components:
             self.logger.log("info", "Loading attacksurface module ...")
             from core.brains.apk.attacksurface import AttackSurface
             self.attack_surface = AttackSurface(self.apk, self.components)
             self.attack_surface.run()
             # Helps with visual spacing after the results are printed
             print("\n")
     except ImportError as e:
         CommandError("attacksurface : {}".format(e))
Esempio n. 4
0
class Run(Lobotomy):
    def __init__(self):
        Lobotomy.__init__(self)
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self):
        """
        Process the application's classes.dex

        Args:
            None

        Results:
            None
        """
        # Make sure classes.dex exists
        if self.find_dex():
            self.dex = self.apk.get_dex()
            # Analyze classes.dex
            # TODO Throw in a progress bar, this can take awhile
            if self.dex:
                self.logger.log("info", "Loading classes.dex ...")
                from androguard.core.bytecodes.dvm import DalvikVMFormat
                from androguard.core.analysis.analysis import VMAnalysis
                from androguard.core.analysis.ganalysis import GVMAnalysis
                # Create a new virtual machine instance
                self.vm = DalvikVMFormat(self.dex)
                if self.vm:
                    print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                    self.logger.log("info", "Analyzing classes.dex ...")
                    # Analyze the virtual machine instance
                    self.vmx = VMAnalysis(self.vm)
                    self.gmx = GVMAnalysis(self.vmx, None)
                    if self.vmx and self.gmx:
                        print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                        self.vm.set_vmanalysis(self.vmx)
                        self.vm.set_gvmanalysis(self.gmx)
                        # Generate xref(s)
                        self.vm.create_xref()
                        self.vm.create_dref()
                    else:
                        CommandError("Cannot analyze VM instance (!)")
                else:
                    CommandError("Cannot load VM instance (!)")
        else:
            CommandError("classes.dex not found (!)")

    def do_operate(self, args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        try:
            if args.split()[0] == "apk":
                if args.split()[1]:
                    self.logger.log("info", "Loading : {} ...".format(args.split()[1].split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(args.split()[1])
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n".format(args.split()[1].split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process virtual machine
                        self.process_vm()
                    else:
                        CommandError("APK not loaded (!)")
            else:
                CommandError("Unkown command (!)")
        except ImportError as e:
            CommandError(e.message)
        except IndexError as e:
            CommandError("Not enough arguments (!)")

    def do_surgical(self, args):
        """
        := surgical
        """

        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_attacksurface(self, args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
        except ImportError as e:
            CommandError(e.message)

    def do_permissions(self, args):
        """
        := permissions list
        """
        try:
            if self.permissions:
                if args.split()[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_files(self, args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        try:
            if self.files:
                if args.split()[0]:
                    if args.split()[0] == "assets":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("assets"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "libs":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("lib"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "res":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("res"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "all":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError(e.message)

    def do_strings(self, args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """

        # Locals
        strings = None

        try:
            if args.split()[0] == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}".format(s.encode("utf-8"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif args.split()[0] == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : \n"))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s)))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            # We might be see an exception like this:
            # 'utf8' codec can't decode byte 0xc0 in position 0: invalid start byte
            raise e
            CommandError(e.message)

    def do_components(self, args):
        """
        := components list
        """
        try:
            if args.split()[0] == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}".format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}".format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}".format(s)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}".format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_interact(self, args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_macro(self, args):
        """
        """
        return
Esempio n. 5
0
class Run(Lobotomy):
    def __init__(self, ROOT_DIR):
        Lobotomy.__init__(self)
        self.ROOT_DIR = ROOT_DIR
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self, apk=False, dex=False):
        """
        Process the application's classes.dex

        Args:
            param1 = boolean
            param2 = boolean

        Results:
            None
        """
        try:
            if apk:
                # Make sure the APK contains a classes.dex file
                if self.find_dex():
                    self.dex = self.apk.get_dex()
                    if self.dex:
                        self.logger.log("info", "Loading classes.dex ...")
                        from androguard.core.bytecodes.dvm import DalvikVMFormat
                        from androguard.core.analysis.analysis import VMAnalysis
                        from androguard.core.analysis.ganalysis import GVMAnalysis
                        # Create a DalvikVMFormat instance ...
                        # In this case self.dex will be a file type
                        self.vm = DalvikVMFormat(self.dex)
                        if self.vm:
                            print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                            self.logger.log("info", "Analyzing classes.dex ...")
                            # Analyze the DalvikVMFormat instance and return
                            # analysis instances of VMAnalysis and GVMAnalysis
                            self.vmx = VMAnalysis(self.vm)
                            self.gmx = GVMAnalysis(self.vmx, None)
                            if self.vmx and self.gmx:
                                print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                                # Set the analysis properties on the
                                # DalvikVMFormat instance
                                self.vm.set_vmanalysis(self.vmx)
                                self.vm.set_gvmanalysis(self.gmx)
                                # Generate xref(s) and dref(s)
                                self.vm.create_xref()
                                self.vm.create_dref()
                                return
                            else:
                                CommandError("process_vm : Cannot analyze VM instance (!)")
                                return
                        else:
                            CommandError("process_vm : Cannot load VM instance (!)")
                            return
                    else:
                        CommandError("process_vm : classes.dex not found (!)")
                        return
            if dex:
                if self.dex:
                    from androguard.core.bytecodes.dvm import DalvikVMFormat
                    from androguard.core.analysis.analysis import VMAnalysis
                    from androguard.core.analysis.ganalysis import GVMAnalysis
                    # Analyze the DalvikVMFormat instance and return
                    # analysis instances of VMAnalysis and GVMAnalysis
                    self.vm = DalvikVMFormat(self.util.read(self.dex))
                    if self.vm:
                        print(self.t.yellow("\n\t--> Loaded {} (!)\n"
                                            .format(self.dex
                                                    .split("/")[-1])))
                        self.logger.log("info", "Analyzing {} ..."
                                        .format(self.dex
                                                .split("/")[-1]))
                        # Set the analysis properties on the
                        # DalvikVMFormat instance
                        self.vmx = VMAnalysis(self.vm)
                        self.gmx = GVMAnalysis(self.vmx, None)
                        if self.vmx and self.gmx:
                            print(self.t.yellow("\n\t--> Analyzed {} (!)\n"
                                                .format(self.dex
                                                        .split("/")[-1])))
                            # Set the analysis properties on the
                            # DalvikVMFormat instance
                            self.vm.set_vmanalysis(self.vmx)
                            self.vm.set_gvmanalysis(self.gmx)
                            # Generate xref(s) and dref(s)
                            self.vm.create_xref()
                            self.vm.create_dref()
                            return
                        else:
                            CommandError("process_vm :" +
                                         "Cannot analyze VM instance (!)")
                            return
                    else:
                        CommandError("process_vm :" +
                                     "Cannot load VM instance (!)")
                        return
                else:
                    CommandError("process_vm : classes.dex not found (!)")
                    return
        except Exception as e:
            CommandError("process_vm : {}".format(e))

    def do_operate(self, args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        try:
            if args.split()[0] == "apk":
                if args.split()[1]:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(args.split()[1].split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(args.split()[1])
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n"
                                            .format(args.split()[1]
                                                    .split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process DVM
                        self.process_vm(apk=True)
                    else:
                        CommandError("APK not loaded (!)")
            elif args.split()[0] == "dex":
                self.logger.log("info", "Loading : {} ..."
                                .format(args.split()[1].split("/")[-1]))
                if args.split()[1]:
                    self.dex = args.split()[1]
                    # Process DVM
                    self.process_vm(dex=True)
            else:
                CommandError("Unkown command (!)")
        except ImportError as e:
            CommandError(e.message)
        except IndexError as e:
            CommandError("Not enough arguments (!)")

    def do_surgical(self, args):
        """
        := surgical
        """

        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_attacksurface(self, args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
                # Helps with visual spacing after the results are printed
                print("\n")
        except ImportError as e:
            CommandError(e.message)

    def do_permissions(self, args):
        """
        := permissions list
        """
        try:
            if self.permissions:
                if args.split()[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_binja(self, args):
        """
        := binja
        """
        rpc = None
        functions = None

        try:
            import xmlrpclib
            rpc = xmlrpclib.ServerProxy('http://localhost:6666/lobotomy')
            functions = rpc.jni()
            if functions:
                self.logger.log("info", "Found JNI methods (!)")
                print("\n")
                for f in functions:
                    print(self.t.cyan("\t--> {}".format(f)))
                print("\n")
            else:
                self.logger.info("Registered JNI functions not found (!)")
        except Exception as e:
            CommandError("binja : {}".format(e))

    def do_files(self, args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        try:
            if self.files:
                if args.split()[0]:
                    if args.split()[0] == "assets":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("assets"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "libs":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("lib"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "res":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("res"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "all":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError(e.message)

    def do_strings(self, args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """

        # Locals
        strings = None

        try:
            if args.split()[0] == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}"
                                              .format(s.encode("utf-8"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif args.split()[0] == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : "))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s)))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            # We might be see an exception like this:
            # 'utf8' codec can't decode byte 0xc0 in position 0:
            # invalid start byte
            raise e
            CommandError(e.message)

    def do_components(self, args):
        """
        := components list
        """
        try:
            if args.split()[0] == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}"
                                                .format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}"
                                                .format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}"
                                                .format(r)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}"
                                                .format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_interact(self, args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_class_tree(self, args):
        """
        := class_tree
        """
        try:
            if self.vm:
                for c in self.vm.get_classes():
                    print("\n")
                    print(self.t.yellow("\t--> class : {}".format(c.name)))
                    for f in c.get_fields():
                        print(self.t.white("\t\t--> field : {}".format(f.name)))
                    for m in c.get_methods():
                        print(self.t.cyan("\t\t\t--> method : {}".format(m.name)))
                print("\n")
            else:
                CommandError("class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("class_tree : {}".format(e))

    def do_native(self, args):
        """
        := native
        """
        native_methods = list()

        try:
            if self.vm:
                for method in self.vm.get_methods():
                    if method.get_access_flags() & 0x100:
                        native_methods.append((method.get_class_name(),
                                               method.get_name()))
                if native_methods:
                    print("\n")
                    for n in native_methods:
                        print(self.t.cyan("\t--> {} : {}".format(n[0], n[1])))
                    print("\n")
            else:
                self.logger.log("info",
                                "class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("native : {}".format(e))

    def do_ui(self, args):
        """
        := ui
        """
        try:
            if self.vm and self.vmx:
                from core.brains.ui.terminal import TerminalApp
                ui = TerminalApp(self.vm, self.vmx)
                ui.run()
        except Exception as e:
            CommandError("ui : {}".format(e))

    def do_macro(self, args):
        """
        := macro
        """
        # Locals
        directory_items = None
        macro = path.join(self.ROOT_DIR, "macro")
        selection = None
        apk_path = None
        json = None

        try:
            print("\n")
            directory_items = listdir(macro)
            for i in range(0, len(directory_items)):
                print(self.t.cyan("\t--> [{}] {}"
                                  .format(i, directory_items[i])))
            print("\n")
            selection = raw_input(self.t.yellow("\t--> Select config : "))
            print("\n")
            if selection:
                for f in directory_items:
                    if selection == f:
                        with open("".join([macro, "/", f]), "rb") as config:
                            # Load the config as JSON
                            json = loads(config.read())
                            if json:
                                for k, v in json.items():
                                    if k == "apk":
                                        if v:
                                            apk_path = str(v)
                                            # Call operate() with the path to
                                            # apk
                                            self.do_operate("apk {}"
                                                            .format(apk_path))
                                            return
                                        else:
                                            CommandError("macro : Path to APK not found in {}"
                                                         .format(selection))
                            else:
                                CommandError("macro : Error loading {} as JSON"
                                             .format(selection))
        except Exception as e:
            CommandError("macro : {}".format(e))
Esempio n. 6
0
class Run(Lobotomy):
    def __init__(self, ROOT_DIR):
        Lobotomy.__init__(self)
        self.ROOT_DIR = ROOT_DIR
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def _cmd_completer(self, name, text, line, begidx, endidx):
        fn = getattr(self, 'do_'+name)
        if not hasattr(fn.im_func, "_expected_args"):
            return []
        a = [arg for arg in fn.im_func._expected_args if arg.startswith(text)]
        return a

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self, apk=False, dex=False):
        """
        Process the application's classes.dex

        Args:
            param1 = boolean
            param2 = boolean

        Results:
            None
        """
        try:
            if apk:
                # Make sure the APK contains a classes.dex file
                if self.find_dex():
                    self.dex = self.apk.get_dex()
                    if self.dex:
                        self.logger.log("info", "Loading classes.dex ...")
                        from androguard.core.bytecodes.dvm import DalvikVMFormat
                        from androguard.core.analysis.analysis import VMAnalysis
                        from androguard.core.analysis.ganalysis import GVMAnalysis
                        # Create a DalvikVMFormat instance ...
                        # In this case self.dex will be a file type
                        self.vm = DalvikVMFormat(self.dex)
                        if self.vm:
                            print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                            self.logger.log("info", "Analyzing classes.dex ...")
                            # Analyze the DalvikVMFormat instance and return
                            # analysis instances of VMAnalysis and GVMAnalysis
                            self.vmx = VMAnalysis(self.vm)
                            self.gmx = GVMAnalysis(self.vmx, None)
                            if self.vmx and self.gmx:
                                print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                                # Set the analysis properties on the
                                # DalvikVMFormat instance
                                self.vm.set_vmanalysis(self.vmx)
                                self.vm.set_gvmanalysis(self.gmx)
                                # Generate xref(s) and dref(s)
                                self.vm.create_xref()
                                self.vm.create_dref()
                                return
                            else:
                                CommandError("process_vm : Cannot analyze VM instance (!)")
                                return
                        else:
                            CommandError("process_vm : Cannot load VM instance (!)")
                            return
                    else:
                        CommandError("process_vm : classes.dex not found (!)")
                        return
            if dex:
                if self.dex:
                    from androguard.core.bytecodes.dvm import DalvikVMFormat
                    from androguard.core.analysis.analysis import VMAnalysis
                    from androguard.core.analysis.ganalysis import GVMAnalysis
                    # Analyze the DalvikVMFormat instance and return
                    # analysis instances of VMAnalysis and GVMAnalysis
                    self.vm = DalvikVMFormat(self.util.read(self.dex))
                    if self.vm:
                        print(self.t.yellow("\n\t--> Loaded {} (!)\n"
                                            .format(self.dex
                                                    .split("/")[-1])))
                        self.logger.log("info", "Analyzing {} ..."
                                        .format(self.dex
                                                .split("/")[-1]))
                        # Set the analysis properties on the
                        # DalvikVMFormat instance
                        self.vmx = VMAnalysis(self.vm)
                        self.gmx = GVMAnalysis(self.vmx, None)
                        if self.vmx and self.gmx:
                            print(self.t.yellow("\n\t--> Analyzed {} (!)\n"
                                                .format(self.dex
                                                        .split("/")[-1])))
                            # Set the analysis properties on the
                            # DalvikVMFormat instance
                            self.vm.set_vmanalysis(self.vmx)
                            self.vm.set_gvmanalysis(self.gmx)
                            # Generate xref(s) and dref(s)
                            self.vm.create_xref()
                            self.vm.create_dref()
                            return
                        else:
                            CommandError("process_vm :" +
                                         "Cannot analyze VM instance (!)")
                            return
                    else:
                        CommandError("process_vm :" +
                                     "Cannot load VM instance (!)")
                        return
                else:
                    CommandError("process_vm : classes.dex not found (!)")
                    return
        except Exception as e:
            CommandError("process_vm : {}".format(e))

    def complete_operate(self, *args):
        return self._cmd_completer("operate", *args)

    @cmd_arguments(["apk", "dex"])
    def do_operate(self, *args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        # Locals
        arg0 = args[0].split(" ")[0]
        arg1 = args[0].split(" ")[1]

        try:
            if arg0 == "apk":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(arg1)
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n"
                                            .format(arg1.split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process DVM
                        self.process_vm(apk=True)
                    else:
                        CommandError("APK not loaded (!)")
            elif arg0 == "dex":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    self.dex = arg1
                    self.process_vm(dex=True)
        except ImportError as e:
            CommandError("operate : {}".format(e))

    def complete_surgical(self, *args):
        return self._cmd_completer("surgical", *args)

    def do_surgical(self, *args):
        """
        := surgical
        """
        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("surgical : {}".format(e))

    def complete_attacksurface(self, *args):
        return self._cmd_completer("attacksurface", *args)

    def do_attacksurface(self, *args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
                # Helps with visual spacing after the results are printed
                print("\n")
        except ImportError as e:
            CommandError("attacksurface : {}".format(e))

    def complete_permissions(self, *args):
        return self._cmd_completer("permissions", *args)

    @cmd_arguments(["list"])
    def do_permissions(self, *args):
        """
        := permissions list
        """
        # Locals
        arg0 = args[0]

        try:
            if self.permissions:
                if args[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError("permissions : {}".format(e))

    def complete_binja(self, *args):
        return self._cmd_completer("binja", *args)

    def do_binja(self, *args):
        """
        := binja
        """
        try:
            from .binja import Run
            run = Run(self.files, self.apk)
            run.prompt = self.t.cyan("(binja) ")
            run.ruler = self.t.cyan("-")
            run.cmdloop()
        except Exception as e:
            CommandError("binja : {}".format(e))



    def complete_files(self, *args):
        return self._cmd_completer("files", *args)

    @cmd_arguments(["all", "assets", "libs", "res"])
    def do_files(self, *args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        # Locals
        arg0 = args[0]

        try:
            if self.files:
                if arg0 == "assets":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("assets"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "libs":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("lib"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "res":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("res"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "all":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError("files : {}".format(e))

    def complete_strings(self, *args):
        return self._cmd_completer("strings", *args)

    @cmd_arguments(["list", "search"])
    def do_strings(self, *args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """
        # Locals
        arg0 = args[0]
        strings = None

        try:
            if arg0 == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}".format(s.encode("utf-8", errors="ignore"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif arg0 == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : "))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s.encode("utf-8", errors="ignore"))))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("strings : {}".format(e))

    def complete_components(self, *args):
        return self._cmd_completer("components", *args)

    @cmd_arguments(["list"])
    def do_components(self, *args):
        """
        := components list
        """
        # Locals
        arg0 = args[0]

        try:
            if arg0 == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}"
                                                .format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}"
                                                .format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}"
                                                .format(r)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}"
                                                .format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
        except Exception as e:
            CommandError("components : {}".format(e))

    def complete_interact(self, *args):
        return self._cmd_completer("interact", *args)

    def do_interact(self, *args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("interact : {}".format(e.message))

    def complete_class_tree(self, *args):
        return self._cmd_completer("class_tree", *args)

    def do_class_tree(self, *args):
        """
        := class_tree
        """
        try:
            if self.vm:
                for c in self.vm.get_classes():
                    # We don't care about Android support classes or resource
                    # classes
                    if c.name.startswith("Landroid") or \
                            c.name.split("/")[-1].startswith("R") or \
                            "google" in c.name or \
                            "android" in c.name or \
                            "log4j" in c.name:
                        continue
                    print("\n")
                    print(self.t.yellow("\t--> class : {} {}".format(c.get_access_flags_string(), c.name)))
                    for f in c.get_fields():
                        print(self.t.white("\t\t--> field : {} {} {}".format(f.get_access_flags_string(), f.get_descriptor(), f.name)))
                    for m in c.get_methods():
                        print(self.t.cyan("\t\t\t--> method : {} {} {}".format(m.get_access_flags_string(), m.name, m.get_descriptor())))
                print("\n")
            else:
                CommandError("class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("class_tree : {}".format(e))

    def complete_native(self, *args):
        return self._cmd_completer("native", *args)

    def do_native(self, *args):
        """
        := native
        """
        # Locals
        native_methods = list()

        try:
            if self.vm:
                for method in self.vm.get_methods():
                    if method.get_access_flags() & 0x100:
                        native_methods.append((method.get_class_name(),
                                               method.get_name()))
                if native_methods:
                    print("\n")
                    for n in native_methods:
                        print(self.t.cyan("\t--> {} : {}".format(n[0], n[1])))
                    print("\n")
            else:
                self.logger.log("info",
                                "class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("native : {}".format(e))

    def complete_ui(self, *args):
        return self._cmd_completer("ui", *args)

    def do_ui(self, *args):
        """
        := ui
        """
        try:
            if self.vm and self.vmx:
                from core.brains.ui.terminal import TerminalApp
                ui = TerminalApp(self.vm, self.vmx)
                ui.run()
        except Exception as e:
            CommandError("ui : {}".format(e))

    def complete_macro(self, *args):
        return self._cmd_completer("macro", *args)

    def do_macro(self, args):
        """
        := macro
        """
        # Locals
        directory_items = None
        macro = path.join(self.ROOT_DIR, "macro")
        selection = None
        apk_path = None
        json = None

        try:
            print("\n")
            directory_items = listdir(macro)
            for i, item in enumerate(directory_items):
                print(self.t.cyan("\t--> [{}] {}"
                                  .format(i, item)))
            print("\n")
            selection = raw_input(self.t.yellow("[{}] Select config : ".format(datetime.now())))
            try:
                index = int(selection)
            except ValueError:
                index = -1
            print("\n")
            if selection:
                for i, item in enumerate(directory_items):
                    if selection == item or i == index:
                        selection = item
                        break
                with open("".join([macro, "/", selection]), "rb") as config:
                    # Load the config as JSON
                    json = loads(config.read())
                    if json:
                        for k, v in json.items():
                            if k == "apk":
                                if v:
                                    apk_path = str(v)
                                    # Call operate() with the path to apk
                                    self.do_operate("apk {}"
                                                    .format(apk_path))
                                    return
                                else:
                                    CommandError("macro : Path to APK not found in {}"
                                                 .format(selection))
                            else:
                                CommandError("macro : Error loading {} as JSON"
                                             .format(selection))
        except Exception as e:
            CommandError("macro : {}".format(e))
Esempio n. 7
0
class Run(Lobotomy):
    def __init__(self, ROOT_DIR):
        Lobotomy.__init__(self)
        self.ROOT_DIR = ROOT_DIR
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def _cmd_completer(self, name, text, line, begidx, endidx):
        fn = getattr(self, 'do_'+name)
        if not hasattr(fn.im_func, "_expected_args"):
            return []
        a = [arg for arg in fn.im_func._expected_args if arg.startswith(text)]
        return a

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self, apk=False, dex=False):
        """
        Process the application's classes.dex

        Args:
            param1 = boolean
            param2 = boolean

        Results:
            None
        """
        try:
            if apk:
                # Make sure the APK contains a classes.dex file
                if self.find_dex():
                    self.dex = self.apk.get_dex()
                    if self.dex:
                        self.logger.log("info", "Loading classes.dex ...")
                        from androguard.core.bytecodes.dvm import DalvikVMFormat
                        from androguard.core.analysis.analysis import VMAnalysis
                        from androguard.core.analysis.ganalysis import GVMAnalysis
                        # Create a DalvikVMFormat instance ...
                        # In this case self.dex will be a file type
                        self.vm = DalvikVMFormat(self.dex)
                        if self.vm:
                            print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                            self.logger.log("info", "Analyzing classes.dex ...")
                            # Analyze the DalvikVMFormat instance and return
                            # analysis instances of VMAnalysis and GVMAnalysis
                            self.vmx = VMAnalysis(self.vm)
                            self.gmx = GVMAnalysis(self.vmx, None)
                            if self.vmx and self.gmx:
                                print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                                # Set the analysis properties on the
                                # DalvikVMFormat instance
                                self.vm.set_vmanalysis(self.vmx)
                                self.vm.set_gvmanalysis(self.gmx)
                                # Generate xref(s) and dref(s)
                                self.vm.create_xref()
                                self.vm.create_dref()
                                return
                            else:
                                CommandError("process_vm : Cannot analyze VM instance (!)")
                                return
                        else:
                            CommandError("process_vm : Cannot load VM instance (!)")
                            return
                    else:
                        CommandError("process_vm : classes.dex not found (!)")
                        return
            if dex:
                if self.dex:
                    from androguard.core.bytecodes.dvm import DalvikVMFormat
                    from androguard.core.analysis.analysis import VMAnalysis
                    from androguard.core.analysis.ganalysis import GVMAnalysis
                    # Analyze the DalvikVMFormat instance and return
                    # analysis instances of VMAnalysis and GVMAnalysis
                    self.vm = DalvikVMFormat(self.util.read(self.dex))
                    if self.vm:
                        print(self.t.yellow("\n\t--> Loaded {} (!)\n"
                                            .format(self.dex
                                                    .split("/")[-1])))
                        self.logger.log("info", "Analyzing {} ..."
                                        .format(self.dex
                                                .split("/")[-1]))
                        # Set the analysis properties on the
                        # DalvikVMFormat instance
                        self.vmx = VMAnalysis(self.vm)
                        self.gmx = GVMAnalysis(self.vmx, None)
                        if self.vmx and self.gmx:
                            print(self.t.yellow("\n\t--> Analyzed {} (!)\n"
                                                .format(self.dex
                                                        .split("/")[-1])))
                            # Set the analysis properties on the
                            # DalvikVMFormat instance
                            self.vm.set_vmanalysis(self.vmx)
                            self.vm.set_gvmanalysis(self.gmx)
                            # Generate xref(s) and dref(s)
                            self.vm.create_xref()
                            self.vm.create_dref()
                            return
                        else:
                            CommandError("process_vm :" +
                                         "Cannot analyze VM instance (!)")
                            return
                    else:
                        CommandError("process_vm :" +
                                     "Cannot load VM instance (!)")
                        return
                else:
                    CommandError("process_vm : classes.dex not found (!)")
                    return
        except Exception as e:
            CommandError("process_vm : {}".format(e))

    def complete_operate(self, *args):
        return self._cmd_completer("operate", *args)

    @cmd_arguments(["apk", "dex"])
    def do_operate(self, *args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        # Locals
        arg0 = args[0].split(" ")[0]
        arg1 = args[0].split(" ")[1]

        try:
            if arg0 == "apk":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(arg1)
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n"
                                            .format(arg1.split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process DVM
                        self.process_vm(apk=True)
                    else:
                        CommandError("APK not loaded (!)")
            elif arg0 == "dex":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    self.dex = arg1
                    self.process_vm(dex=True)
        except ImportError as e:
            CommandError("operate : {}".format(e))

    def complete_surgical(self, *args):
        return self._cmd_completer("surgical", *args)

    def do_surgical(self, *args):
        """
        := surgical
        """
        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("surgical : {}".format(e))

    def complete_attacksurface(self, *args):
        return self._cmd_completer("attacksurface", *args)

    def do_attacksurface(self, *args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
                # Helps with visual spacing after the results are printed
                print("\n")
        except ImportError as e:
            CommandError("attacksurface : {}".format(e))

    def complete_permissions(self, *args):
        return self._cmd_completer("permissions", *args)

    @cmd_arguments(["list"])
    def do_permissions(self, *args):
        """
        := permissions list
        """
        # Locals
        arg0 = args[0]

        try:
            if self.permissions:
                if args[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError("permissions : {}".format(e))

    def complete_binja(self, *args):
        return self._cmd_completer("binja", *args)

    def do_binja(self, *args):
        """
        := binja
        """
        try:
            from .binja import Run
            run = Run(self.files, self.apk)
            run.prompt = self.t.cyan("(binja) ")
            run.ruler = self.t.cyan("-")
            run.cmdloop()
        except Exception as e:
            CommandError("binja : {}".format(e))



    def complete_files(self, *args):
        return self._cmd_completer("files", *args)

    @cmd_arguments(["all", "assets", "libs", "res"])
    def do_files(self, *args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        # Locals
        arg0 = args[0]

        try:
            if self.files:
                if arg0 == "assets":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("assets"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "libs":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("lib"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "res":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("res"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "all":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError("files : {}".format(e))

    def complete_strings(self, *args):
        return self._cmd_completer("strings", *args)

    @cmd_arguments(["list", "search"])
    def do_strings(self, *args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """
        # Locals
        arg0 = args[0]
        strings = None

        try:
            if arg0 == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}".format(s.encode("utf-8", errors="ignore"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif arg0 == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : "))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s.encode("utf-8", errors="ignore"))))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("strings : {}".format(e))

    def complete_components(self, *args):
        return self._cmd_completer("components", *args)

    @cmd_arguments(["list"])
    def do_components(self, *args):
        """
        := components list
        """
        # Locals
        arg0 = args[0]

        try:
            if arg0 == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}"
                                                .format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}"
                                                .format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}"
                                                .format(r)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}"
                                                .format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
        except Exception as e:
            CommandError("components : {}".format(e))

    def complete_interact(self, *args):
        return self._cmd_completer("interact", *args)

    def do_interact(self, *args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("interact : {}".format(e.message))

    def complete_class_tree(self, *args):
        return self._cmd_completer("class_tree", *args)

    def do_class_tree(self, *args):
        """
        := class_tree
        """
        try:
            if self.vm:
                for c in self.vm.get_classes():
                    # We don't care about Android support classes or resource
                    # classes
                    if c.name.startswith("Landroid") or \
                            c.name.split("/")[-1].startswith("R"):
                        continue
                    print("\n")
                    print(self.t.yellow("\t--> class : {} {}".format(c.get_access_flags_string(), c.name)))
                    for f in c.get_fields():
                        print(self.t.white("\t\t--> field : {} {} {}".format(f.get_access_flags_string(), f.get_descriptor(), f.name)))
                    for m in c.get_methods():
                        print(self.t.cyan("\t\t\t--> method : {} {} {}".format(m.get_access_flags_string(), m.name, m.get_descriptor())))
                print("\n")
            else:
                CommandError("class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("class_tree : {}".format(e))

    def complete_native(self, *args):
        return self._cmd_completer("native", *args)

    def do_native(self, *args):
        """
        := native
        """
        # Locals
        native_methods = list()

        try:
            if self.vm:
                for method in self.vm.get_methods():
                    if method.get_access_flags() & 0x100:
                        native_methods.append((method.get_class_name(),
                                               method.get_name()))
                if native_methods:
                    print("\n")
                    for n in native_methods:
                        print(self.t.cyan("\t--> {} : {}".format(n[0], n[1])))
                    print("\n")
            else:
                self.logger.log("info",
                                "class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("native : {}".format(e))

    def complete_ui(self, *args):
        return self._cmd_completer("ui", *args)

    def do_ui(self, *args):
        """
        := ui
        """
        try:
            if self.vm and self.vmx:
                from core.brains.ui.terminal import TerminalApp
                ui = TerminalApp(self.vm, self.vmx)
                ui.run()
        except Exception as e:
            CommandError("ui : {}".format(e))

    def complete_macro(self, *args):
        return self._cmd_completer("macro", *args)

    def do_macro(self, args):
        """
        := macro
        """
        # Locals
        directory_items = None
        macro = path.join(self.ROOT_DIR, "macro")
        selection = None
        apk_path = None
        json = None

        try:
            print("\n")
            directory_items = listdir(macro)
            for i, item in enumerate(directory_items):
                print(self.t.cyan("\t--> [{}] {}"
                                  .format(i, item)))
            print("\n")
            selection = raw_input(self.t.yellow("[{}] Select config : ".format(datetime.now())))
            try:
                index = int(selection)
            except ValueError:
                index = -1
            print("\n")
            if selection:
                for i, item in enumerate(directory_items):
                    if selection == item or i == index:
                        selection = item
                        break
                with open("".join([macro, "/", selection]), "rb") as config:
                    # Load the config as JSON
                    json = loads(config.read())
                    if json:
                        for k, v in json.items():
                            if k == "apk":
                                if v:
                                    apk_path = str(v)
                                    # Call operate() with the path to apk
                                    self.do_operate("apk {}"
                                                    .format(apk_path))
                                    return
                                else:
                                    CommandError("macro : Path to APK not found in {}"
                                                 .format(selection))
                            else:
                                CommandError("macro : Error loading {} as JSON"
                                             .format(selection))
        except Exception as e:
            CommandError("macro : {}".format(e))