def static_analyzer(request):
    """Do static analysis on an request and save to db."""
    try:
        # Input validation
        app_dic = {}
        typ = request.GET['type']
        # output = request.GET['format'] # Later for json output
        match = re.match('^[0-9a-f]{32}$', request.GET['checksum'])
        if ((match) and (request.GET['name'].lower().endswith('.apk')
                         or request.GET['name'].lower().endswith('.zip'))
                and (typ in ['zip', 'apk'])):
            app_dic['dir'] = settings.BASE_DIR  # BASE DIR
            app_dic['app_name'] = request.GET['name']  # APP ORGINAL NAME
            app_dic['md5'] = request.GET['checksum']  # MD5
            app_dic['app_dir'] = os.path.join(
                settings.UPLD_DIR, app_dic['md5'] + '/')  # APP DIRECTORY
            app_dic['tools_dir'] = os.path.join(
                app_dic['dir'], 'StaticAnalyzer/tools/')  # TOOLS DIR
            # DWD_DIR = settings.DWD_DIR # not needed? Var is never used.
            print "[INFO] Starting Analysis on : " + app_dic['app_name']
            rescan = str(request.GET.get('rescan', 0))
            if typ == 'apk':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.apk'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH

                    # ANALYSIS BEGINS
                    app_dic['size'] = str(FileSize(
                        app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic['sha256'] = HashGen(
                        app_dic['app_path'])

                    app_dic['files'] = Unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])

                    print "[INFO] APK Extracted"

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_dir'], app_dic['tools_dir'], '', True)

                    # Set Manifest link
                    app_dic['mani'] = '../ManifestView/?md5=' + \
                        app_dic['md5'] + '&type=apk&bin=1'
                    man_data_dic = manifest_data(app_dic['parsed_xml'])

                    man_an_dic = manifest_analysis(app_dic['parsed_xml'],
                                                   man_data_dic)

                    cert_dic = cert_info(app_dic['app_dir'],
                                         app_dic['tools_dir'])
                    dex_2_jar(app_dic['app_path'], app_dic['app_dir'],
                              app_dic['tools_dir'])
                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])
                    jar_2_java(app_dic['app_dir'], app_dic['tools_dir'])
                    code_an_dic = code_analysis(app_dic['app_dir'],
                                                app_dic['md5'],
                                                man_an_dic['permissons'],
                                                "apk")

                    print "\n[INFO] Generating Java and Smali Downloads"
                    gen_downloads(app_dic['app_dir'], app_dic['md5'])

                    # Get the strings
                    app_dic['strings'] = strings(app_dic['app_file'],
                                                 app_dic['app_dir'],
                                                 app_dic['tools_dir'])
                    app_dic['zipped'] = '&type=apk'

                    print "\n[INFO] Connecting to Database"
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            print "\n[INFO] Updating Database..."
                            update_db_entry(app_dic, man_data_dic, man_an_dic,
                                            code_an_dic, cert_dic)
                        elif rescan == '0':
                            print "\n[INFO] Saving to Database"
                            create_db_entry(app_dic, man_data_dic, man_an_dic,
                                            code_an_dic, cert_dic)
                    except:
                        PrintException("[ERROR] Saving to Database Failed")
                    context = get_context_from_an(app_dic, man_data_dic,
                                                  man_an_dic, code_an_dic,
                                                  cert_dic)
                template = "static_analysis/static_analysis.html"
                return render(request, template, context)
            elif typ == 'zip':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry_zip(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.zip'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH
                    print "[INFO] Extracting ZIP"
                    app_dic['files'] = Unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        print "[INFO] Redirecting to iOS Source Code Analyzer"
                        return HttpResponseRedirect(
                            '/StaticAnalyzer_iOS/?name=' +
                            app_dic['app_name'] + '&type=ios&checksum=' +
                            app_dic['md5'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])
                    print "[INFO] ZIP Type - " + pro_type
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(FileSize(
                            app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic['sha256'] = HashGen(
                            app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            app_dic['app_dir'], app_dic['tools_dir'], pro_type,
                            False)

                        # Set manifest view link
                        app_dic['mani'] = ('../ManifestView/?md5=' +
                                           app_dic['md5'] + '&type=' +
                                           pro_type + '&bin=0')

                        man_data_dic = manifest_data(app_dic['persed_xml'])

                        man_an_dic = manifest_analysis(app_dic['persed_xml'],
                                                       man_data_dic)

                        code_an_dic = code_analysis(app_dic['app_dir'],
                                                    app_dic['md5'],
                                                    man_an_dic['permissons'],
                                                    pro_type)
                        print "\n[INFO] Connecting to Database"
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                print "\n[INFO] Updating Database..."
                                update_db_entry_zip(app_dic, man_data_dic,
                                                    man_an_dic, code_an_dic)
                            elif rescan == '0':
                                print "\n[INFO] Saving to Database"
                                create_db_entry_zip(app_dic, man_data_dic,
                                                    man_an_dic, code_an_dic)
                        except:
                            PrintException("[ERROR] Saving to Database Failed")
                        context = get_context_from_an_zip(
                            app_dic, man_data_dic, man_an_dic, code_an_dic)
                    else:
                        return HttpResponseRedirect('/zip_format/')
                template = "static_analysis/static_analysis_android_zip.html"
                return render(request, template, context)
            else:
                print "\n[ERROR] Only APK,IPA and Zipped Android/iOS Source code supported now!"
        else:
            return HttpResponseRedirect('/error/')

    except Exception as excep:
        PrintException("[ERROR] Static Analyzer")
        context = {
            'title': 'Error',
            'exp': excep.message,
            'doc': excep.__doc__
        }
        template = "general/error.html"
        return render(request, template, context)
示例#2
0
def pdf(request, api=False, jsonres=False):
    try:
        if api:
            checksum = request.POST['hash']
            scan_type = request.POST['scan_type']
        else:
            checksum = request.GET['md5']
            scan_type = request.GET['type']
        hash_match = re.match('^[0-9a-f]{32}$', checksum)
        if hash_match:
            if scan_type.lower() in ['apk', 'andzip']:
                static_db = StaticAnalyzerAndroid.objects.filter(MD5=checksum)
                if static_db.exists():
                    logger.info('Fetching data from DB for '
                                'PDF Report Generation (Android)')
                    context = get_context_from_db_entry(static_db)
                    context['average_cvss'], context['security_score'] = score(
                        context['findings'])
                    if scan_type.lower() == 'apk':
                        template = get_template(
                            'pdf/android_binary_analysis.pdf.html')
                    else:
                        template = get_template(
                            'pdf/android_source_analysis_pdf.html')
                else:
                    if api:
                        return {'report': 'Report not Found'}
                    else:
                        return HttpResponse(
                            json.dumps({'report': 'Report not Found'}),
                            content_type='application/json; charset=utf-8',
                            status=500)
            elif scan_type.lower() in ['ipa', 'ioszip']:
                if scan_type.lower() == 'ipa':
                    static_db = StaticAnalyzerIPA.objects.filter(MD5=checksum)
                    if static_db.exists():
                        logger.info('Fetching data from DB for '
                                    'PDF Report Generation (IOS IPA)')
                        context = get_context_from_db_entry_ipa(static_db)
                        context['average_cvss'], context[
                            'security_score'] = score(context['bin_anal'])
                        template = get_template(
                            'pdf/ios_binary_analysis_pdf.html')
                    else:
                        if api:
                            return {'report': 'Report not Found'}
                        else:
                            return HttpResponse(
                                json.dumps({'report': 'Report not Found'}),
                                content_type='application/json; charset=utf-8',
                                status=500)
                elif scan_type.lower() == 'ioszip':
                    static_db = StaticAnalyzerIOSZIP.objects.filter(
                        MD5=checksum)
                    if static_db.exists():
                        logger.info('Fetching data from DB for '
                                    'PDF Report Generation (IOS ZIP)')
                        context = get_context_from_db_entry_ios(static_db)
                        context['average_cvss'], context[
                            'security_score'] = score(context['insecure'])
                        template = get_template(
                            'pdf/ios_source_analysis_pdf.html')
                    else:
                        if api:
                            return {'report': 'Report not Found'}
                        else:
                            return HttpResponse(
                                json.dumps({'report': 'Report not Found'}),
                                content_type='application/json; charset=utf-8',
                                status=500)
            elif 'appx' == scan_type.lower():
                if scan_type.lower() == 'appx':
                    db_entry = StaticAnalyzerWindows.objects.filter(
                        MD5=checksum, )
                    if db_entry.exists():
                        logger.info('Fetching data from DB for '
                                    'PDF Report Generation (APPX)')

                        context = {
                            'title':
                            db_entry[0].TITLE,
                            'name':
                            db_entry[0].APP_NAME,
                            'pub_name':
                            db_entry[0].PUB_NAME,
                            'size':
                            db_entry[0].SIZE,
                            'md5':
                            db_entry[0].MD5,
                            'sha1':
                            db_entry[0].SHA1,
                            'sha256':
                            db_entry[0].SHA256,
                            'bin_name':
                            db_entry[0].BINNAME,
                            'version':
                            db_entry[0].VERSION,
                            'arch':
                            db_entry[0].ARCH,
                            'compiler_version':
                            db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':
                            db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':
                            db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':
                            db_entry[0].TARGET_OS,
                            'appx_dll_version':
                            db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':
                            db_entry[0].PROJ_GUID,
                            'opti_tool':
                            db_entry[0].OPTI_TOOL,
                            'target_run':
                            db_entry[0].TARGET_RUN,
                            'files':
                            python_list(db_entry[0].FILES),
                            'strings':
                            python_list(db_entry[0].STRINGS),
                            'bin_an_results':
                            python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings':
                            python_list(db_entry[0].BIN_AN_WARNINGS),
                        }
                        template = get_template(
                            'pdf/windows_binary_analysis_pdf.html')
            else:
                if api:
                    return {'scan_type': 'Type is not Allowed'}
                else:
                    return HttpResponse(
                        json.dumps({'type': 'Type is not Allowed'}),
                        content_type='application/json; charset=utf-8',
                        status=500)

            context['VT_RESULT'] = None
            if settings.VT_ENABLED:
                app_dir = os.path.join(settings.UPLD_DIR, checksum + '/')
                vt = VirusTotal.VirusTotal()
                if 'zip' in scan_type.lower():
                    context['VT_RESULT'] = None
                else:
                    context['VT_RESULT'] = vt.get_result(
                        os.path.join(app_dir, checksum) + '.' +
                        scan_type.lower(), checksum)
            try:
                if api and jsonres:
                    return {'report_dat': context}
                else:
                    options = {
                        'page-size': 'A4',
                        'quiet': '',
                        'no-collate': '',
                        'margin-top': '0.50in',
                        'margin-right': '0.50in',
                        'margin-bottom': '0.50in',
                        'margin-left': '0.50in',
                        'encoding': 'UTF-8',
                        'custom-header': [
                            ('Accept-Encoding', 'gzip'),
                        ],
                        'no-outline': None,
                    }
                    html = template.render(context)
                    pdf_dat = pdfkit.from_string(html, False, options=options)
                    if api:
                        return {'pdf_dat': pdf_dat}
                    return HttpResponse(pdf_dat,
                                        content_type='application/pdf')
            except Exception as exp:
                logger.exception('Error Generating PDF Report')
                if api:
                    return {
                        'error': 'Cannot Generate PDF/JSON',
                        'err_details': str(exp)
                    }
                else:
                    return HttpResponse(
                        json.dumps({
                            'pdf_error': 'Cannot Generate PDF',
                            'err_details': str(exp)
                        }),
                        content_type='application/json; charset=utf-8',
                        status=500)

        else:
            if api:
                return {'error': 'Invalid scan hash'}
            else:
                return HttpResponse(
                    json.dumps({'md5': 'Invalid MD5'}),
                    content_type='application/json; charset=utf-8',
                    status=500)
    except Exception as exp:
        logger.exception('Error Generating PDF Report')
        msg = str(exp)
        exp = exp.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
def generic_compare(request,
                    first_hash: str,
                    second_hash: str,
                    api: bool = False):
    # This context consists of specific lists and analysis that is done on the classic ones
    # it will be filled during the different diff analysis
    context = {
        'title': 'Compare report',
        'first_app': dict(),
        'second_app': dict(),
        'urls': dict(),
        'api': dict(),
        'permissions': dict(),
        'apkid': dict()
    }
    static_fields = [
        'md5', 'name', 'size', 'icon_found', 'icon_hidden', 'act_count',
        'e_act', 'serv_count', 'e_ser', 'bro_count', 'e_bro', 'prov_count',
        'e_cnt', 'apkid'
    ]

    # For now - support only android
    db_entry = StaticAnalyzerAndroid.objects.filter(MD5=first_hash)
    db_entry2 = StaticAnalyzerAndroid.objects.filter(MD5=second_hash)

    if not (db_entry.exists() and db_entry2.exists()):
        return print_n_send_error_response(
            request,
            "One of the Hashes wasn't found in the Android-results DB, make sure "
            "both of the apps finished analysis & they are both Android",
            False)

    # First fetch the already done analysis on each of the apps
    # We don't want to return this whole context back to the user because its a lot of data we don't use
    # it should help the performance I guess
    first_app = deepcopy(get_context_from_db_entry(db_entry))
    second_app = deepcopy(get_context_from_db_entry(db_entry2))

    # Second, fill the common static parts that are missing in the classic analysis
    for curr_app, db_context in [('first_app', first_app),
                                 ('second_app', second_app)]:

        # format informative title
        context[curr_app]['name_ver'] = "{0} - {1}".format(
            db_context['packagename'], db_context['androvername'])

        # Fill all the static information
        for static_attr in static_fields:
            context[curr_app][static_attr] = db_context[static_attr]

        # Get only the subject of the cert
        subject_regex = re.compile(r'.*Subject:([^<]+)</br>.*', re.DOTALL)
        match = subject_regex.match(db_context['certinfo'])
        if match:
            context[curr_app]['cert_subject'] = match.group(1)
        else:
            context[curr_app]['cert_subject'] = "No subject"

        # Some preparations so we have some sort of same structures
        # (urls are lists inside the list which mess things up...)
        tmp_list = list()
        for url_obj in db_context['urls']:
            for url in url_obj['urls']:
                # urls can mess up the table because they can be really long, so let's cut them
                tmp_url = url[:70]
                while len(url) > 70:
                    url = url[70:]
                    tmp_url += '<br />'
                    tmp_url += url[:70]
                tmp_list.append(tmp_url)

        db_context['urls'] = list(set(deepcopy(tmp_list)))
        tmp_list.clear()

    # apkid check - we do it here just because its really ugly inside the template
    # it has a dedicated function because the result is more complicated then the others...
    diff_apkid(context)

    # Third, calculate some diffs
    for section, is_tuples in [('permissions', True), ('api', True),
                               ('urls', False)]:
        if is_tuples:
            context[section]['common'] = [
                (x, y) for (x, y) in first_app[section].items()
                if x in second_app[section].keys()
            ]

            # Only first
            context[section]['only_first'] = [
                (x, y) for (x, y) in first_app[section].items()
                if x not in second_app[section].keys()
            ]

            # Only Second
            context[section]['only_second'] = [
                (x, y) for (x, y) in second_app[section].items()
                if x not in first_app[section].keys()
            ]
        else:
            context[section]['common'] = [
                x for x in first_app[section] if x in second_app[section]
            ]

            context[section]['only_first'] = [
                x for x in first_app[section] if x not in second_app[section]
            ]

            context[section]['only_second'] = [
                x for x in second_app[section] if x not in first_app[section]
            ]

    template = "static_analysis/compare.html"
    if api:
        return context
    else:
        return render(request, template, context)
示例#4
0
def generic_compare(request,
                    first_hash: str,
                    second_hash: str,
                    api: bool = False):
    # This context consists of specific lists and analysis
    # that is done on the classic ones
    # it will be filled during the different diff analysis
    context = {
        'title': 'Compare report',
        'version': settings.MOBSF_VER,
        'first_app': {},
        'second_app': {},
        'urls': {},
        'android_api': {},
        'permissions': {},
        'apkid': {},
    }
    static_fields = [
        'md5', 'file_name', 'size', 'icon_found', 'icon_hidden', 'activities',
        'services', 'providers', 'receivers', 'exported_count', 'apkid'
    ]

    # For now - support only android
    db_entry = StaticAnalyzerAndroid.objects.filter(MD5=first_hash)
    db_entry2 = StaticAnalyzerAndroid.objects.filter(MD5=second_hash)

    if not (db_entry.exists() and db_entry2.exists()):
        return print_n_send_error_response(
            request,
            'Currently you can only diff/compare android apps. '
            'One of the app has not completed static analysis or'
            ' they are not both android APK/ZIP.',
            api,
        )

    # First fetch the already done analysis on each of the apps
    # We don't want to return this whole context back to the user
    # because its a lot of data we don't use
    # it should help the performance I guess
    first_app = deepcopy(get_context_from_db_entry(db_entry))
    second_app = deepcopy(get_context_from_db_entry(db_entry2))

    # Second, fill the common static parts that
    # are missing in the classic analysis
    for curr_app, db_context in [('first_app', first_app),
                                 ('second_app', second_app)]:

        # format informative title
        context[curr_app]['name_ver'] = '{0} - {1}'.format(
            db_context['package_name'], db_context['version_name'])

        # Fill all the static information
        for static_attr in static_fields:
            context[curr_app][static_attr] = db_context[static_attr]

        # Get only the subject of the cert
        subject_regex = re.compile(r'Subject: .*')
        match = subject_regex.search(
            db_context['certificate_analysis']['certificate_info'])
        if match:
            context[curr_app]['cert_subject'] = match.group()
        else:
            context[curr_app]['cert_subject'] = 'No subject'

        # Some preparations so we have some sort of same structures
        # (urls are lists inside the list which mess things up...)
        tmp_list = []
        for url_obj in db_context['urls']:
            for url in url_obj['urls']:
                # urls can mess up the table because they can be really long,
                # so let's cut them
                # escape url
                url = escape(url)
                tmp_url = url[:70]
                while len(url) > 70:
                    url = url[70:]
                    tmp_url += '<br />'
                    tmp_url += url[:70]
                tmp_list.append(tmp_url)

        db_context['urls'] = list(set(deepcopy(tmp_list)))
        tmp_list.clear()

    # apkid check - we do it here just because
    # its really ugly inside the template
    # it has a dedicated function because the result
    # is more complicated then the others...
    diff_apkid(context)

    # Third, calculate some diffs
    for section, is_tuples in [
        ('permissions', True),
        ('android_api', True),
        ('urls', False),
    ]:
        if is_tuples:
            context[section]['common'] = [
                (x, y) for (x, y) in first_app[section].items()
                if x in second_app[section].keys()
            ]

            # Only first
            context[section]['only_first'] = [
                (x, y) for (x, y) in first_app[section].items()
                if x not in second_app[section].keys()
            ]

            # Only Second
            context[section]['only_second'] = [
                (x, y) for (x, y) in second_app[section].items()
                if x not in first_app[section].keys()
            ]
        else:
            context[section]['common'] = [
                x for x in first_app[section] if x in second_app[section]
            ]

            context[section]['only_first'] = [
                x for x in first_app[section] if x not in second_app[section]
            ]

            context[section]['only_second'] = [
                x for x in second_app[section] if x not in first_app[section]
            ]
    template = 'static_analysis/compare.html'
    if api:
        return context
    else:
        return render(request, template, context)
示例#5
0
def static_analyzer(request, api=False):
    """Do static analysis on an request and save to db."""
    try:
        if api:
            typ = request.POST['scan_type']
            checksum = request.POST['hash']
            filename = request.POST['file_name']
            rescan = str(request.POST.get('re_scan', 0))
        else:
            typ = request.GET['type']
            checksum = request.GET['checksum']
            filename = request.GET['name']
            rescan = str(request.GET.get('rescan', 0))
        # Input validation
        app_dic = {}
        match = re.match('^[0-9a-f]{32}$', checksum)
        if ((match) and (filename.lower().endswith('.apk')
                         or filename.lower().endswith('.zip'))
                and (typ in ['zip', 'apk'])):
            app_dic['dir'] = Path(settings.BASE_DIR)  # BASE DIR
            app_dic['app_name'] = filename  # APP ORGINAL NAME
            app_dic['md5'] = checksum  # MD5
            # APP DIRECTORY
            app_dic['app_dir'] = Path(settings.UPLD_DIR) / checksum
            app_dic['tools_dir'] = app_dic['dir'] / 'StaticAnalyzer' / 'tools'
            app_dic['tools_dir'] = app_dic['tools_dir'].as_posix()
            logger.info('Starting Analysis on : %s', app_dic['app_name'])

            if typ == 'apk':
                app_dic['app_file'] = app_dic['md5'] + '.apk'  # 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() + '/'
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    # ANALYSIS BEGINS
                    app_dic['size'] = str(file_size(
                        app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic['sha256'] = hash_gen(
                        app_dic['app_path'])
                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    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)
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])

                    logger.info('APK Extracted')

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_path'],
                        app_dic['app_dir'],
                        app_dic['tools_dir'],
                        '',
                        True,
                    )

                    # get app_name
                    app_dic['real_name'] = get_app_name(
                        app_dic['app_path'],
                        app_dic['app_dir'],
                        app_dic['tools_dir'],
                        True,
                    )

                    # Get icon
                    res_path = os.path.join(app_dic['app_dir'], 'res')
                    app_dic['icon_hidden'] = True
                    # Even if the icon is hidden, try to guess it by the
                    # default paths
                    app_dic['icon_found'] = False
                    app_dic['icon_path'] = ''
                    # TODO: Check for possible different names for resource
                    # folder?
                    if os.path.exists(res_path):
                        icon_dic = get_icon(app_dic['app_path'], res_path)
                        if icon_dic:
                            app_dic['icon_hidden'] = icon_dic['hidden']
                            app_dic['icon_found'] = bool(icon_dic['path'])
                            app_dic['icon_path'] = icon_dic['path']

                    # Set Manifest link
                    app_dic['mani'] = ('../ManifestView/?md5=' +
                                       app_dic['md5'] + '&type=apk&bin=1')
                    man_data_dic = manifest_data(app_dic['parsed_xml'])
                    app_dic['playstore'] = get_app_details(
                        man_data_dic['packagename'])
                    man_an_dic = manifest_analysis(
                        app_dic['parsed_xml'],
                        man_data_dic,
                        '',
                        app_dic['app_dir'],
                    )
                    bin_an_buff = []
                    bin_an_buff += elf_analysis(app_dic['app_dir'])
                    bin_an_buff += res_analysis(app_dic['app_dir'])
                    cert_dic = cert_info(app_dic['app_dir'],
                                         app_dic['app_file'])
                    apkid_results = apkid_analysis(app_dic['app_dir'],
                                                   app_dic['app_path'],
                                                   app_dic['app_name'])
                    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'])

                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])

                    code_an_dic = code_analysis(app_dic['app_dir'], 'apk')

                    # Get the strings
                    string_res = strings_jar(app_dic['app_file'],
                                             app_dic['app_dir'])
                    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'] = malware_check(
                        list(set(code_an_dic['urls_list'])))
                    # Copy App icon
                    copy_icon(app_dic['md5'], app_dic['icon_path'])
                    app_dic['zipped'] = 'apk'

                    logger.info('Connecting to Database')
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            logger.info('Updating Database...')
                            save_or_update(
                                'update',
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                                tracker_res,
                            )
                            update_scan_timestamp(app_dic['md5'])
                        elif rescan == '0':
                            logger.info('Saving to Database')
                            save_or_update(
                                'save',
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_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,
                        bin_an_buff,
                        apkid_results,
                        tracker_res,
                    )
                context['average_cvss'], context['security_score'] = score(
                    context['code_analysis'])
                context['dynamic_analysis_done'] = is_file_exists(
                    os.path.join(app_dic['app_dir'], 'logcat.txt'))

                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)
            elif typ == 'zip':
                ios_ret = HttpResponseRedirect('/StaticAnalyzer_iOS/?name=' +
                                               app_dic['app_name'] +
                                               '&type=ios&checksum=' +
                                               app_dic['md5'])
                # Check if in DB
                # pylint: disable=E1101
                cert_dic = {
                    'certificate_info': '',
                    'certificate_status': '',
                    'description': '',
                }
                bin_an_buff = []
                app_dic['strings'] = []
                app_dic['secrets'] = []
                app_dic['zipped'] = ''
                # Above fields are only available for APK and not ZIP
                app_dic['app_file'] = app_dic['md5'] + '.zip'  # 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'])
                ios_db_entry = StaticAnalyzerIOS.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                elif ios_db_entry.exists() and rescan == '0':
                    if api:
                        return {'type': 'ios'}
                    else:
                        return ios_ret
                else:
                    logger.info('Extracting ZIP')
                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        logger.info('Redirecting to iOS Source Code Analyzer')
                        if api:
                            return {'type': 'ios'}
                        else:
                            return ios_ret
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])
                    app_dic['zipped'] = pro_type
                    logger.info('ZIP Type - %s', pro_type)
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(file_size(
                            app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic['sha256'] = hash_gen(
                            app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            '',
                            app_dic['app_dir'],
                            app_dic['tools_dir'],
                            pro_type,
                            False,
                        )

                        # get app_name
                        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'] = ('../ManifestView/?md5=' +
                                           app_dic['md5'] + '&type=' +
                                           pro_type + '&bin=0')

                        man_data_dic = manifest_data(app_dic['persed_xml'])
                        app_dic['playstore'] = get_app_details(
                            man_data_dic['packagename'])
                        man_an_dic = manifest_analysis(
                            app_dic['persed_xml'],
                            man_data_dic,
                            pro_type,
                            app_dic['app_dir'],
                        )
                        # Get icon
                        eclipse_res_path = os.path.join(
                            app_dic['app_dir'], 'res')
                        studio_res_path = os.path.join(app_dic['app_dir'],
                                                       'app', 'src', 'main',
                                                       'res')
                        if os.path.exists(eclipse_res_path):
                            res_path = eclipse_res_path
                        elif os.path.exists(studio_res_path):
                            res_path = studio_res_path
                        else:
                            res_path = ''

                        app_dic['icon_hidden'] = man_an_dic['icon_hidden']
                        app_dic['icon_found'] = False
                        app_dic['icon_path'] = ''
                        if res_path:
                            app_dic['icon_path'] = find_icon_path_zip(
                                res_path, man_data_dic['icons'])
                            if app_dic['icon_path']:
                                app_dic['icon_found'] = True

                        if app_dic['icon_path']:
                            if os.path.exists(app_dic['icon_path']):
                                shutil.copy2(
                                    app_dic['icon_path'],
                                    os.path.join(settings.DWD_DIR,
                                                 app_dic['md5'] + '-icon.png'))

                        code_an_dic = code_analysis(app_dic['app_dir'],
                                                    pro_type)
                        # 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'] = malware_check(
                            list(set(code_an_dic['urls_list'])))
                        logger.info('Connecting to Database')
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                logger.info('Updating Database...')
                                save_or_update(
                                    'update',
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                    {},
                                )
                                update_scan_timestamp(app_dic['md5'])
                            elif rescan == '0':
                                logger.info('Saving to Database')
                                save_or_update(
                                    'save',
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                    {},
                                )
                        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,
                            bin_an_buff,
                            {},
                            {},
                        )
                    else:
                        msg = 'This ZIP Format is not supported'
                        if api:
                            return print_n_send_error_response(
                                request, msg, True)
                        else:
                            print_n_send_error_response(request, msg, False)
                            ctx = {
                                'title': 'Invalid ZIP archive',
                                'version': settings.MOBSF_VER,
                            }
                            template = 'general/zip.html'
                            return render(request, template, ctx)
                context['average_cvss'], context['security_score'] = score(
                    context['code_analysis'])
                template = 'static_analysis/android_source_analysis.html'
                if api:
                    return context
                else:
                    return render(request, template, context)
            else:
                err = ('Only APK,IPA and Zipped '
                       'Android/iOS Source code supported now!')
                logger.error(err)
        else:
            msg = 'Hash match failed or Invalid file extension or file type'
            if api:
                return print_n_send_error_response(request, msg, True)
            else:
                return print_n_send_error_response(request, msg, False)

    except Exception as excep:
        logger.exception('Error Performing Static Analysis')
        msg = str(excep)
        exp = excep.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
示例#6
0
def PDF(request):
    try:
        MD5 = request.GET['md5']
        TYP = request.GET['type']
        m = re.match('^[0-9a-f]{32}$', MD5)
        if m:
            if TYP in ['APK', 'ANDZIP']:
                DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5)
                if DB.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(DB)
                    if TYP == 'APK':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    return HttpResponse(
                        json.dumps({"report": "Report not Found"}),
                        content_type="application/json; charset=utf-8")
            elif re.findall('IPA|IOSZIP', TYP):
                if TYP == 'IPA':
                    DB = StaticAnalyzerIPA.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'strings': python_list(DB[0].STRINGS),
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        return HttpResponse(
                            json.dumps({"report": "Report not Found"}),
                            content_type="application/json; charset=utf-8")
                elif TYP == 'IOSZIP':
                    DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'api': DB[0].HTML,
                            'insecure': DB[0].CODEANAL,
                            'urls': DB[0].URLnFile,
                            'domains': python_dict(DB[0].DOMAINS),
                            'emails': DB[0].EmailnFile,
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        return HttpResponse(
                            json.dumps({"report": "Report not Found"}),
                            content_type="application/json; charset=utf-8")
            elif re.findall('APPX', TYP):
                if TYP == 'APPX':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=MD5)
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title':
                            db_entry[0].TITLE,
                            'name':
                            db_entry[0].APP_NAME,
                            'pub_name':
                            db_entry[0].PUB_NAME,
                            'size':
                            db_entry[0].SIZE,
                            'md5':
                            db_entry[0].MD5,
                            'sha1':
                            db_entry[0].SHA1,
                            'sha256':
                            db_entry[0].SHA256,
                            'bin_name':
                            db_entry[0].BINNAME,
                            'version':
                            db_entry[0].VERSION,
                            'arch':
                            db_entry[0].ARCH,
                            'compiler_version':
                            db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':
                            db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':
                            db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':
                            db_entry[0].TARGET_OS,
                            'appx_dll_version':
                            db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':
                            db_entry[0].PROJ_GUID,
                            'opti_tool':
                            db_entry[0].OPTI_TOOL,
                            'target_run':
                            db_entry[0].TARGET_RUN,
                            'files':
                            python_list(db_entry[0].FILES),
                            'strings':
                            python_list(db_entry[0].STRINGS),
                            'bin_an_results':
                            python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings':
                            python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                return HttpResponse(
                    json.dumps({"type": "Type is not Allowed"}),
                    content_type="application/json; charset=utf-8")
            html = template.render(context)
            result = StringIO()
            pdf = pisa.pisaDocument(StringIO("{0}".format(
                html.encode('utf-8'))),
                                    result,
                                    encoding='utf-8')
            if not pdf.err:
                return HttpResponse(result.getvalue(),
                                    content_type='application/pdf')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                content_type="application/json; charset=utf-8")
    except:

        PrintException("[ERROR] PDF Report Generation Error")
        return HttpResponseRedirect('/error/')
示例#7
0
def PDF(request):
    try:
        MD5 = request.GET['md5']
        TYP = request.GET['type']
        m = re.match('^[0-9a-f]{32}$', MD5)
        if m:
            if TYP in ['APK', 'ANDZIP']:
                DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5)
                if DB.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(DB)
                    if TYP == 'APK':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    return HttpResponse(json.dumps({"report": "Report not Found"}),
                                        content_type="application/json; charset=utf-8")
            elif re.findall('IPA|IOSZIP', TYP):
                if TYP == 'IPA':
                    DB = StaticAnalyzerIPA.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = get_context_from_db_entry_ipa(DB)
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
                elif TYP == 'IOSZIP':
                    DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = get_context_from_db_entry_ios(DB)
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
            elif re.findall('APPX', TYP):
                if TYP == 'APPX':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=MD5
                    )
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title': db_entry[0].TITLE,
                            'name': db_entry[0].APP_NAME,
                            'pub_name': db_entry[0].PUB_NAME,
                            'size': db_entry[0].SIZE,
                            'md5': db_entry[0].MD5,
                            'sha1': db_entry[0].SHA1,
                            'sha256': db_entry[0].SHA256,
                            'bin_name': db_entry[0].BINNAME,
                            'version':  db_entry[0].VERSION,
                            'arch':  db_entry[0].ARCH,
                            'compiler_version':  db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':  db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':  db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':  db_entry[0].TARGET_OS,
                            'appx_dll_version':  db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':  db_entry[0].PROJ_GUID,
                            'opti_tool':  db_entry[0].OPTI_TOOL,
                            'target_run':  db_entry[0].TARGET_RUN,
                            'files':  python_list(db_entry[0].FILES),
                            'strings': python_list(db_entry[0].STRINGS),
                            'bin_an_results': python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings': python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                return HttpResponse(json.dumps({"type": "Type is not Allowed"}),
                                    content_type="application/json; charset=utf-8")
            html = template.render(context)
            try:
                options = {
                    'page-size': 'A4',
                    'quiet': '',
                    'no-collate': '',
                    'margin-top': '0.50in',
                    'margin-right': '0.50in',
                    'margin-bottom': '0.50in',
                    'margin-left': '0.50in',
                    'encoding': "UTF-8",
                    'custom-header': [
                        ('Accept-Encoding', 'gzip')
                    ],
                    'no-outline': None
                }
                pdf = pdfkit.from_string(html, False, options=options)
                return HttpResponse(pdf, content_type='application/pdf')
            except Exception as exp:
                return HttpResponse(json.dumps({"pdf_error": "Cannot Generate PDF",
                                                "err_details": str(exp)}),
                                    content_type="application/json; charset=utf-8")

        else:
            return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                content_type="application/json; charset=utf-8")
    except:

        PrintException("[ERROR] PDF Report Generation Error")
        return HttpResponseRedirect('/error/')
def static_analyzer(request):
    """Do static analysis on an request and save to db."""
    try:
        # Input validation
        app_dic = {}
        typ = request.GET['type']
        # output = request.GET['format'] # Later for json output
        match = re.match('^[0-9a-f]{32}$', request.GET['checksum'])
        if (
                (
                    match
                ) and (
                    request.GET['name'].lower().endswith('.apk') or
                    request.GET['name'].lower().endswith('.zip')
                ) and (
                    typ in ['zip', 'apk']
                )
        ):
            app_dic['dir'] = settings.BASE_DIR  # BASE DIR
            app_dic['app_name'] = request.GET['name']  # APP ORGINAL NAME
            app_dic['md5'] = request.GET['checksum']  # MD5
            app_dic['app_dir'] = os.path.join(settings.UPLD_DIR, app_dic[
                                              'md5'] + '/')  # APP DIRECTORY
            app_dic['tools_dir'] = os.path.join(
                app_dic['dir'], 'StaticAnalyzer/tools/')  # TOOLS DIR
            # DWD_DIR = settings.DWD_DIR # not needed? Var is never used.
            print "[INFO] Starting Analysis on : " + app_dic['app_name']
            rescan = str(request.GET.get('rescan', 0))
            if typ == 'apk':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic['app_file'] = app_dic[
                        'md5'] + '.apk'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH

                    # ANALYSIS BEGINS
                    app_dic['size'] = str(
                        FileSize(app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic[
                        'sha256'] = HashGen(app_dic['app_path'])

                    app_dic['files'] = Unzip(
                        app_dic['app_path'], app_dic['app_dir'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
                                                                   'files'])

                    print "[INFO] APK Extracted"

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_dir'],
                        app_dic['tools_dir'],
                        '',
                        True
                    )

                    # Set Manifest link
                    app_dic['mani'] = '../ManifestView/?md5=' + \
                        app_dic['md5'] + '&type=apk&bin=1'
                    man_data_dic = manifest_data(app_dic['parsed_xml'])

                    man_an_dic = manifest_analysis(
                        app_dic['parsed_xml'],
                        man_data_dic
                    )
                    bin_an_buff = []
                    bin_an_buff += elf_analysis(
                        app_dic['app_dir'],
                        "apk"
                    )
                    bin_an_buff += res_analysis(
                        app_dic['app_dir'],
                        "apk"
                    )
                    cert_dic = cert_info(
                        app_dic['app_dir'], app_dic['tools_dir'])
                    dex_2_jar(app_dic['app_path'], app_dic[
                              'app_dir'], app_dic['tools_dir'])
                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])
                    jar_2_java(app_dic['app_dir'], app_dic['tools_dir'])
                    code_an_dic = code_analysis(
                        app_dic['app_dir'],
                        app_dic['md5'],
                        man_an_dic['permissons'],
                        "apk"
                    )
                    print "\n[INFO] Generating Java and Smali Downloads"
                    gen_downloads(app_dic['app_dir'], app_dic['md5'])

                    # Get the strings
                    app_dic['strings'] = strings(
                        app_dic['app_file'],
                        app_dic['app_dir'],
                        app_dic['tools_dir']
                    )
                    app_dic['zipped'] = '&type=apk'

                    print "\n[INFO] Connecting to Database"
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            print "\n[INFO] Updating Database..."
                            update_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff
                            )
                        elif rescan == '0':
                            print "\n[INFO] Saving to Database"
                            create_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff
                            )
                    except:
                        PrintException("[ERROR] Saving to Database Failed")
                    context = get_context_from_analysis(
                        app_dic,
                        man_data_dic,
                        man_an_dic,
                        code_an_dic,
                        cert_dic,
                        bin_an_buff
                    )
                template = "static_analysis/static_analysis.html"
                return render(request, template, context)
            elif typ == 'zip':
                # Check if in DB
                # pylint: disable=E1101
                cert_dic = {}
                cert_dic['cert_info'] = ''
                cert_dic['issued'] = ''
                bin_an_buff = []
                app_dic['strings'] = ''
                app_dic['zipped'] = ''
                #Above fields are only available for APK and not ZIP
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic['app_file'] = app_dic[
                        'md5'] + '.zip'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH
                    print "[INFO] Extracting ZIP"
                    app_dic['files'] = Unzip(
                        app_dic['app_path'], app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        print "[INFO] Redirecting to iOS Source Code Analyzer"
                        return HttpResponseRedirect(
                            '/StaticAnalyzer_iOS/?name=' + app_dic['app_name'] +
                            '&type=ios&checksum=' + app_dic['md5']
                        )
                    app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
                                                                   'files'])
                    print "[INFO] ZIP Type - " + pro_type
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(
                            FileSize(app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic[
                            'sha256'] = HashGen(app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            app_dic['app_dir'],
                            app_dic['tools_dir'],
                            pro_type,
                            False
                        )

                        # Set manifest view link
                        app_dic['mani'] = (
                            '../ManifestView/?md5=' +
                            app_dic['md5'] + '&type=' + pro_type + '&bin=0'
                        )

                        man_data_dic = manifest_data(app_dic['persed_xml'])

                        man_an_dic = manifest_analysis(
                            app_dic['persed_xml'],
                            man_data_dic
                        )

                        code_an_dic = code_analysis(
                            app_dic['app_dir'],
                            app_dic['md5'],
                            man_an_dic['permissons'],
                            pro_type
                        )
                        print "\n[INFO] Connecting to Database"
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                print "\n[INFO] Updating Database..."
                                update_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff
                                )
                            elif rescan == '0':
                                print "\n[INFO] Saving to Database"
                                create_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff
                                )
                        except:
                            PrintException("[ERROR] Saving to Database Failed")
                        context = get_context_from_analysis(
                            app_dic,
                            man_data_dic,
                            man_an_dic,
                            code_an_dic,
                            cert_dic,
                            bin_an_buff
                        )
                    else:
                        return HttpResponseRedirect('/zip_format/')
                template = "static_analysis/static_analysis_android_zip.html"
                return render(request, template, context)
            else:
                print "\n[ERROR] Only APK,IPA and Zipped Android/iOS Source code supported now!"
        else:
            return HttpResponseRedirect('/error/')

    except Exception as excep:
        PrintException("[ERROR] Static Analyzer")
        context = {
            'title': 'Error',
            'exp': excep.message,
            'doc': excep.__doc__
        }
        template = "general/error.html"
        return render(request, template, context)
def PDF(request):
    try:
        MD5 = request.GET['md5']
        TYP = request.GET['type']
        m = re.match('^[0-9a-f]{32}$', MD5)
        if m:
            if TYP in ['APK', 'ANDZIP']:
                DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5)
                if DB.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(DB)
                    if TYP == 'APK':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    return HttpResponse(json.dumps({"report": "Report not Found"}),
                                        content_type="application/json; charset=utf-8")
            elif re.findall('IPA|IOSZIP', TYP):
                if TYP == 'IPA':
                    DB = StaticAnalyzerIPA.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'strings': python_list(DB[0].STRINGS),
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
                elif TYP == 'IOSZIP':
                    DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'api': DB[0].HTML,
                            'insecure': DB[0].CODEANAL,
                            'urls': DB[0].URLnFile,
                            'domains': python_dict(DB[0].DOMAINS),
                            'emails': DB[0].EmailnFile,
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
            elif re.findall('APPX', TYP):
                if TYP == 'APPX':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=MD5
                    )
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title': db_entry[0].TITLE,
                            'name': db_entry[0].APP_NAME,
                            'pub_name': db_entry[0].PUB_NAME,
                            'size': db_entry[0].SIZE,
                            'md5': db_entry[0].MD5,
                            'sha1': db_entry[0].SHA1,
                            'sha256': db_entry[0].SHA256,
                            'bin_name': db_entry[0].BINNAME,
                            'version':  db_entry[0].VERSION,
                            'arch':  db_entry[0].ARCH,
                            'compiler_version':  db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':  db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':  db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':  db_entry[0].TARGET_OS,
                            'appx_dll_version':  db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':  db_entry[0].PROJ_GUID,
                            'opti_tool':  db_entry[0].OPTI_TOOL,
                            'target_run':  db_entry[0].TARGET_RUN,
                            'files':  python_list(db_entry[0].FILES),
                            'strings': python_list(db_entry[0].STRINGS),
                            'bin_an_results': python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings': python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                return HttpResponse(json.dumps({"type": "Type is not Allowed"}),
                                    content_type="application/json; charset=utf-8")
            html = template.render(context)
            result = StringIO()
            pdf = pisa.pisaDocument(StringIO("{0}".format(
                html.encode('utf-8'))), result, encoding='utf-8')
            if not pdf.err:
                return HttpResponse(result.getvalue(), content_type='application/pdf')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                content_type="application/json; charset=utf-8")
    except:

        PrintException("[ERROR] PDF Report Generation Error")
        return HttpResponseRedirect('/error/')
def pdf(request, api=False):
    try:
        if api:
            checksum = request.POST['hash']
            scan_type = request.POST['scan_type']
        else:
            checksum = request.GET['md5']
            scan_type = request.GET['type']
        hash_match = re.match('^[0-9a-f]{32}$', checksum)
        if hash_match:
            if scan_type.lower() in ['apk', 'andzip']:
                static_db = StaticAnalyzerAndroid.objects.filter(MD5=checksum)
                if static_db.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(static_db)
                    if scan_type.lower() == 'apk':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    if api:
                        return {"report": "Report not Found"}
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8", status_code=500)
            elif re.findall('ipa|ioszip', scan_type.lower()):
                if scan_type.lower() == 'ipa':
                    static_db = StaticAnalyzerIPA.objects.filter(MD5=checksum)
                    if static_db.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = get_context_from_db_entry_ipa(static_db)
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        if api:
                            return {"report": "Report not Found"}
                        else:
                            return HttpResponse(json.dumps({"report": "Report not Found"}),
                                                content_type="application/json; charset=utf-8", status_code=500)
                elif scan_type.lower() == 'ioszip':
                    static_db = StaticAnalyzerIOSZIP.objects.filter(MD5=checksum)
                    if static_db.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = get_context_from_db_entry_ios(static_db)
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        if api:
                            return {"report": "Report not Found"}
                        else:
                            return HttpResponse(json.dumps({"report": "Report not Found"}),
                                                content_type="application/json; charset=utf-8", status_code=500)
            elif re.findall('appx', scan_type.lower()):
                if scan_type.lower() == 'appx':
                    db_entry = StaticAnalyzerWindows.objects.filter(# pylint: disable-msg=E1101
                        MD5=checksum
                    )
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title': db_entry[0].TITLE,
                            'name': db_entry[0].APP_NAME,
                            'pub_name': db_entry[0].PUB_NAME,
                            'size': db_entry[0].SIZE,
                            'md5': db_entry[0].MD5,
                            'sha1': db_entry[0].SHA1,
                            'sha256': db_entry[0].SHA256,
                            'bin_name': db_entry[0].BINNAME,
                            'version':  db_entry[0].VERSION,
                            'arch':  db_entry[0].ARCH,
                            'compiler_version':  db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':  db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':  db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':  db_entry[0].TARGET_OS,
                            'appx_dll_version':  db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':  db_entry[0].PROJ_GUID,
                            'opti_tool':  db_entry[0].OPTI_TOOL,
                            'target_run':  db_entry[0].TARGET_RUN,
                            'files':  python_list(db_entry[0].FILES),
                            'strings': python_list(db_entry[0].STRINGS),
                            'bin_an_results': python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings': python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                if api:
                    return {"scan_type": "Type is not Allowed"}
                else:
                    return HttpResponse(json.dumps({"type": "Type is not Allowed"}),
                                        content_type="application/json; charset=utf-8", status_code=500)
            html = template.render(context)
            try:
                options = {
                    'page-size': 'A4',
                    'quiet': '',
                    'no-collate': '',
                    'margin-top': '0.50in',
                    'margin-right': '0.50in',
                    'margin-bottom': '0.50in',
                    'margin-left': '0.50in',
                    'encoding': "UTF-8",
                    'custom-header': [
                        ('Accept-Encoding', 'gzip')
                    ],
                    'no-outline': None
                }
                pdf_dat = pdfkit.from_string(html, False, options=options)
                if api:
                    return {"pdf_dat": pdf_dat}
                else:
                    return HttpResponse(pdf_dat, content_type='application/pdf')
            except Exception as exp:
                if api:
                    return {"error": "Cannot Generate PDF", "err_details": str(exp)}
                else:
                    return HttpResponse(json.dumps({"pdf_error": "Cannot Generate PDF",
                                                    "err_details": str(exp)}),
                                        content_type="application/json; charset=utf-8", status_code=500)

        else:
            if api:
                return {"error": "Invalid scan hash"}
            else:
                return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                    content_type="application/json; charset=utf-8", status_code=500)
    except Exception as exp:
        msg = str(exp)
        exp = exp.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
def generic_compare(request, first_hash: str, second_hash: str, api: bool = False):
    # This context consists of specific lists and analysis that is done on the classic ones
    # it will be filled during the different diff analysis
    context = {
        'title': 'Compare report',
        'first_app': dict(),
        'second_app': dict(),
        'urls': dict(),
        'api': dict(),
        'permissions': dict()
    }
    static_fields = ['md5', 'name', 'size', 'icon_found', 'icon_hidden', 'act_count', 'e_act', 'serv_count', 'e_ser',
                     'bro_count', 'e_bro', 'prov_count', 'e_cnt', 'apkid']

    # For now - support only android
    db_entry = StaticAnalyzerAndroid.objects.filter(MD5=first_hash)
    db_entry2 = StaticAnalyzerAndroid.objects.filter(MD5=second_hash)

    if not (db_entry.exists() and db_entry2.exists()):
        return print_n_send_error_response(request,
                                           "One of the Hashes wasn't found in the Android-results DB, make sure "
                                           "both of the apps finished analysis & they are both Android", False)

    # First fetch the already done analysis on each of the apps
    # We don't want to return this whole context back to the user because its a lot of data we don't use
    # it should help the performance I guess
    first_app = deepcopy(get_context_from_db_entry(db_entry))
    second_app = deepcopy(get_context_from_db_entry(db_entry2))

    # Second, fill the mutual static parts that are missing in the classic analysis
    for curr_app, db_context in [('first_app', first_app), ('second_app', second_app)]:

        # format informative title
        context[curr_app]['name_ver'] = "{0} - {1}".format(db_context['packagename'],
                                                           db_context['androvername'])

        # Fill all the static information
        for static_attr in static_fields:
            context[curr_app][static_attr] = db_context[static_attr]

        # Get only the subject of the cert
        subject_regex = re.compile(r'.*Subject:([^<]+)</br>.*', re.DOTALL)
        match = subject_regex.match(db_context['certinfo'])
        if match:
            context[curr_app]['cert_subject'] = match.group(1)
        else:
            context[curr_app]['cert_subject'] = "No subject"

        # Some preparations so we have some sort of same structures
        # (urls are lists inside the list which mess things up...)
        tmp_list = list()
        for url_obj in db_context['urls']:
            for url in url_obj['urls']:
                # urls can mess up the table because they can be really long, so let's cut them
                tmp_url = url[:70]
                while len(url) > 70:
                    url = url[70:]
                    tmp_url += '<br />'
                    tmp_url += url[:70]
                tmp_list.append(tmp_url)

        db_context['urls'] = list(set(deepcopy(tmp_list)))
        tmp_list.clear()

    # apkid check - we do it here just because its really ugly inside the template
    # I split it into these lines just it to be really clear what I'm checking

    first_error = context['first_app']['apkid'].get('error', False)
    second_error = context['second_app']['apkid'].get('error', False)
    first_has_version = context['first_app']['apkid'].get('apkid_version', False)
    second_has_version = context['second_app']['apkid'].get('apkid_version', False)
    context['apkid_error'] = (first_error or not first_has_version) or (second_error or not second_has_version)

    # Third, calculate some diffs
    for section, is_tuples in [
        ('permissions', True),
        ('api', True),
        ('urls', False)
    ]:
        if is_tuples:
            context[section]['mutual'] = [(x, y) for (x, y) in first_app[section].items() if x in
                                          second_app[section].keys()]

            # Only first
            context[section]['only_first'] = [(x, y) for (x, y) in first_app[section].items() if x not in
                                              second_app[section].keys()]

            # Only Second
            context[section]['only_second'] = [(x, y) for (x, y) in second_app[section].items() if x not in
                                               first_app[section].keys()]
        else:
            context[section]['mutual'] = [x for x in first_app[section] if x in
                                          second_app[section]]

            context[section]['only_first'] = [x for x in first_app[section] if x not in
                                              second_app[section]]

            context[section]['only_second'] = [x for x in second_app[section] if x not in
                                               first_app[section]]

    template = "static_analysis/compare.html"
    if api:
        return context
    else:
        return render(request, template, context)
def static_analyzer(request, api=False):
    """Do static analysis on an request and save to db."""
    try:
        if api:
            typ = request.POST['scan_type']
            checksum = request.POST['hash']
            filename = request.POST['file_name']
            rescan = str(request.POST.get('re_scan', 0))
        else:
            typ = request.GET['type']
            checksum = request.GET['checksum']
            filename = request.GET['name']
            rescan = str(request.GET.get('rescan', 0))
        # Input validation
        app_dic = {}
        match = re.match('^[0-9a-f]{32}$', checksum)
        if (
                (
                    match
                ) and (
                    filename.lower().endswith('.apk') or
                    filename.lower().endswith('.zip')
                ) and (
                    typ in ['zip', 'apk']
                )
        ):
            app_dic['dir'] = settings.BASE_DIR  # BASE DIR
            app_dic['app_name'] = filename  # APP ORGINAL NAME
            app_dic['md5'] = checksum  # MD5
            app_dic['app_dir'] = os.path.join(settings.UPLD_DIR, app_dic[
                                              'md5'] + '/')  # APP DIRECTORY
            app_dic['tools_dir'] = os.path.join(
                app_dic['dir'], 'StaticAnalyzer/tools/')  # TOOLS DIR
            # DWD_DIR = settings.DWD_DIR # not needed? Var is never used.
            logger.info("Starting Analysis on : " + app_dic['app_name'])

            if typ == 'apk':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic['app_file'] = app_dic[
                        'md5'] + '.apk'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH

                    # ANALYSIS BEGINS
                    app_dic['size'] = str(
                        file_size(app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic[
                        'sha256'] = hash_gen(app_dic['app_path'])

                    app_dic['files'] = unzip(
                        app_dic['app_path'], app_dic['app_dir'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
                                                                   'files'])

                    logger.info("APK Extracted")

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_path'],
                        app_dic['app_dir'],
                        app_dic['tools_dir'],
                        '',
                        True
                    )

                    # Get icon
                    res_path = os.path.join(app_dic['app_dir'], 'res')
                    app_dic['icon_hidden'] = True
                    # Even if the icon is hidden, try to guess it by the
                    # default paths
                    app_dic['icon_found'] = False
                    app_dic['icon_path'] = ''
                    # TODO: Check for possible different names for resource
                    # folder?
                    if os.path.exists(res_path):
                        icon_dic = get_icon(
                            app_dic['app_path'], res_path)
                        if icon_dic:
                            app_dic['icon_hidden'] = icon_dic['hidden']
                            app_dic['icon_found'] = bool(icon_dic['path'])
                            app_dic['icon_path'] = icon_dic['path']

                    # Set Manifest link
                    app_dic['mani'] = '../ManifestView/?md5=' + \
                        app_dic['md5'] + '&type=apk&bin=1'
                    man_data_dic = manifest_data(app_dic['parsed_xml'])
                    app_dic['playstore'] = get_app_details(
                        man_data_dic['packagename'])
                    man_an_dic = manifest_analysis(
                        app_dic['parsed_xml'],
                        man_data_dic
                    )
                    bin_an_buff = []
                    bin_an_buff += elf_analysis(app_dic['app_dir'])
                    bin_an_buff += res_analysis(app_dic['app_dir'])
                    cert_dic = cert_info(
                        app_dic['app_dir'], app_dic['app_file'], app_dic['tools_dir'])
                    apkid_results = apkid_analysis(app_dic[
                        'app_dir'], app_dic['app_path'], app_dic['app_name'])
                    dex_2_jar(app_dic['app_path'], app_dic[
                              'app_dir'], app_dic['tools_dir'])
                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])
                    jar_2_java(app_dic['app_dir'], app_dic['tools_dir'])
                    code_an_dic = code_analysis(
                        app_dic['app_dir'],
                        man_an_dic['permissons'],
                        "apk"
                    )

                    # Get the strings
                    string_res = strings_jar(
                        app_dic['app_file'],
                        app_dic['app_dir']
                    )
                    if string_res:
                        app_dic['strings'] = string_res['strings']
                        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'] = []

                    # 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"] = malware_check(
                        list(set(code_an_dic["urls_list"])))

                    logger.info("Generating Java and Smali Downloads")
                    gen_downloads(app_dic['app_dir'], app_dic[
                                  'md5'], app_dic['icon_path'])
                    app_dic['zipped'] = '&type=apk'

                    logger.info("Connecting to Database")
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            logger.info("Updating Database...")
                            update_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                            )
                            update_scan_timestamp(app_dic['md5'])
                        elif rescan == '0':
                            logger.info("Saving to Database")
                            create_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                            )
                    except:
                        PrintException("Saving to Database Failed")
                    context = get_context_from_analysis(
                        app_dic,
                        man_data_dic,
                        man_an_dic,
                        code_an_dic,
                        cert_dic,
                        bin_an_buff,
                        apkid_results,
                    )
                context["average_cvss"], context[
                    "security_score"] = score(context["findings"])
                context['dynamic_analysis_done'] = os.path.exists(
                    os.path.join(app_dic['app_dir'], 'logcat.txt'))

                context['VT_RESULT'] = None
                if settings.VT_ENABLED:
                    vt = VirusTotal.VirusTotal()
                    context['VT_RESULT'] = vt.get_result(
                        os.path.join(app_dic['app_dir'],
                                     app_dic['md5']) + '.apk',
                        app_dic['md5']
                    )
                template = "static_analysis/android_binary_analysis.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            elif typ == 'zip':
                # Check if in DB
                # pylint: disable=E1101
                cert_dic = {}
                cert_dic['cert_info'] = ''
                cert_dic['issued'] = ''
                cert_dic['sha256Digest'] = False
                bin_an_buff = []
                app_dic['strings'] = ''
                app_dic['zipped'] = ''
                # Above fields are only available for APK and not ZIP
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic['app_file'] = app_dic[
                        'md5'] + '.zip'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH
                    logger.info("Extracting ZIP")
                    app_dic['files'] = unzip(
                        app_dic['app_path'], app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        logger.info("Redirecting to iOS Source Code Analyzer")
                        if api:
                            return {"type": "ios"}
                        else:
                            return HttpResponseRedirect(
                                '/StaticAnalyzer_iOS/?name=' + app_dic['app_name'] +
                                '&type=ios&checksum=' + app_dic['md5']
                            )
                    app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
                                                                   'files'])
                    app_dic['zipped'] = pro_type
                    logger.info("ZIP Type - " + pro_type)
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(
                            file_size(app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic[
                            'sha256'] = hash_gen(app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            "",
                            app_dic['app_dir'],
                            app_dic['tools_dir'],
                            pro_type,
                            False
                        )

                        # Set manifest view link
                        app_dic['mani'] = (
                            '../ManifestView/?md5=' +
                            app_dic['md5'] + '&type=' + pro_type + '&bin=0'
                        )

                        man_data_dic = manifest_data(app_dic['persed_xml'])
                        app_dic['playstore'] = get_app_details(
                            man_data_dic['packagename'])
                        man_an_dic = manifest_analysis(
                            app_dic['persed_xml'],
                            man_data_dic
                        )
                        # Get icon
                        eclipse_res_path = os.path.join(
                            app_dic['app_dir'], 'res')
                        studio_res_path = os.path.join(
                            app_dic['app_dir'], 'app', 'src', 'main', 'res')
                        if os.path.exists(eclipse_res_path):
                            res_path = eclipse_res_path
                        elif os.path.exists(studio_res_path):
                            res_path = studio_res_path
                        else:
                            res_path = ''

                        app_dic['icon_hidden'] = man_an_dic['icon_hidden']
                        app_dic['icon_found'] = False
                        app_dic['icon_path'] = ''
                        if res_path:
                            app_dic['icon_path'] = find_icon_path_zip(
                                res_path, man_data_dic['icons'])
                            if app_dic['icon_path']:
                                app_dic['icon_found'] = True

                        if app_dic['icon_path']:
                            if os.path.exists(app_dic['icon_path']):
                                shutil.copy2(app_dic['icon_path'], os.path.join(
                                    settings.DWD_DIR, app_dic['md5'] + '-icon.png'))

                        code_an_dic = code_analysis(
                            app_dic['app_dir'],
                            man_an_dic['permissons'],
                            pro_type
                        )
                        # 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"] = malware_check(
                            list(set(code_an_dic["urls_list"])))
                        logger.info("Connecting to Database")
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                logger.info("Updating Database...")
                                update_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                )
                                update_scan_timestamp(app_dic['md5'])
                            elif rescan == '0':
                                logger.info("Saving to Database")
                                create_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                )
                        except:
                            PrintException("Saving to Database Failed")
                        context = get_context_from_analysis(
                            app_dic,
                            man_data_dic,
                            man_an_dic,
                            code_an_dic,
                            cert_dic,
                            bin_an_buff,
                            {},
                        )
                    else:
                        msg = "This ZIP Format is not supported"
                        if api:
                            return print_n_send_error_response(request, msg, True)
                        else:
                            print_n_send_error_response(request, msg, False)
                            return HttpResponseRedirect('/zip_format/')
                context["average_cvss"], context[
                    "security_score"] = score(context["findings"])
                template = "static_analysis/android_source_analysis.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            else:
                logger.error(
                    "Only APK,IPA and Zipped Android/iOS Source code supported now!")
        else:
            msg = "Hash match failed or Invalid file extension or file type"
            if api:
                return print_n_send_error_response(request, msg, True)
            else:
                return print_n_send_error_response(request, msg, False)

    except Exception as excep:
        msg = str(excep)
        exp = excep.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
def PDF(request):
    try:
        MD5 = request.GET['md5']
        TYP = request.GET['type']
        m = re.match('^[0-9a-f]{32}$', MD5)
        if m:
            if TYP in ['APK', 'ANDZIP']:
                DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5)
                if DB.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(DB)
                    if TYP == 'APK':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    return HttpResponse(json.dumps({"report": "Report not Found"}),
                                        content_type="application/json; charset=utf-8")
            elif re.findall('IPA|IOSZIP', TYP):
                if TYP == 'IPA':
                    DB = StaticAnalyzerIPA.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = get_context_from_db_entry_ipa(DB)
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
                elif TYP == 'IOSZIP':
                    DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = get_context_from_db_entry_ios(DB)
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        return HttpResponse(json.dumps({"report": "Report not Found"}),
                                            content_type="application/json; charset=utf-8")
            elif re.findall('APPX', TYP):
                if TYP == 'APPX':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=MD5
                    )
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title': db_entry[0].TITLE,
                            'name': db_entry[0].APP_NAME,
                            'pub_name': db_entry[0].PUB_NAME,
                            'size': db_entry[0].SIZE,
                            'md5': db_entry[0].MD5,
                            'sha1': db_entry[0].SHA1,
                            'sha256': db_entry[0].SHA256,
                            'bin_name': db_entry[0].BINNAME,
                            'version':  db_entry[0].VERSION,
                            'arch':  db_entry[0].ARCH,
                            'compiler_version':  db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':  db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':  db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':  db_entry[0].TARGET_OS,
                            'appx_dll_version':  db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':  db_entry[0].PROJ_GUID,
                            'opti_tool':  db_entry[0].OPTI_TOOL,
                            'target_run':  db_entry[0].TARGET_RUN,
                            'files':  python_list(db_entry[0].FILES),
                            'strings': python_list(db_entry[0].STRINGS),
                            'bin_an_results': python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings': python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                return HttpResponse(json.dumps({"type": "Type is not Allowed"}),
                                    content_type="application/json; charset=utf-8")
            html = template.render(context)
            try:
                options = {
                    'page-size': 'A4',
                    'quiet': '',
                    'no-collate': '',
                    'margin-top': '0.50in',
                    'margin-right': '0.50in',
                    'margin-bottom': '0.50in',
                    'margin-left': '0.50in',
                    'encoding': "UTF-8",
                    'custom-header': [
                        ('Accept-Encoding', 'gzip')
                    ],
                    'no-outline': None
                }
                pdf = pdfkit.from_string(html, False, options=options)
                return HttpResponse(pdf, content_type='application/pdf')
            except Exception as exp:
                return HttpResponse(json.dumps({"pdf_error": "Cannot Generate PDF",
                                                "err_details": str(exp)}),
                                    content_type="application/json; charset=utf-8")

        else:
            return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                content_type="application/json; charset=utf-8")
    except:

        PrintException("[ERROR] PDF Report Generation Error")
        return HttpResponseRedirect('/error/')
示例#14
0
def pdf(request, api=False):
    try:
        if api:
            checksum = request.POST['hash']
            scan_type = request.POST['scan_type']
        else:
            checksum = request.GET['md5']
            scan_type = request.GET['type']
        hash_match = re.match('^[0-9a-f]{32}$', checksum)
        if hash_match:
            if scan_type.lower() in ['apk', 'andzip']:
                static_db = StaticAnalyzerAndroid.objects.filter(MD5=checksum)
                if static_db.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(static_db)
                    if scan_type.lower() == 'apk':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    if api:
                        return {"report": "Report not Found"}
                    else:
                        return HttpResponse(
                            json.dumps({"report": "Report not Found"}),
                            content_type="application/json; charset=utf-8",
                            status=500)
            elif re.findall('ipa|ioszip', scan_type.lower()):
                if scan_type.lower() == 'ipa':
                    static_db = StaticAnalyzerIPA.objects.filter(MD5=checksum)
                    if static_db.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = get_context_from_db_entry_ipa(static_db)
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        if api:
                            return {"report": "Report not Found"}
                        else:
                            return HttpResponse(
                                json.dumps({"report": "Report not Found"}),
                                content_type="application/json; charset=utf-8",
                                status=500)
                elif scan_type.lower() == 'ioszip':
                    static_db = StaticAnalyzerIOSZIP.objects.filter(
                        MD5=checksum)
                    if static_db.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = get_context_from_db_entry_ios(static_db)
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        if api:
                            return {"report": "Report not Found"}
                        else:
                            return HttpResponse(
                                json.dumps({"report": "Report not Found"}),
                                content_type="application/json; charset=utf-8",
                                status=500)
            elif re.findall('appx', scan_type.lower()):
                if scan_type.lower() == 'appx':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=checksum)
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title':
                            db_entry[0].TITLE,
                            'name':
                            db_entry[0].APP_NAME,
                            'pub_name':
                            db_entry[0].PUB_NAME,
                            'size':
                            db_entry[0].SIZE,
                            'md5':
                            db_entry[0].MD5,
                            'sha1':
                            db_entry[0].SHA1,
                            'sha256':
                            db_entry[0].SHA256,
                            'bin_name':
                            db_entry[0].BINNAME,
                            'version':
                            db_entry[0].VERSION,
                            'arch':
                            db_entry[0].ARCH,
                            'compiler_version':
                            db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':
                            db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':
                            db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':
                            db_entry[0].TARGET_OS,
                            'appx_dll_version':
                            db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':
                            db_entry[0].PROJ_GUID,
                            'opti_tool':
                            db_entry[0].OPTI_TOOL,
                            'target_run':
                            db_entry[0].TARGET_RUN,
                            'files':
                            python_list(db_entry[0].FILES),
                            'strings':
                            python_list(db_entry[0].STRINGS),
                            'bin_an_results':
                            python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings':
                            python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                if api:
                    return {"scan_type": "Type is not Allowed"}
                else:
                    return HttpResponse(
                        json.dumps({"type": "Type is not Allowed"}),
                        content_type="application/json; charset=utf-8",
                        status=500)

            context['VT_RESULT'] = None
            if settings.VT_ENABLED:
                app_dir = os.path.join(settings.UPLD_DIR, checksum + '/')
                vt = VirusTotal.VirusTotal()
                context['VT_RESULT'] = vt.get_result(
                    os.path.join(app_dir, checksum) + '.' + scan_type.lower(),
                    checksum)

            html = template.render(context)
            try:
                options = {
                    'page-size': 'A4',
                    'quiet': '',
                    'no-collate': '',
                    'margin-top': '0.50in',
                    'margin-right': '0.50in',
                    'margin-bottom': '0.50in',
                    'margin-left': '0.50in',
                    'encoding': "UTF-8",
                    'custom-header': [('Accept-Encoding', 'gzip')],
                    'no-outline': None
                }

                BASE_DIR = os.path.dirname(
                    os.path.dirname(os.path.dirname(
                        os.path.abspath(__file__))))
                path_wk = os.path.join(BASE_DIR,
                                       'windows/wkhtmltopdf/wkhtmltopdf.exe')
                # path_wk = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'  # 安装位置
                config = pdfkit.configuration(wkhtmltopdf=path_wk)
                pdf_dat = pdfkit.from_string(html,
                                             False,
                                             options=options,
                                             configuration=config)
                if api:
                    return {"pdf_dat": pdf_dat}
                else:
                    return HttpResponse(pdf_dat,
                                        content_type='application/pdf')
            except Exception as exp:
                if api:
                    return {
                        "error": "Cannot Generate PDF",
                        "err_details": str(exp)
                    }
                else:
                    return HttpResponse(
                        json.dumps({
                            "pdf_error": "Cannot Generate PDF",
                            "err_details": str(exp)
                        }),
                        content_type="application/json; charset=utf-8",
                        status=500)

        else:
            if api:
                return {"error": "Invalid scan hash"}
            else:
                return HttpResponse(
                    json.dumps({"md5": "Invalid MD5"}),
                    content_type="application/json; charset=utf-8",
                    status=500)
    except Exception as exp:
        msg = str(exp)
        exp = exp.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
示例#15
0
def XML(request):
    try:
        MD5 = request.GET['md5']
        TYP = request.GET['type']
        m = re.match('^[0-9a-f]{32}$', MD5)
        if m:
            if TYP in ['APK', 'ANDZIP']:
                DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5)
                if DB.exists():
                    print "\n[INFO] Fetching data from DB for PDF Report Generation (Android)"
                    context = get_context_from_db_entry(DB)
                    if TYP == 'APK':
                        template = get_template("pdf/static_analysis_pdf.html")
                    else:
                        template = get_template(
                            "pdf/static_analysis_zip_pdf.html")
                else:
                    return HttpResponse(
                        json.dumps({"report": "Report not Found"}),
                        content_type="application/json; charset=utf-8")
            elif re.findall('IPA|IOSZIP', TYP):
                if TYP == 'IPA':
                    DB = StaticAnalyzerIPA.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS IPA)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'strings': python_list(DB[0].STRINGS),
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_binary_analysis_pdf.html")
                    else:
                        return HttpResponse(
                            json.dumps({"report": "Report not Found"}),
                            content_type="application/json; charset=utf-8")
                elif TYP == 'IOSZIP':
                    DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5)
                    if DB.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (IOS ZIP)"
                        context = {
                            'title': DB[0].TITLE,
                            'name': DB[0].APPNAMEX,
                            'size': DB[0].SIZE,
                            'md5': DB[0].MD5,
                            'sha1': DB[0].SHA1,
                            'sha256': DB[0].SHA256,
                            'plist': DB[0].INFOPLIST,
                            'bin_name': DB[0].BINNAME,
                            'id': DB[0].IDF,
                            'ver': DB[0].VERSION,
                            'sdk': DB[0].SDK,
                            'pltfm': DB[0].PLTFM,
                            'min': DB[0].MINX,
                            'bin_anal': DB[0].BIN_ANAL,
                            'libs': DB[0].LIBS,
                            'files': python_list(DB[0].FILES),
                            'file_analysis': DB[0].SFILESX,
                            'api': DB[0].HTML,
                            'insecure': DB[0].CODEANAL,
                            'urls': DB[0].URLnFile,
                            'domains': python_dict(DB[0].DOMAINS),
                            'emails': DB[0].EmailnFile,
                            'permissions': python_list(DB[0].PERMISSIONS)
                        }
                        template = get_template(
                            "pdf/ios_source_analysis_pdf.html")
                    else:
                        return HttpResponse(
                            json.dumps({"report": "Report not Found"}),
                            content_type="application/json; charset=utf-8")
            elif re.findall('APPX', TYP):
                if TYP == 'APPX':
                    db_entry = StaticAnalyzerWindows.objects.filter(  # pylint: disable-msg=E1101
                        MD5=MD5)
                    if db_entry.exists():
                        print "\n[INFO] Fetching data from DB for PDF Report Generation (APPX)"

                        context = {
                            'title':
                            db_entry[0].TITLE,
                            'name':
                            db_entry[0].APP_NAME,
                            'pub_name':
                            db_entry[0].PUB_NAME,
                            'size':
                            db_entry[0].SIZE,
                            'md5':
                            db_entry[0].MD5,
                            'sha1':
                            db_entry[0].SHA1,
                            'sha256':
                            db_entry[0].SHA256,
                            'bin_name':
                            db_entry[0].BINNAME,
                            'version':
                            db_entry[0].VERSION,
                            'arch':
                            db_entry[0].ARCH,
                            'compiler_version':
                            db_entry[0].COMPILER_VERSION,
                            'visual_studio_version':
                            db_entry[0].VISUAL_STUDIO_VERSION,
                            'visual_studio_edition':
                            db_entry[0].VISUAL_STUDIO_EDITION,
                            'target_os':
                            db_entry[0].TARGET_OS,
                            'appx_dll_version':
                            db_entry[0].APPX_DLL_VERSION,
                            'proj_guid':
                            db_entry[0].PROJ_GUID,
                            'opti_tool':
                            db_entry[0].OPTI_TOOL,
                            'target_run':
                            db_entry[0].TARGET_RUN,
                            'files':
                            python_list(db_entry[0].FILES),
                            'strings':
                            python_list(db_entry[0].STRINGS),
                            'bin_an_results':
                            python_list(db_entry[0].BIN_AN_RESULTS),
                            'bin_an_warnings':
                            python_list(db_entry[0].BIN_AN_WARNINGS)
                        }
                        template = get_template(
                            "pdf/windows_binary_analysis_pdf.html")
            else:
                return HttpResponse(
                    json.dumps({"type": "Type is not Allowed"}),
                    content_type="application/json; charset=utf-8")
            html = template.render(context)

            memorandum = etree.Element("memorandum")

            etree.SubElement(
                memorandum, "titul"
            ).text = context.get("title") + " - " + context.get("name")
            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "fileInformation")
            etree.SubElement(precuinat, "title").text = "File Information"
            etree.SubElement(precuinat, "nom").text = context.get("name")
            etree.SubElement(precuinat, "tam").text = context.get("size")
            etree.SubElement(precuinat, "md5").text = context.get("md5")
            etree.SubElement(precuinat, "sha1").text = context.get("sha1")
            etree.SubElement(precuinat, "sha256").text = context.get("sha256")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "appInformation")
            etree.SubElement(precuinat, "title").text = "App Information"
            etree.SubElement(precuinat,
                             "packagename").text = context.get("packagename")
            etree.SubElement(precuinat,
                             "mainactivity").text = context.get("mainactivity")
            etree.SubElement(precuinat,
                             "targetsdk").text = context.get("targetsdk")
            etree.SubElement(precuinat, "minsdk").text = context.get("minsdk")
            etree.SubElement(precuinat, "maxsdk").text = context.get("maxsdk")
            etree.SubElement(precuinat,
                             "androvername").text = context.get("androvername")
            etree.SubElement(precuinat,
                             "androver").text = context.get("androver")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "codeNature")
            etree.SubElement(precuinat, "title").text = "Code Nature"
            etree.SubElement(precuinat, "native").text = context.get("native")
            etree.SubElement(precuinat,
                             "dynamic").text = context.get("dynamic")
            etree.SubElement(precuinat,
                             "reflection").text = context.get("reflection")
            etree.SubElement(precuinat, "crypto").text = context.get("crypto")
            etree.SubElement(precuinat, "obfus").text = context.get("obfus")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "certificate")
            etree.SubElement(precuinat, "title").text = "Certificate"
            etree.SubElement(precuinat,
                             "certinfo").text = context.get("certinfo")
            etree.SubElement(
                precuinat,
                "issued").text = "Certificate Status: " + context.get("issued")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "permissions")
            etree.SubElement(precuinat, "title").text = "Permissions"
            dic = context.get("permissions")

            for perm, desc in dic.items():
                etree.SubElement(
                    precuinat,
                    "perm").text = "PERMISSION: " + perm + " " + desc[0]
                etree.SubElement(precuinat, "info").text = "INFO: " + desc[1]
                etree.SubElement(
                    precuinat, "description").text = "DESCRIPTION: " + desc[2]

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "SOLibraryBinaryAnalis")
            etree.SubElement(precuinat,
                             "title").text = "ANDROID LIBRARY BINARY ANALYSIS"
            dic = context.get("binary_analysis")
            dic2 = dic[0]
            for i, j in dic2.items():
                etree.SubElement(precuinat, "key").text = i
                etree.SubElement(precuinat, "value").text = j

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "brossableActivities")
            etree.SubElement(precuinat, "title").text = "Brossable Activities"
            dic = context.get("browsable_activities")

            for i, j in dic.items():
                etree.SubElement(precuinat, "activity").text = "ACTIVITY " + i
                etree.SubElement(precuinat, "intent").text = "INTENT " + j

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "manifestAnalysis")
            etree.SubElement(precuinat, "title").text = "Manifest Analysis"
            dic = context.get("manifest")

            for p in dic:
                for i, j in p.items():
                    etree.SubElement(precuinat, "key").text = i
                    etree.SubElement(precuinat, "value").text = j

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "codeAnalysis")
            etree.SubElement(precuinat, "title").text = "Code Analysis"
            etree.SubElement(precuinat, "contenido").text = context.get("dang")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "AndroidAPI")
            etree.SubElement(precuinat, "title").text = "Android API"
            etree.SubElement(precuinat, "contenido").text = context.get("api")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "urls")
            etree.SubElement(precuinat, "title").text = "URLS"
            etree.SubElement(precuinat, "contenido").text = context.get("urls")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "malwareChecks")
            etree.SubElement(precuinat, "title").text = "Malware Checks"
            dic = context.get("domain")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "emails")
            etree.SubElement(precuinat, "title").text = "Emails"
            etree.SubElement(precuinat,
                             "contenido").text = context.get("emails")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "fileAnalysis")
            etree.SubElement(precuinat, "title").text = "File Analysis"
            etree.SubElement(precuinat,
                             "contenido").text = context.get("certz")

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "strings")
            etree.SubElement(precuinat, "title").text = "Strings"
            list = context.get("strings")
            for var in list:
                etree.SubElement(precuinat, "strings").text = var

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "activities")
            etree.SubElement(precuinat, "title").text = "Activities"
            list = context.get("activities")

            for act in list:
                etree.SubElement(precuinat, "activity").text = act

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "providers")
            etree.SubElement(precuinat, "title").text = "Providers"
            list = context.get("providers")
            for prov in list:
                etree.SubElement(precuinat, "provider").text = prov

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "receivers")
            etree.SubElement(precuinat, "title").text = "Receivers"
            list = context.get("receivers")
            for rec in list:
                etree.SubElement(precuinat, "receiver").text = rec

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "services")
            etree.SubElement(precuinat, "title").text = "Services"
            list = context.get("services")
            for ser in list:
                etree.SubElement(precuinat, "service").text = ser

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "libraries")
            etree.SubElement(precuinat, "title").text = "Libraries"
            list = context.get("libraries")
            for lib in list:
                etree.SubElement(precuinat, "library").text = lib

            precuinat = etree.SubElement(memorandum, "precuinat")
            precuinat.set("category", "files")
            etree.SubElement(precuinat, "title").text = "Files"
            list = context.get("files")
            for f in list:
                etree.SubElement(precuinat, "file").text = f

            g = open('./xml/t.xml', 'w')
            g.write('<?xml version="1.0"?>')
            # print(etree.tostring(memorandum, xml_declaration=True, encoding = 'iso-8859-1'))
            g.write(etree.tostring(memorandum))
            g.close()

            g = open('./xml/t.xml', 'r')
            response = HttpResponse(g,
                                    content_type='application/force-download')
            response['Content-Disposition'] = 'attachment; filename=t.xml'
            g.close()
            return response

        else:
            return HttpResponse(json.dumps({"md5": "Invalid MD5"}),
                                content_type="application/json; charset=utf-8")
    except:

        PrintException("[ERROR] XML Report Generation Error")
        return HttpResponseRedirect('/error/')
def static_analyzer(request, api=False):
    """Do static analysis on an request and save to db."""
    try:
        if api:
            typ = request.POST['scan_type']
            checksum = request.POST['hash']
            filename = request.POST['file_name']
            rescan = str(request.POST.get('re_scan', 0))
        else:
            typ = request.GET['type']
            checksum = request.GET['checksum']
            filename = request.GET['name']
            rescan = str(request.GET.get('rescan', 0))
        # Input validation
        app_dic = {}
        match = re.match('^[0-9a-f]{32}$', checksum)
        if ((match) and (filename.lower().endswith('.apk')
                         or filename.lower().endswith('.zip'))
                and (typ in ['zip', 'apk'])):
            app_dic['dir'] = settings.BASE_DIR  # BASE DIR
            app_dic['app_name'] = filename  # APP ORGINAL NAME
            app_dic['md5'] = checksum  # MD5
            app_dic['app_dir'] = os.path.join(
                settings.UPLD_DIR, app_dic['md5'] + '/')  # APP DIRECTORY
            app_dic['tools_dir'] = os.path.join(
                app_dic['dir'], 'StaticAnalyzer/tools/')  # TOOLS DIR
            # DWD_DIR = settings.DWD_DIR # not needed? Var is never used.
            logger.info("Starting Analysis on : " + app_dic['app_name'])

            if typ == 'apk':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.apk'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH

                    # ANALYSIS BEGINS
                    app_dic['size'] = str(file_size(
                        app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic['sha256'] = hash_gen(
                        app_dic['app_path'])

                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    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)
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])

                    logger.info("APK Extracted")

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_path'], app_dic['app_dir'],
                        app_dic['tools_dir'], '', True)

                    # Get icon
                    res_path = os.path.join(app_dic['app_dir'], 'res')
                    app_dic['icon_hidden'] = True
                    # Even if the icon is hidden, try to guess it by the
                    # default paths
                    app_dic['icon_found'] = False
                    app_dic['icon_path'] = ''
                    # TODO: Check for possible different names for resource
                    # folder?
                    if os.path.exists(res_path):
                        icon_dic = get_icon(app_dic['app_path'], res_path)
                        if icon_dic:
                            app_dic['icon_hidden'] = icon_dic['hidden']
                            app_dic['icon_found'] = bool(icon_dic['path'])
                            app_dic['icon_path'] = icon_dic['path']

                    # Set Manifest link
                    app_dic['mani'] = '../ManifestView/?md5=' + \
                        app_dic['md5'] + '&type=apk&bin=1'
                    man_data_dic = manifest_data(app_dic['parsed_xml'])
                    app_dic['playstore'] = get_app_details(
                        man_data_dic['packagename'])
                    man_an_dic = manifest_analysis(app_dic['parsed_xml'],
                                                   man_data_dic)
                    bin_an_buff = []
                    bin_an_buff += elf_analysis(app_dic['app_dir'])
                    bin_an_buff += res_analysis(app_dic['app_dir'])
                    cert_dic = cert_info(app_dic['app_dir'],
                                         app_dic['app_file'],
                                         app_dic['tools_dir'])
                    apkid_results = apkid_analysis(app_dic['app_dir'],
                                                   app_dic['app_path'],
                                                   app_dic['app_name'])
                    tracker = Trackers.Trackers(app_dic['app_dir'],
                                                app_dic['tools_dir'])
                    tracker_res = tracker.get_trackers()
                    dex_2_jar(app_dic['app_path'], app_dic['app_dir'],
                              app_dic['tools_dir'])
                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])
                    jar_2_java(app_dic['app_dir'], app_dic['tools_dir'])
                    code_an_dic = code_analysis(app_dic['app_dir'],
                                                man_an_dic['permissons'],
                                                "apk")

                    # Get the strings
                    string_res = strings_jar(app_dic['app_file'],
                                             app_dic['app_dir'])
                    if string_res:
                        app_dic['strings'] = string_res['strings']
                        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'] = []

                    # 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"] = malware_check(
                        list(set(code_an_dic["urls_list"])))

                    logger.info("Generating Java and Smali Downloads")
                    gen_downloads(app_dic['app_dir'], app_dic['md5'],
                                  app_dic['icon_path'])
                    app_dic['zipped'] = '&type=apk'

                    logger.info("Connecting to Database")
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            logger.info("Updating Database...")
                            update_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                                tracker_res,
                            )
                            update_scan_timestamp(app_dic['md5'])
                        elif rescan == '0':
                            logger.info("Saving to Database")
                            create_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                                tracker_res,
                            )
                    except:
                        PrintException("Saving to Database Failed")
                    context = get_context_from_analysis(
                        app_dic,
                        man_data_dic,
                        man_an_dic,
                        code_an_dic,
                        cert_dic,
                        bin_an_buff,
                        apkid_results,
                        tracker_res,
                    )
                context["average_cvss"], context["security_score"] = score(
                    context["findings"])
                context['dynamic_analysis_done'] = os.path.exists(
                    os.path.join(app_dic['app_dir'], 'logcat.txt'))

                context['VT_RESULT'] = None
                if settings.VT_ENABLED:
                    vt = VirusTotal.VirusTotal()
                    context['VT_RESULT'] = vt.get_result(
                        os.path.join(app_dic['app_dir'], app_dic['md5']) +
                        '.apk', app_dic['md5'])
                template = "static_analysis/android_binary_analysis.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            elif typ == 'zip':
                # Check if in DB
                # pylint: disable=E1101
                cert_dic = {}
                cert_dic['cert_info'] = ''
                cert_dic['issued'] = ''
                cert_dic['sha256Digest'] = False
                bin_an_buff = []
                app_dic['strings'] = ''
                app_dic['zipped'] = ''
                # Above fields are only available for APK and not ZIP
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.zip'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH
                    logger.info("Extracting ZIP")
                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        logger.info("Redirecting to iOS Source Code Analyzer")
                        if api:
                            return {"type": "ios"}
                        else:
                            return HttpResponseRedirect(
                                '/StaticAnalyzer_iOS/?name=' +
                                app_dic['app_name'] + '&type=ios&checksum=' +
                                app_dic['md5'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])
                    app_dic['zipped'] = pro_type
                    logger.info("ZIP Type - " + pro_type)
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(file_size(
                            app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic['sha256'] = hash_gen(
                            app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            "", app_dic['app_dir'], app_dic['tools_dir'],
                            pro_type, False)

                        # Set manifest view link
                        app_dic['mani'] = ('../ManifestView/?md5=' +
                                           app_dic['md5'] + '&type=' +
                                           pro_type + '&bin=0')

                        man_data_dic = manifest_data(app_dic['persed_xml'])
                        app_dic['playstore'] = get_app_details(
                            man_data_dic['packagename'])
                        man_an_dic = manifest_analysis(app_dic['persed_xml'],
                                                       man_data_dic)
                        # Get icon
                        eclipse_res_path = os.path.join(
                            app_dic['app_dir'], 'res')
                        studio_res_path = os.path.join(app_dic['app_dir'],
                                                       'app', 'src', 'main',
                                                       'res')
                        if os.path.exists(eclipse_res_path):
                            res_path = eclipse_res_path
                        elif os.path.exists(studio_res_path):
                            res_path = studio_res_path
                        else:
                            res_path = ''

                        app_dic['icon_hidden'] = man_an_dic['icon_hidden']
                        app_dic['icon_found'] = False
                        app_dic['icon_path'] = ''
                        if res_path:
                            app_dic['icon_path'] = find_icon_path_zip(
                                res_path, man_data_dic['icons'])
                            if app_dic['icon_path']:
                                app_dic['icon_found'] = True

                        if app_dic['icon_path']:
                            if os.path.exists(app_dic['icon_path']):
                                shutil.copy2(
                                    app_dic['icon_path'],
                                    os.path.join(settings.DWD_DIR,
                                                 app_dic['md5'] + '-icon.png'))

                        code_an_dic = code_analysis(app_dic['app_dir'],
                                                    man_an_dic['permissons'],
                                                    pro_type)
                        # 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"] = malware_check(
                            list(set(code_an_dic["urls_list"])))
                        logger.info("Connecting to Database")
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                logger.info("Updating Database...")
                                update_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                    {},
                                )
                                update_scan_timestamp(app_dic['md5'])
                            elif rescan == '0':
                                logger.info("Saving to Database")
                                create_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                    {},
                                )
                        except:
                            PrintException("Saving to Database Failed")
                        context = get_context_from_analysis(
                            app_dic,
                            man_data_dic,
                            man_an_dic,
                            code_an_dic,
                            cert_dic,
                            bin_an_buff,
                            {},
                            {},
                        )
                    else:
                        msg = "This ZIP Format is not supported"
                        if api:
                            return print_n_send_error_response(
                                request, msg, True)
                        else:
                            print_n_send_error_response(request, msg, False)
                            return HttpResponseRedirect('/zip_format/')
                context["average_cvss"], context["security_score"] = score(
                    context["findings"])
                template = "static_analysis/android_source_analysis.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            else:
                logger.error(
                    "Only APK,IPA and Zipped Android/iOS Source code supported now!"
                )
        else:
            msg = "Hash match failed or Invalid file extension or file type"
            if api:
                return print_n_send_error_response(request, msg, True)
            else:
                return print_n_send_error_response(request, msg, False)

    except Exception as excep:
        msg = str(excep)
        exp = excep.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)
def static_analyzer(request, api=False):
    """Do static analysis on an request and save to db."""
    try:
        if api:
            typ = request.POST['scan_type']
            checksum = request.POST['hash']
            filename = request.POST['file_name']
            rescan = str(request.POST.get('re_scan', 0))
        else:
            typ = request.GET['type']
            checksum = request.GET['checksum']
            filename = request.GET['name']
            rescan = str(request.GET.get('rescan', 0))
        # Input validation
        app_dic = {}
        match = re.match('^[0-9a-f]{32}$', checksum)
        if ((match) and (filename.lower().endswith('.apk')
                         or filename.lower().endswith('.zip'))
                and (typ in ['zip', 'apk'])):
            app_dic['dir'] = settings.BASE_DIR  # BASE DIR
            app_dic['app_name'] = filename  # APP ORGINAL NAME
            app_dic['md5'] = checksum  # MD5
            app_dic['app_dir'] = os.path.join(
                settings.UPLD_DIR, app_dic['md5'] + '/')  # APP DIRECTORY
            app_dic['tools_dir'] = os.path.join(
                app_dic['dir'], 'StaticAnalyzer/tools/')  # TOOLS DIR
            # DWD_DIR = settings.DWD_DIR # not needed? Var is never used.
            print "[INFO] Starting Analysis on : " + app_dic['app_name']

            if typ == 'apk':
                # Check if in DB
                # pylint: disable=E1101
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.apk'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH

                    # ANALYSIS BEGINS
                    app_dic['size'] = str(file_size(
                        app_dic['app_path'])) + 'MB'  # FILE SIZE
                    app_dic['sha1'], app_dic['sha256'] = hash_gen(
                        app_dic['app_path'])

                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])

                    print "[INFO] APK Extracted"

                    # Manifest XML
                    app_dic['parsed_xml'] = get_manifest(
                        app_dic['app_dir'], app_dic['tools_dir'], '', True)

                    # Get icon
                    res_path = os.path.join(app_dic['app_dir'], 'res')
                    app_dic['icon_hidden'] = True
                    app_dic[
                        'icon_found'] = False  # Even if the icon is hidden, try to guess it by the default paths
                    app_dic['icon_path'] = ''
                    if os.path.exists(
                            res_path
                    ):  # TODO: Check for possible different names for resource folder?
                        icon_dic = get_icon(app_dic['app_path'], res_path,
                                            app_dic['tools_dir'])
                        if icon_dic:
                            app_dic['icon_hidden'] = icon_dic['hidden']
                            app_dic['icon_found'] = bool(icon_dic['path'])
                            app_dic['icon_path'] = icon_dic['path']

                    # Set Manifest link
                    app_dic['mani'] = '../ManifestView/?md5=' + \
                        app_dic['md5'] + '&type=apk&bin=1'
                    man_data_dic = manifest_data(app_dic['parsed_xml'])

                    man_an_dic = manifest_analysis(app_dic['parsed_xml'],
                                                   man_data_dic)
                    bin_an_buff = []
                    bin_an_buff += elf_analysis(app_dic['app_dir'], "apk")
                    bin_an_buff += res_analysis(app_dic['app_dir'], "apk")
                    cert_dic = cert_info(app_dic['app_dir'],
                                         app_dic['tools_dir'])
                    apkid_results = apkid_analysis(app_dic['app_dir'])
                    dex_2_jar(app_dic['app_path'], app_dic['app_dir'],
                              app_dic['tools_dir'])
                    dex_2_smali(app_dic['app_dir'], app_dic['tools_dir'])
                    jar_2_java(app_dic['app_dir'], app_dic['tools_dir'])
                    code_an_dic = code_analysis(app_dic['app_dir'],
                                                man_an_dic['permissons'],
                                                "apk")
                    print "\n[INFO] Generating Java and Smali Downloads"
                    gen_downloads(app_dic['app_dir'], app_dic['md5'],
                                  app_dic['icon_path'])

                    # Get the strings
                    app_dic['strings'] = strings(app_dic['app_file'],
                                                 app_dic['app_dir'],
                                                 app_dic['tools_dir'])
                    app_dic['zipped'] = '&type=apk'

                    print "\n[INFO] Connecting to Database"
                    try:
                        # SAVE TO DB
                        if rescan == '1':
                            print "\n[INFO] Updating Database..."
                            update_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                            )
                        elif rescan == '0':
                            print "\n[INFO] Saving to Database"
                            create_db_entry(
                                app_dic,
                                man_data_dic,
                                man_an_dic,
                                code_an_dic,
                                cert_dic,
                                bin_an_buff,
                                apkid_results,
                            )
                    except:
                        PrintException("[ERROR] Saving to Database Failed")
                    context = get_context_from_analysis(
                        app_dic,
                        man_data_dic,
                        man_an_dic,
                        code_an_dic,
                        cert_dic,
                        bin_an_buff,
                        apkid_results,
                    )
                context['dynamic_analysis_done'] = os.path.exists(
                    os.path.join(app_dic['app_dir'], 'logcat.txt'))
                template = "static_analysis/static_analysis.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            elif typ == 'zip':
                # Check if in DB
                # pylint: disable=E1101
                cert_dic = {}
                cert_dic['cert_info'] = ''
                cert_dic['issued'] = ''
                bin_an_buff = []
                app_dic['strings'] = ''
                app_dic['zipped'] = ''
                # Above fields are only available for APK and not ZIP
                db_entry = StaticAnalyzerAndroid.objects.filter(
                    MD5=app_dic['md5'])
                if db_entry.exists() and rescan == '0':
                    context = get_context_from_db_entry(db_entry)
                else:
                    app_dic[
                        'app_file'] = app_dic['md5'] + '.zip'  # NEW FILENAME
                    app_dic['app_path'] = app_dic['app_dir'] + \
                        app_dic['app_file']  # APP PATH
                    print "[INFO] Extracting ZIP"
                    app_dic['files'] = unzip(app_dic['app_path'],
                                             app_dic['app_dir'])
                    # Check if Valid Directory Structure and get ZIP Type
                    pro_type, valid = valid_android_zip(app_dic['app_dir'])
                    if valid and pro_type == 'ios':
                        print "[INFO] Redirecting to iOS Source Code Analyzer"
                        if api:
                            return {"type": "ios"}
                        else:
                            return HttpResponseRedirect(
                                '/StaticAnalyzer_iOS/?name=' +
                                app_dic['app_name'] + '&type=ios&checksum=' +
                                app_dic['md5'])
                    app_dic['certz'] = get_hardcoded_cert_keystore(
                        app_dic['files'])
                    app_dic['zipped'] = pro_type
                    print "[INFO] ZIP Type - " + pro_type
                    if valid and (pro_type in ['eclipse', 'studio']):
                        # ANALYSIS BEGINS
                        app_dic['size'] = str(file_size(
                            app_dic['app_path'])) + 'MB'  # FILE SIZE
                        app_dic['sha1'], app_dic['sha256'] = hash_gen(
                            app_dic['app_path'])

                        # Manifest XML
                        app_dic['persed_xml'] = get_manifest(
                            app_dic['app_dir'], app_dic['tools_dir'], pro_type,
                            False)

                        # Set manifest view link
                        app_dic['mani'] = ('../ManifestView/?md5=' +
                                           app_dic['md5'] + '&type=' +
                                           pro_type + '&bin=0')

                        man_data_dic = manifest_data(app_dic['persed_xml'])

                        man_an_dic = manifest_analysis(app_dic['persed_xml'],
                                                       man_data_dic)

                        # Get icon
                        eclipse_res_path = os.path.join(
                            app_dic['app_dir'], 'res')
                        studio_res_path = os.path.join(app_dic['app_dir'],
                                                       'app', 'src', 'main',
                                                       'res')
                        if os.path.exists(eclipse_res_path):
                            res_path = eclipse_res_path
                        elif os.path.exists(studio_res_path):
                            res_path = studio_res_path
                        else:
                            res_path = ''

                        app_dic['icon_hidden'] = man_an_dic['icon_hidden']
                        app_dic['icon_found'] = False
                        app_dic['icon_path'] = ''
                        if res_path:
                            app_dic['icon_path'] = find_icon_path_zip(
                                res_path, man_data_dic['icons'])
                            if app_dic['icon_path']:
                                app_dic['icon_found'] = True

                        if app_dic['icon_path']:
                            if os.path.exists(app_dic['icon_path']):
                                shutil.copy2(
                                    app_dic['icon_path'],
                                    os.path.join(settings.DWD_DIR,
                                                 app_dic['md5'] + '-icon.png'))

                        code_an_dic = code_analysis(app_dic['app_dir'],
                                                    man_an_dic['permissons'],
                                                    pro_type)
                        print "\n[INFO] Connecting to Database"
                        try:
                            # SAVE TO DB
                            if rescan == '1':
                                print "\n[INFO] Updating Database..."
                                update_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                )
                            elif rescan == '0':
                                print "\n[INFO] Saving to Database"
                                create_db_entry(
                                    app_dic,
                                    man_data_dic,
                                    man_an_dic,
                                    code_an_dic,
                                    cert_dic,
                                    bin_an_buff,
                                    {},
                                )
                        except:
                            PrintException("[ERROR] Saving to Database Failed")
                        context = get_context_from_analysis(
                            app_dic,
                            man_data_dic,
                            man_an_dic,
                            code_an_dic,
                            cert_dic,
                            bin_an_buff,
                            {},
                        )
                    else:
                        msg = "This ZIP Format is not supported"
                        if api:
                            return print_n_send_error_response(
                                request, msg, True)
                        else:
                            print_n_send_error_response(request, msg, False)
                            return HttpResponseRedirect('/zip_format/')
                template = "static_analysis/static_analysis_android_zip.html"
                if api:
                    return context
                else:
                    return render(request, template, context)
            else:
                print "\n[ERROR] Only APK,IPA and Zipped Android/iOS Source code supported now!"
        else:
            msg = "Hash match failed or Invalid file extension or file type"
            if api:
                return print_n_send_error_response(request, msg, True)
            else:
                return print_n_send_error_response(request, msg, False)

    except Exception as excep:
        msg = str(excep)
        exp = excep.__doc__
        if api:
            return print_n_send_error_response(request, msg, True, exp)
        else:
            return print_n_send_error_response(request, msg, False, exp)