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)
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)
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)