[EFR05] Enterprise Feature Request: AAR and JAR support (#2163)

* AAR and JAR support
This commit is contained in:
Ajin Abraham
2023-04-17 12:02:02 -07:00
committed by GitHub
parent 0cd255cb90
commit b43b561a65
20 changed files with 419 additions and 150 deletions
-1
View File
@@ -15,7 +15,6 @@ Made with ![Love](https://cloud.githubusercontent.com/assets/4301109/16754758/82
[![MobSF tests](https://github.com/MobSF/Mobile-Security-Framework-MobSF/workflows/MobSF%20tests/badge.svg?branch=master)](https://github.com/MobSF/Mobile-Security-Framework-MobSF/actions)
[![Requirements Status](https://pyup.io/repos/github/MobSF/Mobile-Security-Framework-MobSF/shield.svg)](https://pyup.io/repos/github/MobSF/Mobile-Security-Framework-MobSF/)
[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/MobSF/Mobile-Security-Framework-MobSF.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/MobSF/Mobile-Security-Framework-MobSF/context:python)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=MobSF_Mobile-Security-Framework-MobSF&metric=alert_status)](https://sonarcloud.io/dashboard?id=MobSF_Mobile-Security-Framework-MobSF)
![GitHub closed issues](https://img.shields.io/github/issues-closed/MobSF/Mobile-Security-Framework-MobSF)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6392/badge)](https://bestpractices.coreinfrastructure.org/projects/6392)
+1 -1
View File
@@ -10,7 +10,7 @@ from mobsf.install.windows.setup import windows_config_local
logger = logging.getLogger(__name__)
VERSION = '3.6.5'
VERSION = '3.6.6'
BANNER = """
__ __ _ ____ _____ _____ __
| \/ | ___ | |__/ ___|| ___|_ _|___ / / /_
+3
View File
@@ -69,6 +69,8 @@ ALLOWED_EXTENSIONS = {
'.tar': 'application/x-tar',
'.apk': 'application/octet-stream',
'.ipa': 'application/octet-stream',
'.jar': 'application/java-archive',
'.aar': 'application/octet-stream',
}
# =============ALLOWED MIMETYPES=================
APK_MIME = [
@@ -76,6 +78,7 @@ APK_MIME = [
'application/vnd.android.package-archive',
'application/x-zip-compressed',
'binary/octet-stream',
'application/java-archive',
]
IPA_MIME = [
'application/iphone',
+11 -1
View File
@@ -29,7 +29,9 @@ class FileType(object):
or self.is_zip()
or self.is_ipa()
or self.is_appx()
or self.is_apks()):
or self.is_apks()
or self.is_jar()
or self.is_aar()):
return True
return False
@@ -45,6 +47,14 @@ class FileType(object):
return (self.file_type in settings.APK_MIME
and self.file_name_lower.endswith('.apk'))
def is_jar(self):
return (self.file_type in settings.APK_MIME
and self.file_name_lower.endswith('.jar'))
def is_aar(self):
return (self.file_type in settings.APK_MIME
and self.file_name_lower.endswith('.aar'))
def is_zip(self):
return (self.file_type in settings.ZIP_MIME
and self.file_name_lower.endswith('.zip'))
+4
View File
@@ -137,6 +137,10 @@ class Upload(object):
return scanning.scan_xapk()
elif self.file_type.is_apks():
return scanning.scan_apks()
elif self.file_type.is_jar():
return scanning.scan_jar()
elif self.file_type.is_aar():
return scanning.scan_aar()
elif self.file_type.is_zip():
return scanning.scan_zip()
elif self.file_type.is_ipa():
+53 -56
View File
@@ -31,7 +31,7 @@ def add_to_recent_scan(data):
logger.exception('Adding Scan URL to Database')
def handle_uploaded_file(content, typ):
def handle_uploaded_file(content, extension):
"""Write Uploaded File."""
md5 = hashlib.md5()
bfr = isinstance(content, io.BufferedReader)
@@ -47,7 +47,7 @@ def handle_uploaded_file(content, typ):
anal_dir = os.path.join(settings.UPLD_DIR, md5sum + '/')
if not os.path.exists(anal_dir):
os.makedirs(anal_dir)
with open(anal_dir + md5sum + typ, 'wb+') as destination:
with open(f'{anal_dir}{md5sum}{extension}', 'wb+') as destination:
if bfr:
content.seek(0, 0)
while chunk := content.read(8192):
@@ -63,87 +63,84 @@ class Scanning(object):
def __init__(self, request):
self.file = request.FILES['file']
self.file_name = request.FILES['file'].name
self.data = {
'analyzer': 'static_analyzer',
'status': 'success',
'hash': '',
'scan_type': '',
'file_name': self.file_name,
}
def scan_apk(self):
"""Android APK."""
md5 = handle_uploaded_file(self.file, '.apk')
data = {
'analyzer': 'static_analyzer',
'status': 'success',
'hash': md5,
'scan_type': 'apk',
'file_name': self.file_name,
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'apk'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Android APK')
return data
return self.data
def scan_xapk(self):
"""Android XAPK."""
md5 = handle_uploaded_file(self.file, '.xapk')
data = {
'analyzer': 'static_analyzer',
'status': 'success',
'hash': md5,
'scan_type': 'xapk',
'file_name': self.file_name,
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'xapk'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Android XAPK base APK')
return data
return self.data
def scan_apks(self):
"""Android Split APK."""
md5 = handle_uploaded_file(self.file, '.apk')
data = {
'analyzer': 'static_analyzer',
'status': 'success',
'hash': md5,
'scan_type': 'apks',
'file_name': self.file_name,
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'apks'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Android Split APK')
return data
return self.data
def scan_jar(self):
"""Java JAR file."""
md5 = handle_uploaded_file(self.file, '.jar')
self.data['hash'] = md5
self.data['scan_type'] = 'jar'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Java JAR')
return self.data
def scan_aar(self):
"""Android AAR file."""
md5 = handle_uploaded_file(self.file, '.aar')
self.data['hash'] = md5
self.data['scan_type'] = 'aar'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Android AAR')
return self.data
def scan_zip(self):
"""Android /iOS Zipped Source."""
md5 = handle_uploaded_file(self.file, '.zip')
data = {
'analyzer': 'static_analyzer',
'status': 'success',
'hash': md5,
'scan_type': 'zip',
'file_name': self.file_name,
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'zip'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Android/iOS Source Code')
return data
return self.data
def scan_ipa(self):
"""IOS Binary."""
md5 = handle_uploaded_file(self.file, '.ipa')
data = {
'analyzer': 'static_analyzer_ios',
'hash': md5,
'scan_type': 'ipa',
'file_name': self.file_name,
'status': 'success',
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'ipa'
self.data['analyzer'] = 'static_analyzer_ios'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of iOS IPA')
return data
return self.data
def scan_appx(self):
"""Windows appx."""
md5 = handle_uploaded_file(self.file, '.appx')
data = {
'analyzer': 'static_analyzer_windows',
'hash': md5,
'scan_type': 'appx',
'file_name': self.file_name,
'status': 'success',
}
add_to_recent_scan(data)
self.data['hash'] = md5
self.data['scan_type'] = 'appx'
self.data['analyzer'] = 'static_analyzer_windows'
add_to_recent_scan(self.data)
logger.info('Performing Static Analysis of Windows APP')
return data
return self.data
+3 -1
View File
@@ -64,7 +64,9 @@ class AndroidChecks(forms.Form):
('studio', 'studio'),
('java', 'java'),
('smali', 'smali'),
('apk', 'apk')))
('apk', 'apk'),
('jar', 'jar'),
('aar', 'aar')))
def clean_file(self):
"""Safe Extension."""
@@ -58,6 +58,7 @@ def cert_info(app_dir, app_file, man_dict):
manidat = ''
cert_info = ''
certlist = []
files = []
summary = {HIGH: 0, WARNING: 0, INFO: 0}
cert_path = os.path.join(app_dir, 'META-INF/')
@@ -68,8 +69,9 @@ def cert_info(app_dir, app_file, man_dict):
'sha256': hashlib.sha256,
'sha512': hashlib.sha512,
}
files = [f for f in os.listdir(
cert_path) if os.path.isfile(os.path.join(cert_path, f))]
if os.path.exists(cert_path):
files = [f for f in os.listdir(
cert_path) if os.path.isfile(os.path.join(cert_path, f))]
a = APK(apk_file)
if a.is_signed():
certlist.append('APK is signed')
@@ -2,9 +2,9 @@
"""Generate Zipped downloads."""
import logging
import os
import re
import shutil
from pathlib import Path
from django.conf import settings
from django.shortcuts import redirect
@@ -15,39 +15,43 @@ logger = logging.getLogger(__name__)
def run(request):
"""Generate downloads for apk, java and smali."""
"""Generate downloads for apk, jar, aar, java zip and smali zip."""
try:
allowed = ('apk', 'smali', 'java', 'jar', 'aar')
logger.info('Generating Downloads')
md5 = request.GET['hash']
file_type = request.GET['file_type']
match = re.match('^[0-9a-f]{32}$', md5)
if not match and file_type not in ['apk', 'smali', 'java']:
logger.exception('Invalid options')
return print_n_send_error_response(request,
'Invalid options')
app_dir = os.path.join(settings.UPLD_DIR, md5)
if (not match
or file_type not in allowed):
msg = 'Invalid download type or hash'
logger.exception(msg)
return print_n_send_error_response(request, msg)
app_dir = Path(settings.UPLD_DIR) / md5
dwd_dir = Path(settings.DWD_DIR)
file_name = ''
if file_type == 'java':
# For Java
file_name = md5 + '-java'
directory = os.path.join(app_dir, 'java_source/')
dwd_dir = os.path.join(settings.DWD_DIR, file_name)
shutil.make_archive(dwd_dir, 'zip', directory)
file_name = file_name + '.zip'
# For Java zipped source code
directory = app_dir / 'java_source'
dwd_file = dwd_dir / f'{md5}-java'
shutil.make_archive(
dwd_file.as_posix(), 'zip', directory.as_posix())
file_name = f'{md5}-java.zip'
elif file_type == 'smali':
# For Smali
file_name = md5 + '-smali'
directory = os.path.join(app_dir, 'smali_source/')
dwd_dir = os.path.join(settings.DWD_DIR, file_name)
shutil.make_archive(dwd_dir, 'zip', directory)
file_name = file_name + '.zip'
elif file_type in ('apk', 'ipa'):
# For Smali zipped source code
directory = app_dir / 'smali_source'
dwd_file = dwd_dir / f'{md5}-smali'
shutil.make_archive(
dwd_file.as_posix(), 'zip', directory.as_posix())
file_name = f'{md5}-smali.zip'
elif file_type in ('apk', 'ipa', 'jar', 'aar'):
# Binaries
file_name = f'{md5}.{file_type}'
src = os.path.join(app_dir, file_name)
dst = os.path.join(settings.DWD_DIR, file_name)
shutil.copy2(src, dst)
return redirect('/download/' + file_name)
src = app_dir / file_name
dst = dwd_dir / file_name
shutil.copy2(src.as_posix(), dst.as_posix())
return redirect(f'/download/{file_name}')
except Exception:
logger.exception('Generating Downloads')
return print_n_send_error_response(request,
'Generating Downloads')
msg = 'Generating Downloads'
logger.exception(msg)
return print_n_send_error_response(request, msg)
@@ -0,0 +1,249 @@
"""Handle JAR and AAR files."""
import logging
from django.conf import settings
from django.shortcuts import render
import mobsf.MalwareAnalyzer.views.Trackers as Trackers
import mobsf.MalwareAnalyzer.views.VirusTotal as VirusTotal
from mobsf.MobSF.utils import (
file_size,
print_n_send_error_response,
)
from mobsf.StaticAnalyzer.views.common.shared_func import (
firebase_analysis,
get_avg_cvss,
hash_gen,
unzip,
update_scan_timestamp,
)
from mobsf.StaticAnalyzer.views.common.appsec import (
get_android_dashboard,
)
from mobsf.StaticAnalyzer.views.android.manifest_analysis import (
get_manifest,
manifest_analysis,
manifest_data,
)
from mobsf.StaticAnalyzer.views.android.strings import strings_from_apk
from mobsf.StaticAnalyzer.views.android.cert_analysis import (
cert_info,
get_hardcoded_cert_keystore,
)
from mobsf.StaticAnalyzer.models import (
StaticAnalyzerAndroid,
)
from mobsf.StaticAnalyzer.views.android.code_analysis import code_analysis
from mobsf.StaticAnalyzer.views.android.converter import (
apk_2_java,
)
from mobsf.StaticAnalyzer.views.android.db_interaction import (
get_context_from_analysis,
get_context_from_db_entry,
save_or_update,
)
from mobsf.MalwareAnalyzer.views.MalwareDomainCheck import MalwareDomainCheck
logger = logging.getLogger(__name__)
def common_analysis(request, app_dic, rescan, api, analysis_type):
app_dic['app_file'] = f'{app_dic["md5"]}.{analysis_type}' # NEW FILENAME
app_dic['app_path'] = (app_dic['app_dir'] / app_dic['app_file']).as_posix()
app_dic['app_dir'] = app_dic['app_dir'].as_posix() + '/'
db_entry = StaticAnalyzerAndroid.objects.filter(MD5=app_dic['md5'])
if db_entry.exists() and not rescan:
context = get_context_from_db_entry(db_entry)
else:
app_dic['size'] = f'{str(file_size(app_dic["app_path"]))}MB'
app_dic['sha1'], app_dic['sha256'] = hash_gen(app_dic['app_path'])
app_dic['files'] = unzip(app_dic['app_path'], app_dic['app_dir'])
logger.info('%s Extracted', analysis_type.upper())
if not app_dic['files']:
return print_n_send_error_response(
request,
f'{analysis_type.upper()} file is invalid or corrupt',
api)
app_dic['certz'] = get_hardcoded_cert_keystore(app_dic['files'])
app_dic['playstore'] = {'error': True}
if analysis_type == 'aar':
# AAR has manifest and sometimes certificate
app_dic['manifest_file'], app_dic['parsed_xml'] = get_manifest(
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
'aar',
)
app_dic['mani'] = (
f'../manifest_view/?md5={app_dic["md5"]}&type=aar')
man_data_dic = manifest_data(app_dic['parsed_xml'])
man_an_dic = manifest_analysis(
app_dic['parsed_xml'],
man_data_dic,
'',
app_dic['app_dir'],
)
cert_dic = cert_info(
app_dic['app_dir'],
app_dic['app_file'],
man_data_dic)
else:
app_dic['manifest_file'] = None
app_dic['parsed_xml'] = ''
app_dic['mani'] = ''
man_data_dic = {
'services': [],
'activities': [],
'receivers': [],
'providers': [],
'libraries': [],
'categories': [],
'perm': {},
'packagename': app_dic['app_name'],
'mainactivity': '',
'min_sdk': '',
'max_sdk': '',
'target_sdk': '',
'androver': '',
'androvername': '',
'icons': [],
}
man_an_dic = {
'manifest_anal': [],
'exported_act': [],
'exported_cnt': {
'exported_activities': 0,
'exported_services': 0,
'exported_receivers': 0,
'exported_providers': 0,
},
'browsable_activities': {},
'permissions': {},
'icon_hidden': True,
'network_security': {
'network_findings': [],
'network_summary': {},
},
}
cert_dic = {
'certificate_info': '',
'certificate_findings': [],
'certificate_summary': {},
}
app_dic['real_name'] = ''
elf_dict = {
'elf_analysis': [],
'elf_strings': [],
}
apkid_results = {}
tracker = Trackers.Trackers(
app_dic['app_dir'],
app_dic['tools_dir'])
tracker_res = tracker.get_trackers()
apk_2_java(
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'])
code_an_dic = code_analysis(
app_dic['app_dir'],
'apk',
app_dic['manifest_file'])
quark_results = []
# Get the strings from android resource and shared objects
string_res = strings_from_apk(
app_dic['app_file'],
app_dic['app_dir'],
elf_dict['elf_strings'])
if string_res:
app_dic['strings'] = string_res['strings']
app_dic['secrets'] = string_res['secrets']
code_an_dic['urls_list'].extend(
string_res['urls_list'])
code_an_dic['urls'].extend(string_res['url_nf'])
code_an_dic['emails'].extend(string_res['emails_nf'])
else:
app_dic['strings'] = []
app_dic['secrets'] = []
# Firebase DB Check
code_an_dic['firebase'] = firebase_analysis(
list(set(code_an_dic['urls_list'])))
# Domain Extraction and Malware Check
logger.info(
'Performing Malware Check on extracted Domains')
code_an_dic['domains'] = MalwareDomainCheck().scan(
list(set(code_an_dic['urls_list'])))
app_dic['zipped'] = analysis_type
app_dic['icon_hidden'] = True
app_dic['icon_found'] = False
logger.info('Connecting to Database')
try:
# SAVE TO DB
if rescan:
logger.info('Updating Database...')
save_or_update(
'update',
app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
elf_dict['elf_analysis'],
apkid_results,
quark_results,
tracker_res,
)
update_scan_timestamp(app_dic['md5'])
else:
logger.info('Saving to Database')
save_or_update(
'save',
app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
elf_dict['elf_analysis'],
apkid_results,
quark_results,
tracker_res,
)
except Exception:
logger.exception('Saving to Database Failed')
context = get_context_from_analysis(
app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
elf_dict['elf_analysis'],
apkid_results,
quark_results,
tracker_res,
)
context['appsec'] = get_android_dashboard(context, True)
context['average_cvss'] = get_avg_cvss(
context['code_analysis'])
context['dynamic_analysis_done'] = False
context['virus_total'] = None
if settings.VT_ENABLED:
vt = VirusTotal.VirusTotal()
context['virus_total'] = vt.get_result(
app_dic['app_path'],
app_dic['md5'])
template = 'static_analysis/android_binary_analysis.html'
if api:
return context
else:
return render(request, template, context)
def jar_analysis(request, app_dic, rescan, api):
return common_analysis(request, app_dic, rescan, api, 'jar')
def aar_analysis(request, app_dic, rescan, api):
return common_analysis(request, app_dic, rescan, api, 'aar')
@@ -28,17 +28,16 @@ logger = logging.getLogger(__name__)
ANDROID_4_2_LEVEL = 17
ANDROID_5_0_LEVEL = 21
ANDROID_8_0_LEVEL = 26
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
def get_manifest(app_path, app_dir, tools_dir, typ, binary):
def get_manifest(app_path, app_dir, tools_dir, typ):
"""Get the manifest file."""
try:
manifest_file = get_manifest_file(
app_dir,
app_path,
tools_dir,
typ,
binary)
typ)
mfile = Path(manifest_file)
if mfile.exists():
manifest = mfile.read_text('utf-8', 'ignore')
@@ -862,21 +861,24 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
logger.exception('Performing Manifest Analysis')
def get_manifest_file(app_dir, app_path, tools_dir, typ, apk):
def get_manifest_file(app_dir, app_path, tools_dir, typ):
"""Read the manifest file."""
try:
manifest = ''
if apk:
if typ == 'aar':
logger.info('Getting AndroidManifest.xml from AAR')
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
elif typ == 'apk':
logger.info('Getting AndroidManifest.xml from APK')
manifest = get_manifest_apk(app_path, app_dir, tools_dir)
else:
logger.info('Getting AndroidManifest.xml from Source Code')
if typ == 'eclipse':
manifest = os.path.join(app_dir, 'AndroidManifest.xml')
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
elif typ == 'studio':
manifest = os.path.join(
app_dir,
'app/src/main/AndroidManifest.xml')
f'app/src/main/{ANDROID_MANIFEST_FILE}')
return manifest
except Exception:
logger.exception('Getting AndroidManifest.xml file')
@@ -905,7 +907,7 @@ def get_manifest_apk(app_path, app_dir, tools_dir):
app_path,
'-o',
output_dir]
manifest = os.path.join(output_dir, 'AndroidManifest.xml')
manifest = os.path.join(output_dir, ANDROID_MANIFEST_FILE)
if is_file_exists(manifest):
# APKTool already created readable XML
return manifest
@@ -23,26 +23,18 @@ def run(request):
directory = settings.BASE_DIR # BASE DIR
md5 = request.GET['md5'] # MD5
typ = request.GET['type'] # APK or SOURCE
binary = request.GET['bin']
match = re.match('^[0-9a-f]{32}$', md5)
if (match
and (typ in ['eclipse', 'studio', 'apk'])
and (binary in ['1', '0'])):
if match and (typ in ['eclipse', 'studio', 'apk', 'aar']):
app_dir = os.path.join(
settings.UPLD_DIR, md5 + '/') # APP DIRECTORY
tools_dir = os.path.join(
directory, 'StaticAnalyzer/tools/') # TOOLS DIR
if binary == '1':
is_binary = True
elif binary == '0':
is_binary = False
app_path = os.path.join(app_dir, md5 + '.apk')
manifest_file = get_manifest_file(
app_dir,
app_path,
tools_dir,
typ,
is_binary)
typ)
mfile = Path(manifest_file)
if mfile.exists():
manifest = mfile.read_text('utf-8', 'ignore')
@@ -60,6 +60,10 @@ from mobsf.StaticAnalyzer.views.android.xapk import (
handle_split_apk,
handle_xapk,
)
from mobsf.StaticAnalyzer.views.android.jar_aar import (
aar_analysis,
jar_analysis,
)
from mobsf.StaticAnalyzer.views.common.shared_func import (
firebase_analysis,
get_avg_cvss,
@@ -101,8 +105,8 @@ def static_analyzer(request, api=False):
match = re.match('^[0-9a-f]{32}$', checksum)
if (match
and filename.lower().endswith(
('.apk', '.xapk', '.zip', '.apks'))
and typ in ['zip', 'apk', 'xapk', 'apks']):
('.apk', '.xapk', '.zip', '.apks', '.jar', '.aar'))
and typ in ['zip', 'apk', 'xapk', 'apks', 'jar', 'aar']):
app_dic['dir'] = Path(settings.BASE_DIR) # BASE DIR
app_dic['app_name'] = filename # APP ORIGINAL NAME
app_dic['md5'] = checksum # MD5
@@ -145,17 +149,10 @@ def static_analyzer(request, api=False):
logger.info('APK Extracted')
if not app_dic['files']:
# Can't Analyze APK, bail out.
msg = 'APK file is invalid or corrupt'
if api:
return print_n_send_error_response(
request,
msg,
True)
else:
return print_n_send_error_response(
request,
msg,
False)
return print_n_send_error_response(
request,
'APK file is invalid or corrupt',
api)
app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
'files'])
# Manifest XML
@@ -163,8 +160,7 @@ def static_analyzer(request, api=False):
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
'',
True,
'apk',
)
app_dic['manifest_file'] = mani_file
app_dic['parsed_xml'] = mani_xml
@@ -173,7 +169,6 @@ def static_analyzer(request, api=False):
app_dic['real_name'] = get_app_name(
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
True,
)
@@ -182,9 +177,8 @@ def static_analyzer(request, api=False):
get_icon_apk(app_dic)
# Set Manifest link
app_dic['mani'] = ('../manifest_view/?md5='
+ app_dic['md5']
+ '&type=apk&bin=1')
app_dic['mani'] = (
f'../manifest_view/?md5={app_dic["md5"]}&type=apk')
man_data_dic = manifest_data(app_dic['parsed_xml'])
app_dic['playstore'] = get_app_details(
man_data_dic['packagename'])
@@ -306,6 +300,10 @@ def static_analyzer(request, api=False):
return context
else:
return render(request, template, context)
elif typ == 'jar':
return jar_analysis(request, app_dic, rescan, api)
elif typ == 'aar':
return aar_analysis(request, app_dic, rescan, api)
elif typ == 'zip':
ret = (
'/static_analyzer_ios/?name='
@@ -369,7 +367,6 @@ def static_analyzer(request, api=False):
app_dic['app_dir'],
app_dic['tools_dir'],
pro_type,
False,
)
app_dic['manifest_file'] = mani_file
app_dic['parsed_xml'] = mani_xml
@@ -378,17 +375,13 @@ def static_analyzer(request, api=False):
app_dic['real_name'] = get_app_name(
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
False,
)
# Set manifest view link
app_dic['mani'] = (
'../manifest_view/?md5='
+ app_dic['md5'] + '&type='
+ pro_type + '&bin=0'
)
f'../manifest_view/?md5={app_dic["md5"]}'
f'&type={pro_type}')
man_data_dic = manifest_data(app_dic['parsed_xml'])
app_dic['playstore'] = get_app_details(
man_data_dic['packagename'])
@@ -513,7 +506,7 @@ def static_analyzer(request, api=False):
else:
return render(request, template, context)
else:
err = ('Only APK,IPA and Zipped '
err = ('Only APK, JAR, AAR, IPA and Zipped '
'Android/iOS Source code supported now!')
logger.error(err)
else:
@@ -591,7 +584,7 @@ def move_to_parent(inside, app_dir):
shutil.rmtree(inside)
def get_app_name(app_path, app_dir, tools_dir, is_apk):
def get_app_name(app_path, app_dir, is_apk):
"""Get app name."""
if is_apk:
a = apk.APK(app_path)
@@ -28,7 +28,7 @@ logger = logging.getLogger(__name__)
def run(request, api=False):
"""View the source of a file."""
try:
logger.info('View Android Source File')
logger.info('View Java Source File')
exp = 'Error Description'
if api:
fil = request.POST['file']
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -225,10 +225,10 @@
// Is valid file extensions
function isValidExt(file_name){
var val = file_name.toLowerCase();
var regex = new RegExp("(.*?)\.(ipa|apk|apks|xapk|zip|appx)$");
var regex = new RegExp("(.*?)\.(ipa|apk|apks|xapk|jar|aar|zip|appx)$");
val = val.replace(/^.*[\\\/]/, '');
if (!(regex.test(val))) {
_('status').innerText = "Please upload APK/APKS/XAPK/IPA/ZIP/APPX only!";
_('status').innerText = "Please upload APK/APKS/XAPK/JAR/AAR/IPA/ZIP/APPX only!";
return false;
}
return true;
+2
View File
@@ -74,6 +74,8 @@
{% if '.apk' == e.FILE_NAME|slice:"-4:"%}<i class="fab fa-android fa-3x"></i>
{% elif '.xapk' == e.FILE_NAME|slice:"-5:"%}<i class="fab fa-android fa-3x"></i>
{% elif '.apks' == e.FILE_NAME|slice:"-5:"%}<i class="fab fa-android fa-3x"></i>
{% elif '.jar' == e.FILE_NAME|slice:"-4:"%}<i class="fab fa-java fa-3x"></i>
{% elif '.aar' == e.FILE_NAME|slice:"-4:"%}<i class="fas fa-table fa-3x"></i>
{% elif '.ipa' == e.FILE_NAME|slice:"-4:"%}<i class="fab fa-apple fa-3x"></i>
{% elif '.zip' == e.FILE_NAME|slice:"-4:"%}<i class="fas fa-file-archive fa-3x"></i>
{% elif '.appx' == e.FILE_NAME|slice:"-5:"%}<i class="fab fa-windows fa-3x"></i>
+3 -3
View File
@@ -182,7 +182,8 @@
<h5>Max SDK:</h5> {{ max_sdk }}</br>
<h5>Android Version Name:</h5> {{ version_name }}</br>
<h5>Android Version Code:</h5> {{ version_code }}</br>
{% if app_type not in 'jar,aar' %}
<h2><i class="fas fa-th-large"></i> APP COMPONENTS </h2>
<h5>Activities:</h5> {{ activities | length }}</br>
@@ -193,7 +194,7 @@
<h5>Exported Services:</h5> <span {% if exported_count.exported_services > 0 %} class="danger" {% endif %}> {{ exported_count.exported_services }}</span></br>
<h5>Exported Receivers:</h5> <span {% if exported_count.exported_receivers > 0 %} class="danger" {% endif %}> {{ exported_count.exported_receivers }}</span></br>
<h5>Exported Providers:</h5> <span {% if exported_count.exported_providers > 0 %} class="danger" {% endif %}> {{ exported_count.exported_providers }}</span></br>
{% endif %}
<h2><i class="fa fa-certificate"></i> CERTIFICATE INFORMATION</h2>
{% if certificate_analysis.certificate_info %}
<div class="panel-body">
@@ -238,7 +239,6 @@
</tbody>
</table>
{% endif %}
{% if virus_total and virus_total.items|length > 9 and 'request successfully queued' not in virus_total.verbose_msg %}
<h2><i class="fas fa-spider"></i> VIRUSTOTAL SCAN</h2>
@@ -328,6 +328,7 @@
</a>
</li>
{% else %}
{% if app_type not in 'jar,aar' %}
<li class="nav-item">
<a onclick="dynamic_loader()" href="../android_dynamic/{{md5}}" class="nav-link">
<i class="nav-icon fa fa-play-circle"></i>
@@ -336,6 +337,7 @@
</p>
</a>
</li>
{% endif %}
{% endif %}
</ul>
</nav>
@@ -484,6 +486,7 @@
</div>
</div>
{% if app_type not in 'jar,aar' %}
<!-- Boxes -->
<div class="container-fluid">
<div class="row">
@@ -619,10 +622,9 @@
</div>
</div>
</section>
{% endif %}
<!-- =========================end information==================================== -->
<a id="scan_options" class="anchor"></a>
<section class="content">
<div class="container-fluid">
@@ -633,12 +635,14 @@
<p>
<strong><i class="fas fa-cog"></i> SCAN OPTIONS</strong>
</p>
<p> <a href="../static_analyzer/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type=apk&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<p> <a href="../static_analyzer/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type={{ app_type }}&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a id="supbtn" onclick="list_suppressions()" role="button" class="btn btn-primary" data-target="#sup_list" data-toggle="modal" href="#"><i class="fa fa-list"></i> Manage Suppressions</a>
</p>
{% if app_type not in 'jar,aar' %}
<p>
<a onclick="dynamic_loader()" href="../android_dynamic/{{md5}}" class="btn btn-success" role="button"><i class="fa fa-play-circle"></i> Start Dynamic Analysis</a>
</p>
{% endif %}
</div>
</div><!-- /.card -->
</div>
@@ -649,14 +653,20 @@
<strong><i class="fas fa-file-code"></i> DECOMPILED CODE</strong>
</p>
<p>
<a target="_blank" href="../manifest_view/?md5={{ md5 }}&amp;type={{ app_type }}&amp;bin=1" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
{% if app_type not in 'jar' %}
<a target="_blank" href="../manifest_view/?md5={{ md5 }}&amp;type={{ app_type }}" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
{% endif %}
<a href="{% url "tree_view" %}?md5={{ md5 }}&amp;type=java" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Source</a>
{% if app_type not in 'jar,aar' %}
<a href="{% url "tree_view" %}?md5={{ md5 }}&amp;type=smali" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Smali</a>
{% endif %}
</p>
<p>
<a href="../generate_downloads/?hash={{ md5 }}&amp;file_type=java" class="btn btn-warning" role="button"> <i class="fa fa-download"></i> Download Java Code</a>
{% if app_type not in 'jar,aar' %}
<a href="../generate_downloads/?hash={{ md5 }}&amp;file_type=smali" class="btn btn-warning"> <i class="fa fa-download"></i> Download Smali Code</a>
<a href="../generate_downloads/?hash={{ md5 }}&amp;file_type=apk" class="btn btn-warning"> <i class="fa fa-download"></i> Download APK</a>
{% endif %}
<a href="../generate_downloads/?hash={{ md5 }}&amp;file_type={{ app_type }}" class="btn btn-warning"> <i class="fa fa-download"></i> Download {{ app_type | upper}}</a>
</p>
</div>
</div>
@@ -535,7 +535,7 @@
<p align="center">
<a href="../static_analyzer/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type=zip&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a id="supbtn" onclick="list_suppressions()" role="button" class="btn btn-primary" data-target="#sup_list" data-toggle="modal" href="#"><i class="fa fa-list"></i> Manage Suppressions</a>
<a target="_blank" href="../manifest_view/?md5={{ md5 }}&amp;type={{ app_type }}&amp;bin=0" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
<a target="_blank" href="../manifest_view/?md5={{ md5 }}&amp;type={{ app_type }}" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
<a href="{% url "tree_view" %}?md5={{ md5 }}&amp;type=java" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Source</a>
</p>
</div>