Esempio n. 1
0
    def run(self):
        result = {
            "title": "Application Does Not Check For Third-Party Keyboards",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report":
                True,
                "details":
                "No evidence of third party keyboard detection \
functions found."
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 2
0
    def run(self):
        result = {
            "title": "Application Was Compiled Without ARC Support",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report": True,
                "details": "No evidence of ARC functions found."
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 3
0
    def run(self):
        # create unzipped directory
        identifier = self.ipa.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]

        Log.info("Crating output directories")
        output_path = "{}/{}.unzipped".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Unzipping application")
        unzip(self.ipa, output_path)

        # get new identifier
        app_path = application_path(output_path)

        # get info
        info_module = InfoModule()
        info_module.unzipped_ipa = output_path
        info = info_module.run()
        for key in info:
            if key.endswith("_info"):
                info = info[key]
                break

        # move to new directory
        if "CFBundleIdentifier" in info:
            identifier = info["CFBundleIdentifier"]
            old_output_path = output_path
            output_path = "{}/{}.unzipped".format(self.output, identifier)
            execute("mv {} {}".format(old_output_path, output_path))

        return {
            "{}_unzipped".format(identifier): output_path,
            "print": "Application unzipped to {}".format(output_path)
        }
Esempio n. 4
0
    def run(self):
        Log.info("Preparing to re-compile the application")

        # get identifier
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" not in self.manifest:
            identifier = self.manifest.popitem()[1].package()

        recompiled_apk = "{}/{}-recompiled.apk".format(self.output, identifier)

        # unzip
        Log.info("Re-compiling application")
        output = recompile(self.decompiled_apk, recompiled_apk)

        if "Exception" in output:
            return {
                "print":
                "Failed to re-compile the application:\n{}".format(output)
            }

        return {
            "{}_recompiled".format(identifier): recompiled_apk,
            "print": "Application re-compiled to {}".format(recompiled_apk)
        }
Esempio n. 5
0
    def run(self):
        result = {
            "title": "Application Uses Deprecated Ciphers",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        ciphers = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            #ssl_socket_files = pretty_grep(self.file_regex, smali)
            ciphers.update(pretty_grep(self.regex, smali))

        if ciphers:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(ciphers, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 6
0
    def run(self):
        result = {
            "title": "Application Uses Native Libraries",
            "details": "",
            "severity": "Low",
            "report": False
        }

        Log.info("Identifying application's libraries")
        libs_path = [lib.strip() for lib in self.libs.split(";")]

        libraries = []
        if self.device.installed(self.identifier):
            app_path = self.device.packages()[self.identifier].rsplit("/",
                                                                      1)[0]

            libs_path_str = " ".join(
                ["{}/{}".format(app_path, lib) for lib in libs_path])

            libraries = [
                lib for lib in self.device.root_execute("ls {}".format(
                    libs_path_str)).split("\n")
                if lib and "No such file or directory" not in lib
            ]

        if libraries:
            result.update({
                "report": True,
                "details": "* {}".format("\n* ".join(libraries))
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 7
0
    def _start_connection(self):
        """
        Starts an SSH connection to the remote device
        """
        from scrounger.utils.ssh import SSHClient
        from scrounger.utils.general import process
        from scrounger.utils.config import SSH_COMMAND_TIMEOUT
        from scrounger.utils.config import SSH_SESSION_TIMEOUT

        # setup
        if not self._ssh_session:
            # this was breaking
            #self._iproxy_process = process(
            #    'iproxy 2222 22 {}'.format(self._device_id))
            self._iproxy_process = process("iproxy 2222 22")
            self._ssh_session = SSHClient("127.0.0.1", 2222, self._username,
                                          self._password, SSH_COMMAND_TIMEOUT)
            self._ssh_session.connect()

            # Log a new sessions
            _Log.debug("new ssh session started.")

        # start a tiemout for the connection
        from threading import Timer
        if self._timer:
            self._timer.cancel()  # cancel old timer and start new one

        self._timer = Timer(SSH_SESSION_TIMEOUT, self._stop_connection)
        self._timer.start()
Esempio n. 8
0
    def run(self):
        result = {
            "title": "Application Has Browsable Activities",
            "details": "",
            "severity": "Informational",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" in self.manifest:
            return {"print": "Could not get the manifest"}

        self.manifest = self.manifest.popitem()[1]

        Log.info("Getting browsable activities and uris")

        browsable_classes = self.manifest.browsable_activities()
        browsable_uris = self.manifest.browsable_uris()

        if browsable_classes or browsable_uris:
            details = "* URIs:\n * {}".format("\n * ".join(browsable_uris))
            details += "\n\n* Classes:\n * {}".format(
                "\n * ".join(browsable_classes))

            result.update({"report": True, "details": details})

        return {
            "{}_result".format(self.name()): result,
            "{}_browsable_classes".format(self.manifest.package()):
            browsable_classes,
            "{}_browsable_uris".format(self.manifest.package()): browsable_uris
        }
Esempio n. 9
0
    def run(self):
        result = {
            "title": "Application Does Not Implement SSL Pinning",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        Log.info("Getting application's strings")
        strs = strings(self.binary)

        Log.info("Analysing strings and class dump")
        matches = re.findall(self._regex, strs)
        evidence = pretty_grep(self._regex, self.class_dump)

        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following strings were found:\n* {}".format("\n* ".join(
                    sorted(set(matches))))
            })

        if evidence:
            result.update({
                "report":
                True,
                "details":
                "{}\nThe following was found in the class dump:\n\
{}".format(result["details"], pretty_grep_to_str(evidence, self.class_dump))
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 10
0
    def run(self):

        # get the jar first
        jar_module = JarModule()
        jar_module.output = self.output
        jar_module.apk = self.apk
        result = jar_module.run()

        self.jar = [result[jar] for jar in result if jar.endswith("_jar")][0]
        if not self.jar:
            return {"print": "Could not decompile the application"}

        Log.info("Creating source directory")
        # create source directory
        identifier = self.jar.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]

        output_path = "{}/{}.source".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Getting application's source")
        source(self.jar, output_path)

        return {
            "{}_source".format(identifier): output_path,
            "print": "Application source reversed to {}".format(output_path)
        }
Esempio n. 11
0
    def run(self):
        result = {
            "title": "Application Has Insecure ATS Configurations",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        info_content = plist(self.info)

        Log.info("Parsing Info.plist file contents")
        ats_xml = plist_dict_to_xml(info_content, self._ats_key)

        Log.info("Analysing Info.plist file")
        if self._ats_key not in info_content or not info_content[
                self._ats_key]:
            result.update({
                "report":
                True,
                "details":
                "No evidence of ATS being implemented found."
            })

        if any(option in ats_xml for option in self._insecure_options):
            result.update({
                "report":
                True,
                "details":
                "The following insecure ATS configuration was \
found : {}".format(ats_xml)
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 12
0
    def run(self):
        result = {
            "title": "Application Does Not Implement Root Detection",
            "details": "",
            "severity": "High",
            "report": True
        }

        # preparing variable to run
        root_detection = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            root_detection.update(pretty_grep(self.regex, smali))

        if root_detection:
            result = {
                "title":
                "Application Has Root Detection",
                "details":
                pretty_grep_to_str(root_detection, self.decompiled_apk,
                                   ignore),
                "severity":
                "Low",
                "report":
                True
            }

        return {"{}_result".format(self.name()): result}
Esempio n. 13
0
    def run(self):
        result = {
            "title": "Application Does Not Check For Third-Party Keyboards",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        third_party_keyboard_evidence = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            third_party_keyboard_evidence.update(pretty_grep(
                self.regex, smali))

            # remove ignored paths
            to_remove = []
            for filename in third_party_keyboard_evidence:
                if any(filepath in filename for filepath in ignore):
                    to_remove += [filename]
            for filename in to_remove:
                third_party_keyboard_evidence.pop(filename)

        if not third_party_keyboard_evidence:
            result.update({"report": True})

        return {"{}_result".format(self.name()): result}
Esempio n. 14
0
    def run(self):
        result = {
            "title": "Application Does Not Use Prepared Statements",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        sqlite_matches = re.findall(self._sqlite_regex, symbols)
        matches = re.findall(self._regex, symbols)
        if sqlite_matches and not matches:
            result.update({
                "report":
                True,
                "details":
                "Evidences of SQLite being used were found but no \
evidence of prepared statements being used was found."
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 15
0
    def run(self):
        Log.info("Installing binaries")
        binaries_to_install = self.binaries.split(";")
        packages_to_install = self.packages.split(";")
        repositories_to_install = self.repositories.split(";")
        binaries_local_path = "{}/bin/ios".format(_SCROUNGER_HOME)

        for binary in binaries_to_install:
            installed = self.device.install_binary("{}/{}".format(
                binaries_local_path, binary))

            if not installed:
                Log.error("Could not install {}".format(binary))

        scrounger_apt_list = "/etc/apt/sources.list.d/scrounger.list"
        repositories_list = " ".join(self.device.repositories())

        Log.info("Adding repositories")
        for repository in repositories_to_install:
            if repository not in repositories_list:
                Log.info("Adding {} repository".format(repository))
                if not repository.endswith("/"):
                    repository = "{}/".format(repository)
                self.device.execute("echo deb {} ./ >> {}".format(
                    repository, scrounger_apt_list))
                self.device.execute("apt update")

        packages = " ".join(packages_to_install)
        Log.info("Trying to install {}".format(packages))
        self.device.execute(
            "apt -y --allow-unauthenticated install {}".format(packages))

        return {
            "print": "Binaries installed."
        }
Esempio n. 16
0
    def run(self):
        Log.info("Dumping classes with otool")
        try:
            class_dump = otool_class_dump_to_dict(otool_class_dump(
                self.binary))
        except Exception as e:
            Log.error("An error ocurred when trying to use otool")
            Log.debug(e)
            Log.info("Trying jtool")
            class_dump = jtool_class_dump_to_dict(jtool_class_dump(
                self.binary))

        dump_name = self.binary.rsplit("/", 1)[-1].replace(" ", ".")
        result = {
            "{}_class_dump".format(dump_name.replace(".", "_")): class_dump
        }

        if hasattr(self, "output") and self.output:
            Log.info("Saving classes to file")
            dump_path = "{}/{}.class.dump".format(self.output, dump_name)

            # create output folder
            execute("mkdir -p {}".format(dump_path))
            save_class_dump(class_dump, dump_path)

            result.update({
                "{}_dump_path".format(dump_name.replace(".", "_")): dump_path,
                "print": "Dump saved in {}.".format(dump_path)
            })

        return result
Esempio n. 17
0
    def _start_connection(self):
        """
        Starts an SSH connection to the remote device
        """
        from scrounger.utils.ssh import SSHClient
        from scrounger.utils.config import SSH_COMMAND_TIMEOUT
        from scrounger.utils.config import SSH_SESSION_TIMEOUT
        from scrounger.utils.config import _SCROUNGER_HOME
        from scrounger.lib.tcprelay import create_server

        # setup
        if not self._ssh_session:

            self._relay_process = create_server()
            self._ssh_session = SSHClient("127.0.0.1", 2222, self._username,
                                          self._password, SSH_COMMAND_TIMEOUT)
            self._ssh_session.connect()

            # Log a new sessions
            _Log.debug("new ssh session started.")

        # add scrounger's key
        key_path = "{}/bin/ios/scrounger.pub".format(_SCROUNGER_HOME)
        if not self._ssh_session.add_key(key_path):
            _Log.debug("Scrounger's ssh key not in authorized_keys")

        # start a tiemout for the connection
        from threading import Timer
        if self._timer:
            self._timer.cancel()  # cancel old timer and start new one

        self._timer = Timer(SSH_SESSION_TIMEOUT, self._stop_connection)
        self._timer.start()
Esempio n. 18
0
    def run(self):
        result = {
            "title": "Application Does Not Disable Clipboard Access",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report":
                True,
                "details":
                "No evidence of the application trying to disable \
clipboard access."
            })

        return {"{}_result".format(self.name()): result}
    def run(self):
        result = {
            "title": "Application Communicates Over Unencrypted Channels",
            "details": "",
            "severity": "Medium",
            "report": False
        }
        ignore = [url.strip() for url in self.ignore.split(";")]

        Log.info("Getting application's strings")
        strs = strings(self.binary)

        Log.info("Analysing strings")
        report_matches = []
        matches = re.finditer(self._regex, strs)
        for item in matches:
            match = item.group()
            if any(iurl in match for iurl in ignore) or match == "http://":
                continue
            report_matches += [match]

        if report_matches:
            result.update({
                "report":
                True,
                "details":
                "The following strings were found:\n* {}".format("\n* ".join(
                    sorted(set(report_matches))))
            })

        return {"{}_result".format(self.name()): result}
    def run(self):
        result = {
            "title": "Application Makes Insecure Function Calls",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self.function_calls, symbols)
        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following function symbols were \
found: * {}".format("\n* ".join(sorted(set(matches))))
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 21
0
    def run(self):
        result = {
            "title": "Application Has World Writable Files",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        if not self.device.installed(self.identifier):
            return {"print": "Application not installed"}

        Log.info("Starting the application")
        self.device.start(self.identifier)

        sleep(5)

        Log.info("Analysing application's data")

        target_paths = self.device.data_paths(self.identifier)

        world_writable_files = []
        for data_path in target_paths:
            world_writable_files += self.device.world_files(data_path, "w")

        if world_writable_files:
            result.update({
                "report":
                True,
                "details":
                "* World Writable Files:\n * {}".format(
                    "\n* ".join(world_writable_files))
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 22
0
    def run(self):
        Log.info("Creating decompilation directory")

        # create decompiled directory
        identifier = self.apk.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]
        output_path = "{}/{}.decompiled".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Decompiling application")
        decompile(self.apk, output_path)

        # get identifier
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = output_path
        self.manifest = manifest_module.run()
        if "print" not in self.manifest:
            identifier = self.manifest.popitem()[1].package()

            # move decompiled app to new path
            old_output_path = output_path
            output_path = "{}/{}.decompiled".format(self.output, identifier)
            execute("mv {} {}".format(old_output_path, output_path))

        return {
            "{}_decompiled".format(identifier): output_path,
            "print": "Application decompiled to {}".format(output_path)
        }
Esempio n. 23
0
    def run(self):
        result = {
            "title": "Application Has Secret Codes",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" in self.manifest:
            return {"print": "Could not get the manifest"}

        self.manifest = self.manifest.popitem()[1]

        Log.info("Analysing application's manifest for secret codes")
        secret_codes = self.manifest.secret_codes()

        if secret_codes:
            details = "* Secret Codes:\n * {}".format(
                "\n * ".join(secret_codes))
            details += """

* Test the secret codes using the following command:
adb shell su -c "am broadcast -a {} -d android_secret_code://CODE"
            """.format(self._secret_code_activity)
            result.update({"report": True, "details": details})

        return {
            "{}_result".format(self.name()): result,
            "{}_secret_codes".format(self.manifest.package()): secret_codes
        }
Esempio n. 24
0
    def run(self):
        result = {
            "title": "Application Does Not Check If A Passcode Is Set",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self._regex, symbols)
        if not matches:
            result.update({
                "report":
                True,
                "details":
                "No evidence of checking for passcode set found."
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 25
0
    def run(self):
        Log.info("Preparing to sign the application")

        binaries_local_path = "{}/bin/android".format(_SCROUNGER_HOME)
        signjar = "{}/signapk.jar".format(binaries_local_path)
        key = "{}/key.pk8".format(binaries_local_path)
        cert = "{}/cert.x509.pem".format(binaries_local_path)

        # get identifier
        identifier = self.recompiled_apk.rsplit("/",1)[-1].rsplit(".", 1)[0]
        signed_apk = "{}/{}-signed.apk".format(self.output, identifier)

        # sign
        Log.info("Signinging application")
        output = sign(self.recompiled_apk, signed_apk, signjar, cert, key)

        if output and "Exception" in output:
            return {
                "print": "Failed to sign the application:\n{}".format(output)
            }

        return {
            "{}_signed".format(identifier): signed_apk,
            "print": "Application signed to {}".format(signed_apk)
        }
Esempio n. 26
0
    def run(self):
        result = {
            "title": "Application Uses Weak Random Functions",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self._regex, symbols)
        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following evidence were found:\n* {}".format("\n* ".join(
                    sorted(set(matches))))
            })

        return {"{}_result".format(self.name()): result}
    def run(self):
        result = {
            "title":
            "Application's Providers Are Vulnerable To Path Traversal",
            "details": "",
            "severity": "High",
            "report": False
        }

        Log.info("Extracting and translating providers")
        providers = parsed_providers(self.decompiled_apk)

        Log.info("Analysing providers")

        vulnerable_providers = []
        example_result = None
        for provider in providers:
            exec_result = self.device.read_provider(provider,
                                                    self.exploit_path)

            if exec_result and "Exception" not in exec_result:
                vulnerable_providers += [provider]
                example_result = exec_result

        if vulnerable_providers:
            details = "* Vulnerable Providers:\n* {}".format(
                "\n* ".join(vulnerable_providers))
            details += "\n\nAn example of exploitation success:\n{}".format(
                example_result)

            result.update({"report": True, "details": details})

        return {"{}_result".format(self.name()): result}
Esempio n. 28
0
    def run(self):
        result = {
            "title": "Application Allows Backups",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        manifest = manifest_module.run()
        if "print" in manifest:
            return {"print": "Could not get the manifest"}

        manifest = manifest.popitem()[1]

        Log.info("Analysing application's manifest")

        if manifest.allow_backup():
            result.update({"report": True})

        return {
            "{}_result".format(self.name()): result
        }
Esempio n. 29
0
    def run(self):
        result = {
            "title": "Application Allows Files To Be Backed Up",
            "details": "",
            "severity": "Low",
            "report": False
        }

        Log.info("Checking if the application is installed")
        installed_apps = self.device.apps()

        if self.identifier not in installed_apps:
            return {"print": "Application not installed."}

        remote_data_path = installed_apps[self.identifier]["data"]

        files = self.device.find_files(remote_data_path)

        report_files = []
        for file_path in files:
            if file_path:
                protection = self.device.backup_flag(file_path)
                if protection and "0" in protection:
                    report_files += [file_path]

        if report_files:
            result.update({
                "report":
                True,
                "details":
                "The following files were found to have the \
backup flag:\n* {}".format("\n* ".join(report_files))
            })

        return {"{}_result".format(self.name()): result}
Esempio n. 30
0
    def run(self):
        result = {
            "title": "Application Logs To Syslog",
            "details": "",
            "severity": "Low",
            "report": True
        }

        Log.info("Getting executable's name")

        info_module = InfoModule()
        info_module.identifier = self.identifier
        info_module.device = self.device
        info_result, info = info_module.run(), None
        for key in info_result:
            if key.endswith("_info"):
                info = info_result[key]

        if not info:
            return {"print": "Couldn't get Info from device."}

        executable_name = info["CFBundleExecutable"]

        Log.info("Getting application's logs")
        logs = self.device.logs(executable_name)

        if logs:
            result.update({
                "report":
                True,
                "details":
                "The following logs were found:\n{}".format(logs)
            })

        return {"{}_result".format(self.name()): result}