def process_apk(self, data, name): """ Processes Android application :param data: :param name: :return: """ from cryptography.x509.base import load_pem_x509_certificate from apk_parse.apk import APK try: apkf = APK(data, process_now=False, process_file_types=False, raw=True, temp_dir=self.args.tmp_dir) apkf.process() self.num_apk += 1 pem = apkf.cert_pem aux = {'subtype': 'apk'} x509 = load_pem_x509_certificate(pem, self.get_backend()) self.process_x509(x509, name=name, idx=0, data=data, pem=True, source='apk-pem-cert', aux=aux) except Exception as e: logger.debug('Exception in processing JSON %s : %s' % (name, e)) self.trace_logger.log(e)
def extraction(apk_path, file): t = "<sep>" apkf = APK(apk_path) f = open("train.csv", 'a') f.write(file + t) f.write(str(apkf.cert_text) + t) f.write(str(apkf.file_md5) + t) f.write(str(apkf.cert_md5) + t) f.write(str(apkf.file_size) + t) f.write(str(apkf.androidversion) + t) f.write(str(apkf.package) + t) f.write(str(apkf.get_android_manifest_xml()) + t) f.write(str(apkf.get_android_manifest_axml()) + t) f.write(str(apkf.is_valid_APK()) + t) f.write(str(apkf.get_filename()) + t) f.write(str(apkf.get_package()) + t) f.write(str(apkf.get_androidversion_code()) + t) f.write(str(apkf.get_androidversion_name()) + t) f.write(str(apkf.get_max_sdk_version()) + t) f.write(str(apkf.get_min_sdk_version()) + t) f.write(str(apkf.get_target_sdk_version()) + t) f.write(str(apkf.get_libraries()) + t) f.write(str(apkf.get_files()) + t) f.write(str(apkf.get_files_types()) + t) f.write(str(apkf.get_main_activity()) + t) f.write(str(apkf.get_activities()) + t) f.write(str(apkf.get_services()) + t) f.write(str(apkf.get_receivers()) + t) f.write(str(apkf.get_providers()) + t) f.write(str(apkf.get_permissions())) f.write("<new>")
def __init__(self, project_dir, apk_dir, config_location): self.project_dir = project_dir self.apk_dir = apk_dir self.apkf = APK(apk_dir) self.manifestDict = extractXML(apk_dir, config_location) self.gradleDict = gr.GradleParserNew(self.project_dir + "/app").parse(False)
def isMalware(self, url): # Preprocess to remove query information to get absolute url link o = urlparse(url) apk_url = o.scheme + "://" + o.netloc + o.path # Check whether it is valid APK path = urlparse(apk_url).path if os.path.splitext(path)[1] != '.apk': return EXIT_CODES.index('NotValid') # business logic here #download apk file and parse it download_apk = APK_Download(apk_url) if download_apk is None: return EXIT_CODES.index('NotValid') apk_file = APK(download_apk) try: if checkUrlRecord(apk_url) is True: return EXIT_CODES.index('isMalware') if checkNameandSizeRecord(apk_file.filename, apk_file.file_size) is True: insertAPK(apk_file.file_md5, apk_file.filename, apk_file.file_size, apk_url) return EXIT_CODES.index('isMalware') if checkMD5Record(apk_file.file_md5) is True: insertAPK(apk_file.file_md5, apk_file.filename, apk_file.file_size, apk_url) return EXIT_CODES.index('isMalware') except Exception as e: return EXIT_CODES.index('DB_no_connection') ''' Virus Total Check ''' vt_instance = VirusTotalPublicApi(API_KEY) self.__throttle_virustotal_api_call() #Submit file to Virus Total for scan scan_status = self.__virustotal_scan_submit(apk_file, vt_instance) if scan_status in EXIT_CODES: return scan_status scan_id = scan_status ret = self.__virustotal_scan_check(apk_file, vt_instance, scan_id) if ret is not None: if ret is EXIT_CODES.index('isMalware'): insertAPK(apk_file.file_md5, apk_file.filename, apk_file.file_size, apk_url) return ret return EXIT_CODES.index('isClean')
def main(): # Parse command line arguments parser = argparse.ArgumentParser( description='Extracts Signing information from the APK') parser.add_argument('files', nargs=argparse.ZERO_OR_MORE, default=[], help='APK files') parser.add_argument('--der', dest='der', default=False, action='store_const', const=True, help='DER only') args = parser.parse_args() for file_name in args.files: apkf = APK(file_name) pem = apkf.cert_pem der = apkf.pkcs7_der if args.der: sys.stdout.write(der) return print(pem) print(apkf.cert_text) p7 = PKCS7.from_der(der) try: signed_date, valid_from, valid_to, signer = p7.get_timestamp_info() print('Sign date: %s = %s' % (utils.unix_time_millis(signed_date), utils.fmt_time(signed_date))) print('Sign not before: %s = %s' % (utils.unix_time_millis(valid_from), utils.fmt_time(valid_from))) print('Sign not after: %s = %s' % (utils.unix_time_millis(valid_to), utils.fmt_time(valid_to))) print('Signer: %s' % str(signer)) except Exception as e: logger.error('Error parsing signer info: %s' % e) if not isinstance(p7.content, PKCS7_SignedData): logger.info('Not a PKCS7 signed data') print('Signer info cnt: %s' % len(p7.content.signerInfos)) if len(p7.content.signerInfos) > 0: signer_info = p7.content.signerInfos[0] print('Signer serial: %s' % signer_info.serial_number) print('Sign issuer: %s' % signer_info.issuer) print('Sign algorithm: %s' % signer_info.oid2name(signer_info.digest_algorithm))
def get_feature(apk_path): try: apkf = APK(apk_path) x_feature = "" x_feature = x_feature + str(apkf.file_size) + sep x_feature = x_feature + str(apkf.get_max_sdk_version()) + sep x_feature = x_feature + str(apkf.get_min_sdk_version()) + sep x_feature = x_feature + str(apkf.get_target_sdk_version()) + sep x_feature = x_feature + str(apkf.androidversion) + sep x_feature = x_feature + str(apkf.get_activities()) + sep x_feature = x_feature + str(apkf.get_services()) + sep x_feature = x_feature + str(apkf.get_receivers()) + sep x_feature = x_feature + str(apkf.get_providers()) + sep x_feature = x_feature + str(apkf.get_permissions()) + "\n" f.write(x_feature) except: pass
def main(): # Parse command line arguments parser = argparse.ArgumentParser( description='Extracts RSA modulus as a hexa string from APK files') parser.add_argument('files', nargs=argparse.ZERO_OR_MORE, default=[], help='APK files') args = parser.parse_args() for file_name in args.files: apkf = APK(file_name) pem = apkf.cert_pem x509 = load_x509(pem) pub = x509.public_key() n = pub.public_numbers().n print('%x' % n)
def test(): if len(sys.argv) == 1: print('Usage: %s app.apk' % sys.argv[0]) sys.exit(1) apk_path = sys.argv[1] # Parsing xapks. apkf = APK(apk_path, process_now=False, process_file_types=False, as_file_name=True) apkf.file_md5 = 'skip' apkf.process() print(apkf.file_md5) print(apkf.file_size) print(apkf.cert_md5) print(apkf.cert_text) print(apkf.cert_pem)
def test(): if len(sys.argv) == 1: print('Usage: %s app.apk' % sys.argv[0]) sys.exit(1) apk_path = sys.argv[1] apkf = APK(apk_path) print(apkf.cert_text) print(apkf.cert_pem) print(apkf.file_md5) print(apkf.cert_md5) print(apkf.file_size) print(apkf.androidversion) print(apkf.package) print(apkf.get_android_manifest_xml()) print(apkf.get_android_manifest_axml()) print(apkf.is_valid_APK()) print(apkf.get_filename()) print(apkf.get_package()) print(apkf.get_androidversion_code()) print(apkf.get_androidversion_name()) print(apkf.get_max_sdk_version()) print(apkf.get_min_sdk_version()) print(apkf.get_target_sdk_version()) print(apkf.get_libraries()) print(apkf.get_files()) # pip install python-magic print(apkf.get_files_types()) # print(apkf.get_dex()) print(apkf.get_main_activity()) print(apkf.get_activities()) print(apkf.get_services()) print(apkf.get_receivers()) print(apkf.get_providers()) print(apkf.get_permissions()) print(binascii.hexlify(apkf.get_signature())) print(apkf.get_signature_name()) print apkf.show()
def get_permission_info(PATH): filenames = os.listdir(PATH) get_permission = {} my_list = [0 for i in range(len(permission_v2))] for filename in filenames: # add permission list 11/12 my_list = [0 for i in range(len(permission_v2))] full_path = PATH + "/" + filename apkf = APK(full_path) permission_list = [] count = 0 for i in apkf.get_permissions(): permission_list.append(i.split(".")[-1]) for i in permission_list: if i in permission_v2: my_list[permission_v2.index(i)]=1 count += 1 my_list.append(count) get_permission[filename[:-4]]= my_list return get_permission
def main(): # Parse command line arguments parser = argparse.ArgumentParser( description='Extracts PEM certificates from APK files') parser.add_argument('files', nargs=argparse.ZERO_OR_MORE, default=[], help='APK files') parser.add_argument('-t', dest='text', default=False, action='store_const', const=True, help='show also text representation') args = parser.parse_args() for file_name in args.files: apkf = APK(file_name) if args.text: print(apkf.cert_text) pem = apkf.cert_pem print(pem)
def apk_info(self): return APK(self.file)
def main(): path = sys.argv[1] malicious = sys.argv[2] result = {} if not os.path.exists(path): return False, "File is not exists" apk = APK(path) if not apk.is_valid_APK(): return False, "APK file is wrong" result = {} ### APK File Info result['Apk'] = {} result['Apk']['path'] = path result['Apk']['malicious'] = malicious result['Apk']['md5'] = apk.file_md5 result['Apk']['sha256'] = apk.file_sha256 result['Apk']['size'] = apk.file_size result['Apk']['magic'] = magic.Magic().from_file(path) result['Apk']['icon_files'] = apk.get_icon_files() ### Certificate Information result['Certificate'] = {} result['Certificate']['md5'] = apk.cert_md5 result['Certificate']['text'] = apk.cert_text ### AndroidManifiest.xml Information result['AndroidManifest'] = {} result['AndroidManifest'][ 'androidversion_code'] = apk.get_androidversion_code() result['AndroidManifest'][ 'androidversion_name'] = apk.get_androidversion_name() result['AndroidManifest']['min_sdk_version'] = apk.get_min_sdk_version() result['AndroidManifest'][ 'target_sdk_version'] = apk.get_target_sdk_version() result['AndroidManifest']['libraries'] = apk.get_libraries() result['AndroidManifest']['main_activitiy'] = apk.get_main_activity() result['AndroidManifest']['activities'] = {} for activity in apk.get_activities(): result['AndroidManifest']['activities'][ activity] = apk.get_intent_filters('activity', activity) result['AndroidManifest']['services'] = {} for service in apk.get_services(): result['AndroidManifest']['services'][ service] = apk.get_intent_filters('service', service) result['AndroidManifest']['receivers'] = {} for receiver in apk.get_receivers(): result['AndroidManifest']['receivers'][ receiver] = apk.get_intent_filters('receiver', receiver) result['AndroidManifest']['permissions'] = {} for permission in apk.get_permissions(): result['AndroidManifest']['permissions'][ permission] = apk.get_intent_filters('permission', permission) result['AndroidManifest']['providers'] = apk.get_providers() ### APK File Information and File Magic Data result['Files'] = {} image_extension_list = ['png', 'jpeg', 'jpg', 'gif'] image_magic_list = ['PNG image data', 'JPEG image data'] for file in apk.get_files(): result['Files'][file] = {} fileData = apk.get_file(filename=file) result['Files'][file]['icon'] = False result['Files'][file]['size'] = len(fileData) result['Files'][file]['md5'] = hashlib.md5(fileData).hexdigest() result['Files'][file]['sha256'] = hashlib.sha256(fileData).hexdigest() result['Files'][file]['magic'] = magic.Magic().from_buffer(fileData) result['Files'][file]['file_name'] = None result['Files'][file]['file_extension'] = None result['Files'][file]['image_resource'] = False if '/' in file: result['Files'][file]['file_name'] = file.split('/')[-1] else: result['Files'][file]['file_name'] = file if '.' in result['Files'][file]['file_name']: result['Files'][file]['file_extension'] = result['Files'][file][ 'file_name'].split('.')[-1].lower() if file in apk.get_icon_files(): result['Files'][file]['icon'] = True if result['Files'][file]['file_extension'] in image_extension_list: result['Files'][file]['image_resource'] = get_image_resource( file_magic=result['Files'][file]['magic'], image_magic_list=image_magic_list) if get_image_resource( file_magic=result['Files'][file]['magic'], image_magic_list=image_magic_list) and result['Files'][file][ 'file_extension'] not in image_extension_list: continue #print "[+] This file is strange %s %s" % (file, result['Files'][file]['magic']) fd = open('./temp/' + file.replace('/', '_'), 'wb') fd.write(apk.get_file(file)) fd.close() ### decompile proc = subprocess.Popen(['java', '-jar', 'apktool_2.3.0.jar', 'd', path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() if '/' in path: path = path.split('/')[-1] result['Class'] = {} for root, dirs, files in os.walk('./' + path + '.out' + os.sep + 'smali'): for file in files: filepath = root + os.sep + file className = filepath.split('/smali/')[-1].split( '.smali')[0].replace('/', '.') result['Class'][className] = {} result['Class'][className]['Method'] = {} result['Class'][className]['interfaces'] = [] result['Class'][className]['Fields'] = [] fd = open(filepath, 'rb') data = fd.read() fd.close() index = 0 for line in data.split('\n'): if not line: continue line = line.strip() if line.startswith('.super '): result['Class'][className]['super_class'] = line[ 8:-1].replace('/', '.') #print result['Class'][className]['super_class'] elif line.startswith('.method '): ### Method Info try: methodName, parameters, returnType = re.search( '\.method\s.+\s(.+)\((.*)\)(.+)', line).groups() except AttributeError: methodName, parameters, returnType = re.search( '\.method\s(.+)\((.*)\)(.+)', line).groups() result['Class'][className]['Method'][methodName] = {} result['Class'][className]['Method'][methodName][ 'parameters'] = [] result['Class'][className]['Method'][methodName][ 'strings'] = [] result['Class'][className]['Method'][methodName][ 'call-api'] = [] result['Class'][className]['Method'][methodName][ 'returnType'] = None result['Class'][className]['Method'][methodName][ 'flags'] = None #if returnType not in ['Z','B','C','D','F','I','J','V']: # print line, returnType # raw_input() ### Method Parameter for parameter in parameters.split(';'): result['Class'][className]['Method'][methodName][ 'parameters'].append(parameter[1:].replace( '/', '.')) if returnType == 'Z': returnType = 'boolean' elif returnType == 'B': returnType = 'byte' elif returnType == 'C': returnType = 'char' elif returnType == 'D': returnType = 'double' elif returnType == 'F': returnType = 'float' elif returnType == 'I': returnType = 'int' elif returnType == 'J': returnType == 'long' elif returnType == 'V': returnType = 'void' elif returnType.startswith('L') and returnType.endswith( ';'): returnType = returnType[1:-1].replace('/', '.') result['Class'][className]['Method'][methodName][ 'returnType'] = returnType #if '[' in returnType: elif line.startswith('const-string'): result['Class'][className]['Method'][methodName][ 'strings'].append( re.search('\"(.*)\"', line).groups()[0]) ### target = {'class', 'method', 'parameters' = []} elif line.startswith('invoke-virtual') or line.startswith( 'invoke-static') or line.startswith( 'invoke-interfaces'): targetClass, targetMethod, targetMethodParameters, targetMethodReturnType = re.search( 'invoke\-.+\s\{.*\}\,\sL(.+)\-\>(.+)\((.*)\)(.*)', line).groups() target = {} target['class'] = targetClass target['mehtod'] = targetMethod target['parameters'] = [] if targetMethodParameters.count(';') > 1: for parameter in targetMethodParameters.split(';'): target['parameters'].append(parameter[1:].replace( '/', '.')) else: target['parameters'].append( targetMethodParameters.replace('/', '.')) result['Class'][className]['Method'][methodName][ 'call-api'].append(target) index += 1 shutil.rmtree('./' + path + '.out') return True, ""
cli.download_packages(pkg_arr) apk_file = "apk_files/" + package_name + ".apk" if not os.path.isfile(apk_file): print("Failed to download " + package_name + " from store.") sys.exit() elif file_path: apk_file = file_path report["package"] = package_name if apk_file is not None: # generate info print("[*] Collecting app info") apk_info = APK(apk_file) report["app_info"] = { "md5": apk_info.file_md5, "cert_md5": apk_info.cert_md5, "file_size": apk_info.file_size, "version_name": apk_info.get_androidversion_name(), "version_code": apk_info.get_androidversion_code(), "main_activity": apk_info.get_main_activity(), "activities": apk_info.get_activities(), "services": apk_info.get_services(), "receivers": apk_info.get_receivers(), "providers": apk_info.get_providers(), "permissions": apk_info.get_permissions(), "certificates": [] }
def main(): banner() for i in range(start, end): target = "bot/" + str(i) try: apkf = APK(target) md5 = apkf.file_md5 package = apkf.get_package() file_size = apkf.file_size andro_version = apkf.get_androidversion_name() libraries = apkf.get_libraries() main_activity = apkf.get_main_activity() activities = apkf.get_activities() services = apkf.get_services() files = apkf.get_files() permissions = apkf.get_permissions() counter_emails = 0 counter_urls = 0 counter_ftps = 0 all_emails = [] all_urls = [] all_ftps = [] print "----------------------------------------------" print colores.header + colores.underline + "[+][TARGET][>]" + package + " [" + str( i) + "]" + colores.normal print colores.header + "[-][md5][>] " + md5 print colores.header + "[-][Android version][>] " + andro_version print colores.green + "|----[>] " + "Searching emails and links in strings ..." + colores.normal strings = os.popen("strings " + target) for word in strings: #To found emails in strings if "@" in word: if word.find(".com") > 0 or word.find( ".es") > 0 or word.find(".eu") > 0 or word.find( ".net") > 0 or word.find( ".gob") > 0 or word.find( ".info") > 0 or word.find(".org") > 0: words = word.split(" ") for w in words: if word.find(".com") > 0 or word.find( ".es" ) > 0 or word.find(".eu") > 0 or word.find( ".net" ) > 0 or word.find(".gob") > 0 or word.find( ".info") > 0 or word.find(".org") > 0: counter_emails += 1 email = re.findall(r'[\w\.-]+@[\w\.-]+', word) if not email in all_emails: print colores.green + "|----[EMAIL][>] " + str( email) + colores.normal all_emails.append(email) #To found urls in strings if "http" in word or "wwww." in word: url = re.findall( 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', word) if not url in all_urls or url == "": all_urls.append(url) print colores.green + "|----[URL][>] " + str( url) + colores.normal #To found FTP in strings if "ftp" in word: ftp = re.findall( 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', word) if not ftp in all_ftps or ftp == "": all_ftps.append(ftp) print colores.green + "|----[FTP][>] " + str( ftp) + colores.normal except: continue insert_mongodb(i, package, md5, file_size, andro_version, main_activity, activities, services, permissions, all_urls, all_emails, all_ftps)