Beispiel #1
0
def axml(input_, output, file_, resource):
    """
    Parse the AndroidManifest.xml.

    Parsing is either direct or from a given APK and prints in XML format or
    saves to file.

    This tool can also be used to process any AXML encoded file, for example
    from the layout directory.

    Example:

    \b
        $ androguard axml AndroidManifest.xml
    """
    if file_ is not None and input_ is not None:
        print("Can not give --input and positional argument! "
              "Please use only one of them!")
        sys.exit(1)

    if file_ is None and input_ is None:
        print("Give one file to decode!")
        sys.exit(1)

    if file_ is not None:
        androaxml_main(file_, output, resource)
    elif input_ is not None:
        androaxml_main(input_, output, resource)
Beispiel #2
0
def axml(input_, output, file_, resource):
    """
    Parse the AndroidManifest.xml.

    Parsing is either direct or from a given APK and prints in XML format or
    saves to file.

    This tool can also be used to process any AXML encoded file, for example
    from the layout directory.

    Example:

    \b
        $ androguard axml AndroidManifest.xml
    """
    if file_ is not None and input_ is not None:
        print("Can not give --input and positional argument! "
              "Please use only one of them!")
        sys.exit(1)

    if file_ is None and input_ is None:
        print("Give one file to decode!")
        sys.exit(1)

    if file_ is not None:
        androaxml_main(file_, output, resource)
    elif input_ is not None:
        androaxml_main(input_, output, resource)
Beispiel #3
0
def analyze(path):
    try:
        start = process_time()
        hashfunctions = dict(md5=hashlib.md5,
                             sha1=hashlib.sha1,
                             sha256=hashlib.sha256,
                             sha512=hashlib.sha512)
        a = APK(path)

        certs = set(
            a.get_certificates_der_v3() + a.get_certificates_der_v2() +
            [a.get_certificate_der(x) for x in a.get_signature_names()])

        for cert in certs:
            x509_cert = x509.Certificate.load(cert)

            issuer = {
                'commonName': None,
                'organizationName': None,
                'organizationalUnitName': None,
                'countryName': None,
                'stateOrProvinceName': None,
                'localityName': None
            }
            subject = {
                'commonName': None,
                'organizationName': None,
                'organizationalUnitName': None,
                'countryName': None,
                'stateOrProvinceName': None,
                'localityName': None
            }

            strIssuer = get_certificate_name_string(x509_cert.issuer,
                                                    short=False)
            strSubject = get_certificate_name_string(x509_cert.subject,
                                                     short=False)

            arrIssuer = strIssuer.split(',')
            for i in arrIssuer:
                if i.lstrip().split('=')[0] == 'commonName':
                    issuer['commonName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationName':
                    issuer['organizationName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationalUnitName':
                    issuer['organizationalUnitName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'countryName':
                    issuer['countryName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'stateOrProvinceName':
                    issuer['stateOrProvinceName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'localityName':
                    issuer['localityName'] = i.lstrip().split('=')[1]

            arrSubject = strSubject.split(',')
            for i in arrSubject:
                if i.lstrip().split('=')[0] == 'commonName':
                    subject['commonName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationName':
                    subject['organizationName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationalUnitName':
                    subject['organizationalUnitName'] = i.lstrip().split(
                        '=')[1]
                elif i.lstrip().split('=')[0] == 'countryName':
                    subject['countryName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'stateOrProvinceName':
                    subject['stateOrProvinceName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'localityName':
                    subject['localityName'] = i.lstrip().split('=')[1]

            for k, v in hashfunctions.items():
                if k == 'md5':
                    md5 = v(cert).hexdigest()
                elif k == 'sha1':
                    sha1 = v(cert).hexdigest()
                elif k == 'sha256':
                    sha256 = v(cert).hexdigest()
                elif k == 'sha512':
                    sha512 = v(cert).hexdigest()

        md5 = md5

        appName = a.get_app_name()
        fileSize = os.stat(a.get_filename()).st_size
        sha1 = sha1
        sha256 = sha256
        sha512 = sha512
        timestamp = time.time()
        dateTime = datetime.fromtimestamp(timestamp)
        timeOfSubmit = dateTime.strftime("%Y-%m-%d %H:%M:%S")
        package = a.get_package()
        androidversionCode = a.get_androidversion_code()
        androidversionName = a.get_androidversion_name()
        minSDKVersion = a.get_min_sdk_version()
        maxSDKVersion = a.get_max_sdk_version()
        targetSDKVersion = a.get_target_sdk_version()
        mainActivity = a.get_main_activity()

        attributes = {
            'validFrom':
            x509_cert['tbs_certificate']['validity']
            ['not_before'].native.strftime("%Y-%m-%d %H:%M:%S"),
            'validTo':
            x509_cert['tbs_certificate']['validity']
            ['not_after'].native.strftime("%Y-%m-%d %H:%M:%S"),
            'serialNumber':
            hex(x509_cert.serial_number),
            'hashAlgorithm':
            x509_cert.hash_algo,
            'signatureAlgorithm':
            x509_cert.signature_algo
        }

        certificateAttributes = json.dumps(attributes)
        certificateIssuer = json.dumps(issuer)
        certificateSubject = json.dumps(subject)

        declaredPermissions = json.dumps(a.get_declared_permissions())

        requestedPermissions = json.dumps(a.get_permissions())

        activities = json.dumps(a.get_activities())

        services = json.dumps(a.get_services())

        receivers = json.dumps(a.get_receivers())

        providers = json.dumps(a.get_providers())

        stop = process_time()
        analysisTime = stop - start

        connect = mysql.connect()
        cursor = connect.cursor()

        sql = "INSERT INTO tbl_apkinfo (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, firstSubmission, lastSubmission, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject,	declaredPermissions, requestedPermissions, activities, services, providers, receivers) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
        param = (md5, appName, fileSize, analysisTime, sha1, sha256, sha512,
                 timeOfSubmit, timeOfSubmit, package, androidversionCode,
                 androidversionName, minSDKVersion, maxSDKVersion,
                 targetSDKVersion, mainActivity, certificateAttributes,
                 certificateIssuer, certificateSubject, declaredPermissions,
                 requestedPermissions, activities, services, providers,
                 receivers)
        cursor.execute(sql, param)

        connect.commit()
        connect.close()

        androaxml_main(path,
                       os.path.join(app.config['OUTPUT_PATH'], md5 + '.xml'))
        return True
    except:
        return False
    def disassemble(self):
        """
        Disassembles the sample (as much as possible), and if the end-user is interested in output (clear unset)
        also decompiles it (as much as possible).
        
        APK: 
                java -jar apktool.jar [-q] d file.apk outdir/apktool
                if apktool failed
                      java -jar baksmali.jar -o outdir/smali classes.dex in file.apk
                      androaxml.py --input binary-manifest in file.apk --output outdir/AndroidManifest.text.xml
                if clear unset,
                      unzip file.apk -d outdir/unzipped
                else
                      just unzip META-INF/

        DEX:
                java -jar baksmali.jar -o outdir/smali classes.dex
                if clear unset,
                      make sure classes.dex is readable
                      dex2jar classes.dex -o classes-dex2jar.jar
                      unzip -qq classes-dex2jar.jar -d outdir/unjarred
                      procyon classes-dex2jar.jar -o outdir/procyon

        What we'll find:
        APK, clear unset: ./smali AndroidManifest.xml ./unzipped classes.dex classes-dex2jar.jar ./unjarred ./procyon
        APK, clear set  : ./smali AndroidManifest.xml classes.dex

        DEX, clear unset: classes.dex ./smali
        DEX, clear set  : classes.dex ./smali classes-dex2jar.jar ./unjarred ./procyon

        """
        if self.verbose:
            print("------------- Disassembling")

        if self.properties.filetype == droidutil.ARM or \
                self.properties.filetype == droidutil.RAR or \
                self.properties.filetype == droidutil.CLASS or \
                self.properties.filetype == droidutil.UNKNOWN:
            # TODO: we could be running procyon on a class file.
            if self.verbose:
                print("Nothing to disassemble for " + self.absolute_filename)
            return

        if self.properties.filetype == droidutil.APK:
            # APKTOOL won't output to an existing dir unless you use the -f switch. But then, -f erases the contents
            # of the output dir... So we can't do this directly on self.outdir
            apktool_outdir = os.path.join(self.outdir, "apktool")
            if self.verbose:
                print("Running apktool on inputfile=" + self.absolute_filename)

            if self.verbose:
                print("Apktool command: java -jar %s d -f %s %s" %
                      (droidconfig.APKTOOL_JAR, self.absolute_filename,
                       apktool_outdir))
                subprocess.call(["java", "-jar", droidconfig.APKTOOL_JAR, \
                                 "d", "-f", self.absolute_filename,  \
                                 "-o", apktool_outdir ])
            else:
                # with quiet option
                subprocess.call(["java", "-jar", droidconfig.APKTOOL_JAR, \
                                 "-q", "d", "-f", self.absolute_filename,  \
                                 "-o", apktool_outdir ], stdout=self.process_output, stderr=self.process_output)

            if self.verbose:
                print("Apktool finished")

            if os.path.isdir(apktool_outdir):
                droidutil.move_dir(apktool_outdir, self.outdir)

            # extract classes.dex whatever happens, we'll use it
            if self.verbose:
                print("Extracting classes.dex")
            try:
                self.ziprar.extract_one_file('classes.dex', self.outdir)
            except:
                if self.verbose:
                    print("Extracting classes.dex failed: %s" %
                          (sys.exc_info()[0]))
                else:
                    print("Extracting classes.dex failed")

        # Disassemble the DEX
        if self.properties.filetype == droidutil.DEX:
            dex_file = self.absolute_filename
        else:
            dex_file = os.path.join(self.outdir, 'classes.dex')

        smali_dir = os.path.join(self.outdir, 'smali')

        if (not os.access( smali_dir, os.R_OK) or \
                (os.access(smali_dir, os.R_OK) and not os.listdir(smali_dir)) \
                and os.access( dex_file, os.R_OK)):
            if self.verbose:
                print("Using baksmali on " + dex_file)
            try:
                subprocess.call( [ "java", "-jar", droidconfig.BAKSMALI_JAR, \
                                   "d", "-o", smali_dir, dex_file ], \
                                 stdout=self.process_output, stderr=self.process_output)
            except:
                print("Baksmali failed")

        # Decompile the DEX
        if self.verbose:
            print("------------- Decompiling")

        if not self.clear and os.access(dex_file, os.R_OK):
            jar_file = os.path.join(self.outdir, 'classes-dex2jar.jar')
            if self.verbose:
                print("Dex2jar on " + dex_file)
            subprocess.call( [ droidconfig.DEX2JAR_CMD, "--force", dex_file, "-o", jar_file ], \
                                 stdout=self.process_output, stderr=self.process_output)
            if os.access(jar_file, os.R_OK):
                if self.enable_procyon:
                    if self.verbose:
                        print("Procyon decompiler on " + jar_file)
                    subprocess.call( [ "java", "-jar", droidconfig.PROCYON_JAR, \
                                           jar_file, "-o", os.path.join(self.outdir, 'procyon') ], \
                                         stdout=self.process_output, stderr=self.process_output)
                if self.verbose:
                    print("Unjarring " + jar_file)
                jarziprar = droidziprar.droidziprar(jar_file,
                                                    zipmode=True,
                                                    verbose=self.verbose)
                if jarziprar.handle == None:
                    if self.verbose:
                        print("Bad Jar / Failed to unjar " + jar_file)
                else:
                    try:
                        jarziprar.extract_all(
                            os.path.join(self.outdir, 'unjarred'))
                    except:
                        print("Failed to unjar: %s" % (sys.exc_info()[0]))
                    jarziprar.close()

        # Convert binary Manifest
        if self.properties.filetype == droidutil.APK:
            manifest = os.path.join(self.outdir, 'AndroidManifest.xml')
            if not os.access(manifest,
                             os.R_OK) or os.path.getsize(manifest) == 0:
                if self.verbose:
                    print("Extracting binary AndroidManifest.xml")
                try:
                    self.ziprar.extract_one_file('AndroidManifest.xml',
                                                 self.outdir)
                except:
                    print("Failed to extract binary manifest: %s" %
                          (sys.exc_info()[0]))
                if os.access(manifest,
                             os.R_OK) and os.path.getsize(manifest) > 0:
                    textmanifest = os.path.join(self.outdir,
                                                'AndroidManifest.text.xml')
                    androaxml_main(manifest, textmanifest)
                    if os.access(textmanifest, os.R_OK):
                        # overwrite the binary manifest with the converted text one
                        os.rename(textmanifest, manifest)