def get_context_from_db_entry_ipa(db_entry): """Return the context for IPA from DB""" try: print("\n[INFO] Analysis is already Done. Fetching data from the DB...") context = { 'title': db_entry[0].TITLE, 'file_name': db_entry[0].FILE_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'build': db_entry[0].BUILD, 'version': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'bin_anal': python_list(db_entry[0].BIN_ANAL), 'libs': python_list(db_entry[0].LIBS), 'files': python_list(db_entry[0].FILES), 'file_analysis': python_list(db_entry[0].SFILESX), 'strings': python_list(db_entry[0].STRINGS), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON), 'bundle_name': db_entry[0].BUNDLE_NAME, 'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES), 'bundle_supported_platforms': python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS), 'bundle_localizations': python_list(db_entry[0].BUNDLE_LOCALIZATIONS), } return context except: PrintException("[ERROR] Fetching from DB")
def get_context_from_db_entry_ios(db_entry): """Return the context for IOS ZIP from DB""" try: print "\n[INFO] Analysis is already Done. Fetching data from the DB..." context = { 'title': db_entry[0].TITLE, 'name': db_entry[0].APPNAMEX, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'ver': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'files': python_list(db_entry[0].FILES), 'file_analysis': db_entry[0].SFILESX, 'api': python_dict(db_entry[0].API), 'insecure': python_dict(db_entry[0].CODEANAL), 'urls': python_list(db_entry[0].URLnFile), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EmailnFile), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON) } return context except: PrintException("[ERROR] Fetching from DB")
def get_context_from_db_entry_ipa(db_entry): """Return the context for IPA from DB""" try: print "\n[INFO] Analysis is already Done. Fetching data from the DB..." context = { 'title': db_entry[0].TITLE, 'name': db_entry[0].APPNAMEX, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'ver': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'bin_anal': db_entry[0].BIN_ANAL, 'libs': db_entry[0].LIBS, 'files': python_list(db_entry[0].FILES), 'file_analysis': db_entry[0].SFILESX, 'strings': python_list(db_entry[0].STRINGS), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON) } return context except: PrintException("[ERROR] Fetching from DB")
def get_context_from_db_entry(db_entry): """Return the context for APK/ZIP from DB""" try: print "\n[INFO] Analysis is already Done. Fetching data from the DB..." context = { 'title': db_entry[0].TITLE, 'name': db_entry[0].APP_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'packagename': db_entry[0].PACKAGENAME, 'mainactivity': db_entry[0].MAINACTIVITY, 'targetsdk': db_entry[0].TARGET_SDK, 'maxsdk': db_entry[0].MAX_SDK, 'minsdk': db_entry[0].MIN_SDK, 'androvername': db_entry[0].ANDROVERNAME, 'androver': db_entry[0].ANDROVER, 'manifest': python_list(db_entry[0].MANIFEST_ANAL), 'permissions': python_dict(db_entry[0].PERMISSIONS), 'binary_analysis': python_list(db_entry[0].BIN_ANALYSIS), 'files': python_list(db_entry[0].FILES), 'certz': db_entry[0].CERTZ, 'activities': python_list(db_entry[0].ACTIVITIES), 'receivers': python_list(db_entry[0].RECEIVERS), 'providers': python_list(db_entry[0].PROVIDERS), 'services': python_list(db_entry[0].SERVICES), 'libraries': python_list(db_entry[0].LIBRARIES), 'browsable_activities': python_dict(db_entry[0].BROWSABLE), 'act_count': db_entry[0].CNT_ACT, 'prov_count': db_entry[0].CNT_PRO, 'serv_count': db_entry[0].CNT_SER, 'bro_count': db_entry[0].CNT_BRO, 'certinfo': db_entry[0].CERT_INFO, 'issued': db_entry[0].ISSUED, 'native': db_entry[0].NATIVE, 'dynamic': db_entry[0].DYNAMIC, 'reflection': db_entry[0].REFLECT, 'crypto': db_entry[0].CRYPTO, 'obfus': db_entry[0].OBFUS, 'api': db_entry[0].API, 'dang': db_entry[0].DANG, 'urls': db_entry[0].URLS, 'domains': python_dict(db_entry[0].DOMAINS), 'emails': db_entry[0].EMAILS, 'strings': python_list(db_entry[0].STRINGS), 'zipped': db_entry[0].ZIPPED, 'mani': db_entry[0].MANI, 'e_act': db_entry[0].E_ACT, 'e_ser': db_entry[0].E_SER, 'e_bro': db_entry[0].E_BRO, 'e_cnt': db_entry[0].E_CNT, } return context except: PrintException("[ERROR] Fetching from DB")
def ActivityTester(request): print "\n[INFO] Activity Tester" try: MD5 = request.POST['md5'] PKG = request.POST['pkg'] m = re.match('^[0-9a-f]{32}$', MD5) if m: if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect('/error/') if request.method == 'POST': DIR = settings.BASE_DIR APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + '/') TOOLS_DIR = os.path.join( DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR SCRDIR = os.path.join(APP_DIR, 'screenshots-apk/') data = {} adb = getADB(TOOLS_DIR) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Activity List from DB" ACTIVITIES = python_list(DB[0].ACTIVITIES) if ACTIVITIES: n = 0 print "\n[INFO] Starting Activity Tester..." print "\n[INFO] " + str(len(ACTIVITIES)) + " Activities Identified" for line in ACTIVITIES: try: n += 1 print "\n[INFO] Launching Activity - " + str(n) + ". " + line subprocess.call( [adb, "-s", getIdentifier(), "shell", "am", "start", "-n", PKG + "/" + line]) Wait(4) subprocess.call( [adb, "-s", getIdentifier(), "shell", "screencap", "-p", "/data/local/screen.png"]) #? get appended from Air :-() if activity names are used subprocess.call( [adb, "-s", getIdentifier(), "pull", "/data/local/screen.png", SCRDIR + "act-" + str(n) + ".png"]) print "\n[INFO] Activity Screenshot Taken" subprocess.call( [adb, "-s", getIdentifier(), "shell", "am", "force-stop", PKG]) print "\n[INFO] Stopping App" except: PrintException("Activity Tester") data = {'acttest': 'done'} else: print "\n[INFO] Activity Tester - No Activity Found!" data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: print "\n[ERROR] Entry does not exist in DB." return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Activity Tester") return HttpResponseRedirect('/error/')
def get_context_from_db_entry_ios(db_entry): """Return the context for IOS ZIP from DB""" try: logger.info("Analysis is already Done. Fetching data from the DB...") context = { 'title': db_entry[0].TITLE, 'file_name': db_entry[0].FILE_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'build': db_entry[0].BUILD, 'version': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'files': python_list(db_entry[0].FILES), 'file_analysis': python_list(db_entry[0].SFILESX), 'api': python_dict(db_entry[0].API), 'insecure': python_dict(db_entry[0].CODEANAL), 'urls': python_list(db_entry[0].URLnFile), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EmailnFile), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON), 'bundle_name': db_entry[0].BUNDLE_NAME, 'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES), 'bundle_supported_platforms': python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS), 'bundle_localizations': python_list(db_entry[0].BUNDLE_LOCALIZATIONS), 'appstore_details': python_dict(db_entry[0].APPSTORE_DETAILS), 'firebase': python_list(db_entry[0].FIREBASE), } return context except: PrintException("Fetching from DB")
def activity_tester(request): """Activity Tester.""" logger.info('Activity Tester') try: md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r';|\$\(|\|\||&&', package): return print_n_send_error_response(request, 'Possible RCE Attack', True) if request.method == 'POST': app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') screen_dir = os.path.join(app_dir, 'screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) data = {} static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): logger.info('Fetching Activity List from DB') activities = python_list(static_android_db[0].ACTIVITIES) if activities: act_no = 0 logger.info('Starting Activity Tester...') logger.info('%s Activities Identified', str(len(activities))) for line in activities: try: act_no += 1 logger.info('Launching Activity - %s. %s', str(act_no), line) adb_command([ 'am', 'start', '-n', package + '/' + line ], True) wait(4) adb_command([ 'screencap', '-p', '/data/local/screen.png' ], True) # ? get appended from Air :-() # if activity names are used outfile = ('{}act-{}.png'.format( screen_dir, act_no)) adb_command([ 'pull', '/data/local/screen.png', outfile ]) logger.info('Activity Screenshot Taken') adb_command(['am', 'force-stop', package], True) logger.info('Stopping App') except Exception: logger.exception('Activity Tester') data = {'acttest': 'done'} else: logger.info('Activity Tester - No Activity Found!') data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: err = 'Entry does not exist in DB' return print_n_send_error_response(request, err, True) else: return print_n_send_error_response(request, 'Only POST allowed', True) else: return print_n_send_error_response(request, 'Invalid Scan Hash', True) except Exception: logger.exception('Activity Tester') return print_n_send_error_response(request, 'Error Running Activity Tester', True)
def get_context_from_db_entry_ipa(db_entry): """Return the context for IPA from DB.""" try: logger.info('Analysis is already Done. Fetching data from the DB...') context = { 'title': db_entry[0].TITLE, 'file_name': db_entry[0].FILE_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'build': db_entry[0].BUILD, 'version': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'bin_anal': python_list(db_entry[0].BIN_ANAL), 'libs': python_list(db_entry[0].LIBS), 'files': python_list(db_entry[0].FILES), 'file_analysis': python_list(db_entry[0].SFILESX), 'strings': python_list(db_entry[0].STRINGS), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON), 'bundle_name': db_entry[0].BUNDLE_NAME, 'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES), 'bundle_supported_platforms': python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS), 'bundle_localizations': python_list(db_entry[0].BUNDLE_LOCALIZATIONS), 'binary_info': python_dict(db_entry[0].MACHOINFO), 'bin_type': db_entry[0].BINTYPE, 'appstore_details': python_dict(db_entry[0].APPSTORE_DETAILS), } return context except Exception: logger.exception('Fetching from DB')
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 = { 'title': DB[0].TITLE, 'name': DB[0].APP_NAME, 'size': DB[0].SIZE, 'md5': DB[0].MD5, 'sha1': DB[0].SHA1, 'sha256': DB[0].SHA256, 'packagename': DB[0].PACKAGENAME, 'mainactivity': DB[0].MAINACTIVITY, 'targetsdk': DB[0].TARGET_SDK, 'maxsdk': DB[0].MAX_SDK, 'minsdk': DB[0].MIN_SDK, 'androvername': DB[0].ANDROVERNAME, 'androver': DB[0].ANDROVER, 'manifest': DB[0].MANIFEST_ANAL, 'permissions': DB[0].PERMISSIONS, 'files': python_list(DB[0].FILES), 'certz': DB[0].CERTZ, 'activities': python_list(DB[0].ACTIVITIES), 'receivers': python_list(DB[0].RECEIVERS), 'providers': python_list(DB[0].PROVIDERS), 'services': python_list(DB[0].SERVICES), 'libraries': python_list(DB[0].LIBRARIES), 'act_count': DB[0].CNT_ACT, 'prov_count': DB[0].CNT_PRO, 'serv_count': DB[0].CNT_SER, 'bro_count': DB[0].CNT_BRO, 'certinfo': DB[0].CERT_INFO, 'issued': DB[0].ISSUED, 'native': DB[0].NATIVE, 'dynamic': DB[0].DYNAMIC, 'reflection': DB[0].REFLECT, 'crypto': DB[0].CRYPTO, 'obfus': DB[0].OBFUS, 'api': DB[0].API, 'dang': DB[0].DANG, 'urls': DB[0].URLS, 'domains': python_dict(DB[0].DOMAINS), 'emails': DB[0].EMAILS, 'strings': python_list(DB[0].STRINGS), 'zipped': DB[0].ZIPPED, 'mani': DB[0].MANI } if TYP == 'APK': template = get_template("static_analysis_pdf.html") else: template = get_template("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': DB[0].STRINGS } template = get_template("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 } template = get_template("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' : 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("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): 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 get_context_from_db_entry(db_entry): """Return the context for IPA/ZIP from DB.""" try: logger.info('Analysis is already Done. Fetching data from the DB...') context = { 'version': settings.MOBSF_VER, 'title': 'Static Analysis', 'file_name': db_entry[0].FILE_NAME, 'app_name': db_entry[0].APP_NAME, 'app_type': db_entry[0].APP_TYPE, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'build': db_entry[0].BUILD, 'app_version': db_entry[0].APP_VERSION, 'sdk_name': db_entry[0].SDK_NAME, 'platform': db_entry[0].PLATFORM, 'min_os_version': db_entry[0].MIN_OS_VERSION, 'bundle_id': db_entry[0].BUNDLE_ID, 'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES), 'bundle_supported_platforms': python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS), 'info_plist': db_entry[0].INFO_PLIST, 'binary_info': python_dict(db_entry[0].MACHO_INFO), 'permissions': python_list(db_entry[0].PERMISSIONS), 'ats_analysis': python_list(db_entry[0].ATS_ANALYSIS), 'binary_analysis': python_list(db_entry[0].BINARY_ANALYSIS), 'ios_api': python_dict(db_entry[0].IOS_API), 'code_analysis': python_dict(db_entry[0].CODE_ANALYSIS), 'file_analysis': python_list(db_entry[0].FILE_ANALYSIS), 'libraries': python_list(db_entry[0].LIBRARIES), 'files': python_list(db_entry[0].FILES), 'urls': python_list(db_entry[0].URLS), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EMAILS), 'strings': python_list(db_entry[0].STRINGS), 'firebase_urls': python_list(db_entry[0].FIREBASE_URLS), 'appstore_details': python_dict(db_entry[0].APPSTORE_DETAILS), } return context except Exception: logger.exception('Fetching from DB')
def activity_tester(request): """Activity Tester""" print("\n[INFO] Activity Tester") try: md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if request.method == 'POST': base_dir = settings.BASE_DIR app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') screen_dir = os.path.join(app_dir, 'screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) data = {} adb = getADB() static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): print("\n[INFO] Fetching Activity List from DB") activities = python_list(static_android_db[0].ACTIVITIES) if activities: act_no = 0 print("\n[INFO] Starting Activity Tester...") print("\n[INFO] " + str(len(activities)) + " Activities Identified") for line in activities: try: act_no += 1 print("\n[INFO] Launching Activity - " + str(act_no) + ". " + line) adb_command( ["am", "start", "-n", package + "/" + line], True) # AVD is much slower, it should get extra time if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": wait(8) else: wait(4) adb_command( ["screencap", "-p", "/data/local/screen.png"], True) #? get appended from Air :-() if activity names are used adb_command(["pull", "/data/local/screen.png", screen_dir + "act-" + str(act_no) + ".png"]) print("\n[INFO] Activity Screenshot Taken") adb_command( ["am", "force-stop", package], True) print("\n[INFO] Stopping App") except: PrintException("Activity Tester") data = {'acttest': 'done'} else: print("\n[INFO] Activity Tester - No Activity Found!") data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: print("\n[ERROR] Entry does not exist in DB.") return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Activity Tester") return HttpResponseRedirect('/error/')
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 staticanalyzer_windows(request, api=False): """Analyse a windows app.""" try: # Input validation logger.info("Windows Static Analysis Started") app_dic = {} # Dict to store the binary attributes if api: typ = request.POST['scan_type'] rescan = str(request.POST.get('re_scan', 0)) checksum = request.POST['hash'] filename = request.POST['file_name'] else: typ = request.GET['type'] rescan = str(request.GET.get('rescan', 0)) checksum = request.GET['checksum'] filename = request.GET['name'] md5_regex = re.match('^[0-9a-f]{32}$', checksum) if (md5_regex) and (typ in ['appx']): app_dic['app_name'] = filename # APP ORGINAL NAME app_dic['md5'] = checksum app_dic['app_dir'] = os.path.join( settings.UPLD_DIR, app_dic['md5'] + '/') app_dic['tools_dir'] = os.path.join( settings.BASE_DIR, 'StaticAnalyzer/tools/windows/') if typ == 'appx': # DB db_entry = StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ) if db_entry.exists() and rescan == '0': logger.info("Analysis is already Done. Fetching data from the DB...") 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) } else: logger.info("Windows Binary Analysis Started") app_dic['app_path'] = os.path.join( app_dic['app_dir'], app_dic['md5'] + '.appx') # ANALYSIS BEGINS app_dic['size'] = str(file_size(app_dic['app_path'])) + 'MB' # Generate hashes app_dic['sha1'], app_dic[ 'sha256'] = hash_gen(app_dic['app_path']) # EXTRACT APPX logger.info("Extracting APPX") app_dic['files'] = unzip( app_dic['app_path'], app_dic['app_dir']) xml_dic = _parse_xml(app_dic['app_dir']) bin_an_dic = _binary_analysis(app_dic) # Saving to db logger.info("Connecting to DB") if rescan == '1': logger.info("Updating Database...") StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ).update( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) elif rescan == '0': logger.info("Saving to Database") db_item = StaticAnalyzerWindows( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) db_item.save() context = { 'title': 'Static Analysis', 'name': app_dic['app_name'], 'pub_name': xml_dic['pub_name'], 'size': app_dic['size'], 'md5': app_dic['md5'], 'sha1': app_dic['sha1'], 'sha256': app_dic['sha256'], 'bin_name': bin_an_dic['bin_name'], 'version': xml_dic['version'], 'arch': xml_dic['arch'], 'compiler_version': xml_dic['compiler_version'], 'visual_studio_version': xml_dic['visual_studio_version'], 'visual_studio_edition': xml_dic['visual_studio_edition'], 'target_os': xml_dic['target_os'], 'appx_dll_version': xml_dic['appx_dll_version'], 'proj_guid': xml_dic['proj_guid'], 'opti_tool': xml_dic['opti_tool'], 'target_run': xml_dic['target_run'], 'files': app_dic['files'], 'strings': bin_an_dic['strings'], 'bin_an_results': bin_an_dic['results'], 'bin_an_warnings': bin_an_dic['warnings'], } template = "static_analysis/windows_binary_analysis.html" if api: return context else: return render(request, template, context) else: msg = "File type not supported" if api: return print_n_send_error_response(request, msg, True) else: return print_n_send_error_response(request, msg, False) else: msg = "Hash match failed or Invalid file extension" if api: return print_n_send_error_response(request, msg, True) else: return print_n_send_error_response(request, msg, False) except Exception as exception: msg = str(exception) exp_doc = exception.__doc__ if api: return print_n_send_error_response(request, msg, True, exp_doc) else: return print_n_send_error_response(request, msg, False, exp_doc)
def APIAnalysis(PKG, LOCATION): print "\n[INFO] Dynamic API Analysis" dat = "" API_BASE64 = [] API_FILEIO = [] API_RELECT = [] API_SYSPROP = [] API_CNTRSLVR = [] API_CNTVAL = [] API_BINDER = [] API_CRYPTO = [] API_ACNTMNGER = [] API_DEVICEINFO = [] API_NET = [] API_DEXLOADER = [] API_CMD = [] API_SMS = [] try: with open(LOCATION, "r") as f: dat = f.readlines() ID = "Droidmon-apimonitor-" + PKG + ":" for line in dat: line = line.decode('utf8', 'ignore') if (ID) in line: #print "LINE: " + line param, value = line.split(ID, 1) #print "PARAM is :" + param #print "Value is :"+ value try: APIs = json.loads(value, strict=False) RET = '' CLS = '' MTD = '' ARGS = '' MTD = str(APIs["method"]) CLS = str(APIs["class"]) #print "Called Class: " + CLS #print "Called Method: " + MTD if APIs.get('return'): RET = str(APIs["return"]) #print "Return Data: " + RET else: #print "No Return Data" RET = "No Return Data" if APIs.get('args'): ARGS = str(APIs["args"]) #print "Passed Arguments" + ARGS else: #print "No Arguments Passed" ARGS = "No Arguments Passed" #XSS Safe D = "</br>METHOD: " + escape( MTD) + "</br>ARGUMENTS: " + escape( ARGS) + "</br>RETURN DATA: " + escape(RET) if re.findall("android.util.Base64", CLS): #Base64 Decode if ("decode" in MTD): args_list = python_list(ARGS) if isBase64(args_list[0]): D += '</br><span class="label label-info">Decoded String:</span> ' + escape( base64.b64decode(args_list[0])) API_BASE64.append(D) if re.findall( 'libcore.io|android.app.SharedPreferencesImpl$EditorImpl', CLS): API_FILEIO.append(D) if re.findall('java.lang.reflect', CLS): API_RELECT.append(D) if re.findall( 'android.content.ContentResolver|android.location.Location|android.media.AudioRecord|android.media.MediaRecorder|android.os.SystemProperties', CLS): API_SYSPROP.append(D) if re.findall( 'android.app.Activity|android.app.ContextImpl|android.app.ActivityThread', CLS): API_BINDER.append(D) if re.findall( 'javax.crypto.spec.SecretKeySpec|javax.crypto.Cipher|javax.crypto.Mac', CLS): API_CRYPTO.append(D) if re.findall( 'android.accounts.AccountManager|android.app.ApplicationPackageManager|android.app.NotificationManager|android.net.ConnectivityManager|android.content.BroadcastReceiver', CLS): API_ACNTMNGER.append(D) if re.findall( 'android.telephony.TelephonyManager|android.net.wifi.WifiInfo|android.os.Debug', CLS): API_DEVICEINFO.append(D) if re.findall( 'dalvik.system.BaseDexClassLoader|dalvik.system.DexFile|dalvik.system.DexClassLoader|dalvik.system.PathClassLoader', CLS): API_DEXLOADER.append(D) if re.findall( 'java.lang.Runtime|java.lang.ProcessBuilder|java.io.FileOutputStream|java.io.FileInputStream|android.os.Process', CLS): API_CMD.append(D) if re.findall('android.content.ContentValues', CLS): API_CNTVAL.append(D) if re.findall('android.telephony.SmsManager', CLS): API_SMS.append(D) if re.findall( 'java.net.URL|org.apache.http.impl.client.AbstractHttpClient', CLS): API_NET.append(D) except: PrintException("[ERROR] Parsing JSON Failed for: " + value) except: PrintException("[ERROR] Dynamic API Analysis") pass return list(set(API_NET)), list(set(API_BASE64)), list( set(API_FILEIO)), list(set(API_BINDER)), list(set(API_CRYPTO)), list( set(API_DEVICEINFO)), list(set(API_CNTVAL)), list( set(API_SMS)), list(set(API_SYSPROP)), list( set(API_DEXLOADER)), list(set(API_RELECT)), list( set(API_ACNTMNGER)), list(set(API_CMD))
def Report(request): print "\n[INFO] Dynamic Analysis Report Generation" try: if request.method == 'GET': MD5 = request.GET['md5'] PKG = request.GET['pkg'] if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect('/error/') m = re.match('^[0-9a-f]{32}$', MD5) if m: DIR = settings.BASE_DIR APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + '/') #APP DIRECTORY DWD_DIR = settings.DWD_DIR DRDMONAPISLOC = os.path.join( APP_DIR, 'x_logcat.txt') #Use check_outputs instead later. API_NET, API_BASE64, API_FILEIO, API_BINDER, API_CRYPTO, API_DEVICEINFO, API_CNTVL, API_SMS, API_SYSPROP, API_DEXLOADER, API_RELECT, API_ACNTMNGER, API_CMD = APIAnalysis( PKG, DRDMONAPISLOC) URL, DOMAINS, EMAIL, HTTP, XML, SQLiteDB, OtherFiles = RunAnalysis( APP_DIR, MD5, PKG) Download(MD5, DWD_DIR, APP_DIR, PKG) #Only After Download Process is Done IMGS = [] ACTIMGS = [] ACT = {} EXPACTIMGS = [] EXPACT = {} if os.path.exists( os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): try: for img in os.listdir( os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): if img.endswith(".png"): if img.startswith("act"): ACTIMGS.append(img) elif img.startswith("expact"): EXPACTIMGS.append(img) else: IMGS.append(img) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Exported Activity & Activity List from DB" EXPORTED_ACT = python_list(DB[0].EXPORTED_ACT) ACTDESC = python_list(DB[0].ACTIVITIES) if len(ACTIMGS) > 0: if len(ACTIMGS) == len(ACTDESC): ACT = dict(zip(ACTIMGS, ACTDESC)) if len(EXPACTIMGS) > 0: if len(EXPACTIMGS) == len(EXPORTED_ACT): EXPACT = dict(zip(EXPACTIMGS, EXPORTED_ACT)) else: print "\n[WARNING] Entry does not exists in the DB." except: PrintException("[ERROR] Screenshot Sorting") context = { 'emails': EMAIL, 'urls': URL, 'domains': DOMAINS, 'md5': MD5, 'http': HTTP, 'xml': XML, 'sqlite': SQLiteDB, 'others': OtherFiles, 'imgs': IMGS, 'acttest': ACT, 'expacttest': EXPACT, 'net': API_NET, 'base64': API_BASE64, 'crypto': API_CRYPTO, 'fileio': API_FILEIO, 'binder': API_BINDER, 'divinfo': API_DEVICEINFO, 'cntval': API_CNTVL, 'sms': API_SMS, 'sysprop': API_SYSPROP, 'dexload': API_DEXLOADER, 'reflect': API_RELECT, 'sysman': API_ACNTMNGER, 'process': API_CMD, 'pkg': PKG, 'title': 'Dynamic Analysis' } template = "dynamic_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Dynamic Analysis Report Generation") return HttpResponseRedirect('/error/')
def ActivityTester(request): print "\n[INFO] Activity Tester" try: MD5 = request.POST['md5'] PKG = request.POST['pkg'] m = re.match('^[0-9a-f]{32}$', MD5) if m: if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect('/error/') if request.method == 'POST': DIR = settings.BASE_DIR APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + '/') TOOLS_DIR = os.path.join(DIR, 'DynamicAnalyzer/tools/') #TOOLS DIR SCRDIR = os.path.join(APP_DIR, 'screenshots-apk/') data = {} adb = getADB(TOOLS_DIR) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Activity List from DB" ACTIVITIES = python_list(DB[0].ACTIVITIES) if len(ACTIVITIES) > 0: n = 0 print "\n[INFO] Starting Activity Tester..." print "\n[INFO] " + str( len(ACTIVITIES)) + " Activities Identified" for line in ACTIVITIES: try: n += 1 print "\n[INFO] Launching Activity - " + str( n) + ". " + line subprocess.call([ adb, "-s", getIdentifier(), "shell", "am", "start", "-n", PKG + "/" + line ]) Wait(4) subprocess.call([ adb, "-s", getIdentifier(), "shell", "screencap", "-p", "/data/local/screen.png" ]) #? get appended from Air :-() if activity names are used subprocess.call([ adb, "-s", getIdentifier(), "pull", "/data/local/screen.png", SCRDIR + "act-" + str(n) + ".png" ]) print "\n[INFO] Activity Screenshot Taken" subprocess.call([ adb, "-s", getIdentifier(), "shell", "am", "force-stop", PKG ]) print "\n[INFO] Stopping App" except: PrintException("Activity Tester") data = {'acttest': 'done'} else: print "\n[INFO] Activity Tester - No Activity Found!" data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: print "\n[ERROR] Entry does not exist in DB." return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Activity Tester") 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=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() 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) 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, "report_dat": context} 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)
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 = { 'title': DB[0].TITLE, 'name': DB[0].APP_NAME, 'size': DB[0].SIZE, 'md5': DB[0].MD5, 'sha1': DB[0].SHA1, 'sha256': DB[0].SHA256, 'packagename': DB[0].PACKAGENAME, 'mainactivity': DB[0].MAINACTIVITY, 'targetsdk': DB[0].TARGET_SDK, 'maxsdk': DB[0].MAX_SDK, 'minsdk': DB[0].MIN_SDK, 'androvername': DB[0].ANDROVERNAME, 'androver': DB[0].ANDROVER, 'manifest': DB[0].MANIFEST_ANAL, 'permissions': DB[0].PERMISSIONS, 'files': python_list(DB[0].FILES), 'certz': DB[0].CERTZ, 'activities': python_list(DB[0].ACTIVITIES), 'receivers': python_list(DB[0].RECEIVERS), 'providers': python_list(DB[0].PROVIDERS), 'services': python_list(DB[0].SERVICES), 'libraries': python_list(DB[0].LIBRARIES), 'act_count': DB[0].CNT_ACT, 'prov_count': DB[0].CNT_PRO, 'serv_count': DB[0].CNT_SER, 'bro_count': DB[0].CNT_BRO, 'certinfo': DB[0].CERT_INFO, 'issued': DB[0].ISSUED, 'native': DB[0].NATIVE, 'dynamic': DB[0].DYNAMIC, 'reflection': DB[0].REFLECT, 'crypto': DB[0].CRYPTO, 'obfus': DB[0].OBFUS, 'api': DB[0].API, 'dang': DB[0].DANG, 'urls': DB[0].URLS, 'domains': python_dict(DB[0].DOMAINS), 'emails': DB[0].EMAILS, 'strings': python_list(DB[0].STRINGS), 'zipped': DB[0].ZIPPED, 'mani': DB[0].MANI } if TYP == 'APK': template = get_template("static_analysis_pdf.html") else: template = get_template("static_analysis_zip_pdf.html") 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': DB[0].STRINGS } template = get_template("ios_binary_analysis_pdf.html") 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 } template = get_template("ios_source_analysis_pdf.html") else: return HttpResponseRedirect('/error/') 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 HttpResponseRedirect('/error/') except: PrintException("[ERROR] PDF Report Generation Error") return HttpResponseRedirect('/error/')
def report(request): """Dynamic Analysis Report Generation.""" logger.info('Dynamic Analysis Report Generation') try: if request.method == 'GET': md5_hash = request.GET['md5'] package = request.GET['pkg'] if re.findall(r';|\$\(|\|\||&&', package): return print_n_send_error_response(request, 'Possible RCE Attack') if re.match('^[0-9a-f]{32}$', md5_hash): app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') # APP DIRECTORY download_dir = settings.DWD_DIR droidmon_api_loc = os.path.join(app_dir, 'x_logcat.txt') api_analysis_result = api_analysis(package, droidmon_api_loc) analysis_result = run_analysis(app_dir, md5_hash, package) download(md5_hash, download_dir, app_dir, package) # Only After Download Process is Done imgs = [] act_imgs = [] act = {} expact_imgs = [] exp_act = {} if os.path.exists( os.path.join(download_dir, md5_hash + '-screenshots-apk/')): try: imp_path = os.path.join(download_dir, md5_hash + '-screenshots-apk/') for img in os.listdir(imp_path): if img.endswith('.png'): if img.startswith('act'): act_imgs.append(img) elif img.startswith('expact'): expact_imgs.append(img) else: imgs.append(img) sadb = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if sadb.exists(): logger.info('\nFetching Exported Activity' ' & Activity List from DB') exported_act = python_list(sadb[0].EXPORTED_ACT) act_desc = python_list(sadb[0].ACTIVITIES) if act_imgs: if len(act_imgs) == len(act_desc): act = dict(list(zip(act_imgs, act_desc))) if expact_imgs: if len(expact_imgs) == len(exported_act): exp_act = dict( list(zip(expact_imgs, exported_act))) else: logger.warning('Entry does not exists in the DB.') except Exception: logger.exception('Screenshot Sorting') context = { 'md5': md5_hash, 'emails': analysis_result['emails'], 'urls': analysis_result['urls'], 'domains': analysis_result['domains'], 'clipboard': analysis_result['clipboard'], 'http': analysis_result['web_data'], 'xml': analysis_result['xmlfiles'], 'sqlite': analysis_result['sqlite_db'], 'others': analysis_result['other_files'], 'imgs': imgs, 'acttest': act, 'expacttest': exp_act, 'net': api_analysis_result['api_net'], 'base64': api_analysis_result['api_base64'], 'crypto': api_analysis_result['api_crypto'], 'fileio': api_analysis_result['api_fileio'], 'binder': api_analysis_result['api_binder'], 'divinfo': api_analysis_result['api_deviceinfo'], 'cntval': api_analysis_result['api_cntvl'], 'sms': api_analysis_result['api_sms'], 'sysprop': api_analysis_result['api_sysprop'], 'dexload': api_analysis_result['api_dexloader'], 'reflect': api_analysis_result['api_reflect'], 'sysman': api_analysis_result['api_acntmnger'], 'process': api_analysis_result['api_cmd'], 'pkg': package, 'title': 'Dynamic Analysis' } template = 'dynamic_analysis/dynamic_analysis.html' return render(request, template, context) else: return print_n_send_error_response(request, 'Invalid Scan Hash') else: return print_n_send_error_response(request, 'Only GET allowed') except Exception: logger.exception('Dynamic Analysis Report Generation') err = 'Error Geneating Dynamic Analysis Report' return print_n_send_error_response(request, err)
def exported_activity_tester(request): """Exported Activity Tester""" logger.info("Exported Activity Tester") try: md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r";|\$\(|\|\||&&", package): return print_n_send_error_response(request, "Possible RCE Attack", True) if request.method == 'POST': base_dir = settings.BASE_DIR app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') screen_dir = os.path.join(app_dir, 'screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) data = {} adb = getADB() static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): logger.info("Fetching Exported Activity List from DB") exported_act = python_list( static_android_db[0].EXPORTED_ACT) if exported_act: exp_act_no = 0 logger.info("Starting Exported Activity Tester...") logger.info("" + str(len(exported_act)) + " Exported Activities Identified") for line in exported_act: try: exp_act_no += 1 logger.info("Launching Exported Activity - " + str(exp_act_no) + ". " + line) adb_command( ["am", "start", "-n", package + "/" + line], True) # AVD is much slower, it should get extra time if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": wait(8) else: wait(4) adb_command( ["screencap", "-p", "/data/local/screen.png"], True) #? get appended from Air :-() if activity names are used adb_command(["pull", "/data/local/screen.png", screen_dir + "expact-" + str(exp_act_no) + ".png"]) logger.info("Activity Screenshot Taken") adb_command( ["am", "force-stop", package], True) logger.info("Stopping App") except: PrintException( "Exported Activity Tester") data = {'expacttest': 'done'} else: logger.info( "Exported Activity Tester - No Activity Found!") data = {'expacttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: return print_n_send_error_response(request, "Entry does not exist in DB", True) else: return print_n_send_error_response(request, "Only POST allowed", True) else: return print_n_send_error_response(request, "Invalid Scan Hash", True) except: PrintException("ERROR] Exported Activity Tester") return print_n_send_error_response(request, "Error Running Exported Activity Tests", True)
def get_context_from_db_entry(db_entry: QuerySet) -> dict: """Return the context for APK/ZIP from DB""" try: logger.info("Analysis is already Done. Fetching data from the DB...") context = { 'title': db_entry[0].TITLE, 'name': db_entry[0].APP_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'packagename': db_entry[0].PACKAGENAME, 'mainactivity': db_entry[0].MAINACTIVITY, 'targetsdk': db_entry[0].TARGET_SDK, 'maxsdk': db_entry[0].MAX_SDK, 'minsdk': db_entry[0].MIN_SDK, 'androvername': db_entry[0].ANDROVERNAME, 'androver': db_entry[0].ANDROVER, 'manifest': python_list(db_entry[0].MANIFEST_ANAL), 'permissions': python_dict(db_entry[0].PERMISSIONS), 'binary_analysis': python_list(db_entry[0].BIN_ANALYSIS), 'files': python_list(db_entry[0].FILES), 'certz': db_entry[0].CERTZ, 'icon_hidden': db_entry[0].ICON_HIDDEN, 'icon_found': db_entry[0].ICON_FOUND, 'activities': python_list(db_entry[0].ACTIVITIES), 'receivers': python_list(db_entry[0].RECEIVERS), 'providers': python_list(db_entry[0].PROVIDERS), 'services': python_list(db_entry[0].SERVICES), 'libraries': python_list(db_entry[0].LIBRARIES), 'browsable_activities': python_dict(db_entry[0].BROWSABLE), 'act_count': db_entry[0].CNT_ACT, 'prov_count': db_entry[0].CNT_PRO, 'serv_count': db_entry[0].CNT_SER, 'bro_count': db_entry[0].CNT_BRO, 'certinfo': db_entry[0].CERT_INFO, 'issued': db_entry[0].ISSUED, 'sha256Digest': db_entry[0].SHA256DIGEST, 'api': python_dict(db_entry[0].API), 'findings': python_dict(db_entry[0].DANG), 'urls': python_list(db_entry[0].URLS), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EMAILS), 'strings': python_list(db_entry[0].STRINGS), 'zipped': db_entry[0].ZIPPED, 'mani': db_entry[0].MANI, 'e_act': db_entry[0].E_ACT, 'e_ser': db_entry[0].E_SER, 'e_bro': db_entry[0].E_BRO, 'e_cnt': db_entry[0].E_CNT, 'apkid': python_dict(db_entry[0].APK_ID), 'play_details': python_dict(db_entry[0].PLAY_DETAILS), 'firebase': python_list(db_entry[0].FIREBASE), } return context except: PrintException("Fetching from DB")
def staticanalyzer_windows(request): """Analyse a windows app.""" try: # Input validation print "[INFO] Windows Static Analysis Started" app_dic = {} # Dict to store the binary attributes typ = request.GET['type'] rescan = str(request.GET.get('rescan', 0)) md5_regex = re.match('^[0-9a-f]{32}$', request.GET['checksum']) if (md5_regex) and (typ in ['appx']): app_dic['app_name'] = request.GET['name'] # APP ORGINAL NAME app_dic['md5'] = request.GET['checksum'] app_dic['app_dir'] = os.path.join( settings.UPLD_DIR, app_dic['md5'] + '/') app_dic['tools_dir'] = os.path.join( settings.BASE_DIR, 'StaticAnalyzer/tools/windows/') if typ == 'appx': # DB db_entry = StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ) if db_entry.exists() and rescan == '0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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) } else: print "[INFO] Windows Binary Analysis Started" app_dic['app_path'] = os.path.join( app_dic['app_dir'], app_dic['md5'] + '.appx') # ANALYSIS BEGINS app_dic['size'] = str(FileSize(app_dic['app_path'])) + 'MB' # Generate hashes app_dic['sha1'], app_dic[ 'sha256'] = HashGen(app_dic['app_path']) # EXTRACT APPX print "[INFO] Extracting APPX" app_dic['files'] = Unzip( app_dic['app_path'], app_dic['app_dir']) xml_dic = _parse_xml(app_dic['app_dir']) bin_an_dic = _binary_analysis(app_dic) # Saving to db print "\n[INFO] Connecting to DB" if rescan == '1': print "\n[INFO] Updating Database..." StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ).update( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) elif rescan == '0': print "\n[INFO] Saving to Database" db_item = StaticAnalyzerWindows( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) db_item.save() context = { 'title': 'Static Analysis', 'name': app_dic['app_name'], 'pub_name': xml_dic['pub_name'], 'size': app_dic['size'], 'md5': app_dic['md5'], 'sha1': app_dic['sha1'], 'sha256': app_dic['sha256'], 'bin_name': bin_an_dic['bin_name'], 'version': xml_dic['version'], 'arch': xml_dic['arch'], 'compiler_version': xml_dic['compiler_version'], 'visual_studio_version': xml_dic['visual_studio_version'], 'visual_studio_edition': xml_dic['visual_studio_edition'], 'target_os': xml_dic['target_os'], 'appx_dll_version': xml_dic['appx_dll_version'], 'proj_guid': xml_dic['proj_guid'], 'opti_tool': xml_dic['opti_tool'], 'target_run': xml_dic['target_run'], 'files': app_dic['files'], 'strings': bin_an_dic['strings'], 'bin_an_results': bin_an_dic['results'], 'bin_an_warnings': bin_an_dic['warnings'], } template = "static_analysis/windows_binary_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except Exception as exception: PrintException("[ERROR] Static Analyzer Windows") context = { 'title': 'Error', 'exp': exception.message, 'doc': exception.__doc__ } template = "general/error.html" return render(request, template, context)
def api_analysis(package, location): """API Analysis""" api_analysis_result = {} logger.info("Dynamic API Analysis") dat = "" api_base64 = [] api_fileio = [] api_reflect = [] api_sysprop = [] api_cntvl = [] api_binder = [] api_crypto = [] api_acntmnger = [] api_deviceinfo = [] api_net = [] api_dexloader = [] api_cmd = [] api_sms = [] try: with open(location, "r", encoding="utf-8") as flip: dat = flip.readlines() res_id = "Droidmon-apimonitor-" + package + ":" for line in dat: if res_id in line: # print "LINE: " + line _, value = line.split(res_id, 1) # print "PARAM is :" + param # print "Value is :"+ value try: apis = json.loads(value, strict=False) ret = '' args = '' mtd = str(apis["method"]) clss = str(apis["class"]) # print "Called Class: " + CLS # print "Called Method: " + MTD if apis.get('return'): ret = str(apis["return"]) # print "Return Data: " + RET else: # print "No Return Data" ret = "No Return Data" if apis.get('args'): args = str(apis["args"]) # print "Passed Arguments" + ARGS else: # print "No Arguments Passed" args = "No Arguments Passed" # XSS Safe call_data = "</br>METHOD: " + \ escape(mtd) + "</br>ARGUMENTS: " + escape(args) + \ "</br>RETURN DATA: " + escape(ret) if re.findall("android.util.Base64", clss): # Base64 Decode if "decode" in mtd: args_list = python_list(args) if isBase64(args_list[0]): call_data += '</br><span class="label label-info">' +\ 'Decoded String:</span> ' + \ escape(base64.b64decode(args_list[0])) api_base64.append(call_data) if re.findall('libcore.io|android.app.SharedPreferencesImpl\$EditorImpl', clss): api_fileio.append(call_data) if re.findall('java.lang.reflect', clss): api_reflect.append(call_data) if re.findall('android.content.ContentResolver|android.location.Location|android.media.AudioRecord|android.media.MediaRecorder|android.os.SystemProperties', clss): api_sysprop.append(call_data) if re.findall('android.app.Activity|android.app.ContextImpl|android.app.ActivityThread', clss): api_binder.append(call_data) if re.findall('javax.crypto.spec.SecretKeySpec|javax.crypto.Cipher|javax.crypto.Mac', clss): api_crypto.append(call_data) if re.findall('android.accounts.AccountManager|android.app.ApplicationPackageManager|android.app.NotificationManager|android.net.ConnectivityManager|android.content.BroadcastReceiver', clss): api_acntmnger.append(call_data) if re.findall('android.telephony.TelephonyManager|android.net.wifi.WifiInfo|android.os.Debug', clss): api_deviceinfo.append(call_data) if re.findall('dalvik.system.BaseDexClassLoader|dalvik.system.DexFile|dalvik.system.DexClassLoader|dalvik.system.PathClassLoader', clss): api_dexloader.append(call_data) if re.findall('java.lang.Runtime|java.lang.ProcessBuilder|java.io.FileOutputStream|java.io.FileInputStream|android.os.Process', clss): api_cmd.append(call_data) if re.findall('android.content.ContentValues', clss): api_cntvl.append(call_data) if re.findall('android.telephony.SmsManager', clss): api_sms.append(call_data) if re.findall('java.net.URL|org.apache.http.impl.client.AbstractHttpClient', clss): api_net.append(call_data) except: PrintException("Parsing JSON Failed for: " + value) except: PrintException("Dynamic API Analysis") api_analysis_result["api_net"] = list(set(api_net)) api_analysis_result["api_base64"] = list(set(api_base64)) api_analysis_result["api_fileio"] = list(set(api_fileio)) api_analysis_result["api_binder"] = list(set(api_binder)) api_analysis_result["api_crypto"] = list(set(api_crypto)) api_analysis_result["api_deviceinfo"] = list(set(api_deviceinfo)) api_analysis_result["api_cntvl"] = list(set(api_cntvl)) api_analysis_result["api_sms"] = list(set(api_sms)) api_analysis_result["api_sysprop"] = list(set(api_sysprop)) api_analysis_result["api_dexloader"] = list(set(api_dexloader)) api_analysis_result["api_reflect"] = list(set(api_reflect)) api_analysis_result["api_acntmnger"] = list(set(api_acntmnger)) api_analysis_result["api_cmd"] = list(set(api_cmd)) return api_analysis_result
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 report(request): """Dynamic Analysis Report Generation""" print("\n[INFO] Dynamic Analysis Report Generation") try: if request.method == 'GET': md5_hash = request.GET['md5'] package = request.GET['pkg'] if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if re.match('^[0-9a-f]{32}$', md5_hash): app_dir = os.path.join( settings.UPLD_DIR, md5_hash + '/') # APP DIRECTORY download_dir = settings.DWD_DIR droidmon_api_loc = os.path.join(app_dir, 'x_logcat.txt') api_analysis_result = api_analysis(package, droidmon_api_loc) analysis_result = run_analysis(app_dir, md5_hash, package) download(md5_hash, download_dir, app_dir, package) # Only After Download Process is Done imgs = [] act_imgs = [] act = {} expact_imgs = [] exp_act = {} if os.path.exists(os.path.join(download_dir, md5_hash + "-screenshots-apk/")): try: imp_path = os.path.join( download_dir, md5_hash + "-screenshots-apk/") for img in os.listdir(imp_path): if img.endswith(".png"): if img.startswith("act"): act_imgs.append(img) elif img.startswith("expact"): expact_imgs.append(img) else: imgs.append(img) static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): print( "\n[INFO] Fetching Exported Activity & Activity List from DB") exported_act = python_list( static_android_db[0].EXPORTED_ACT) act_desc = python_list( static_android_db[0].ACTIVITIES) if act_imgs: if len(act_imgs) == len(act_desc): act = dict(list(zip(act_imgs, act_desc))) if expact_imgs: if len(expact_imgs) == len(exported_act): exp_act = dict( list(zip(expact_imgs, exported_act))) else: print( "\n[WARNING] Entry does not exists in the DB.") except: PrintException("[ERROR] Screenshot Sorting") context = {'md5': md5_hash, 'emails': analysis_result["emails"], 'urls': analysis_result["urls"], 'domains': analysis_result["domains"], 'clipboard': analysis_result["clipboard"], 'http': analysis_result["web_data"], 'xml': analysis_result["xmlfiles"], 'sqlite': analysis_result["sqlite_db"], 'others': analysis_result["other_files"], 'imgs': imgs, 'acttest': act, 'expacttest': exp_act, 'net': api_analysis_result["api_net"], 'base64': api_analysis_result["api_base64"], 'crypto': api_analysis_result["api_crypto"], 'fileio': api_analysis_result["api_fileio"], 'binder': api_analysis_result["api_binder"], 'divinfo': api_analysis_result["api_deviceinfo"], 'cntval': api_analysis_result["api_cntvl"], 'sms': api_analysis_result["api_sms"], 'sysprop': api_analysis_result["api_sysprop"], 'dexload': api_analysis_result["api_dexloader"], 'reflect': api_analysis_result["api_reflect"], 'sysman': api_analysis_result["api_acntmnger"], 'process': api_analysis_result["api_cmd"], 'pkg': package, 'title': 'Dynamic Analysis'} template = "dynamic_analysis/dynamic_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Dynamic Analysis Report Generation") return HttpResponseRedirect('/error/')
def get_context_from_db_entry(db_entry: QuerySet) -> dict: """Return the context for APK/ZIP from DB.""" try: logger.info('Analysis is already Done. Fetching data from the DB...') context = { 'version': settings.MOBSF_VER, 'title': 'Static Analysis', 'file_name': db_entry[0].FILE_NAME, 'app_name': db_entry[0].APP_NAME, 'app_type': db_entry[0].APP_TYPE, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'package_name': db_entry[0].PACKAGE_NAME, 'main_activity': db_entry[0].MAIN_ACTIVITY, 'exported_activities': db_entry[0].EXPORTED_ACTIVITIES, 'browsable_activities': python_dict( db_entry[0].BROWSABLE_ACTIVITIES), 'activities': python_list(db_entry[0].ACTIVITIES), 'receivers': python_list(db_entry[0].RECEIVERS), 'providers': python_list(db_entry[0].PROVIDERS), 'services': python_list(db_entry[0].SERVICES), 'libraries': python_list(db_entry[0].LIBRARIES), 'target_sdk': db_entry[0].TARGET_SDK, 'max_sdk': db_entry[0].MAX_SDK, 'min_sdk': db_entry[0].MIN_SDK, 'version_name': db_entry[0].VERSION_NAME, 'version_code': db_entry[0].VERSION_CODE, 'icon_hidden': db_entry[0].ICON_HIDDEN, 'icon_found': db_entry[0].ICON_FOUND, 'permissions': python_dict(db_entry[0].PERMISSIONS), 'certificate_analysis': python_dict( db_entry[0].CERTIFICATE_ANALYSIS), 'manifest_analysis': python_list(db_entry[0].MANIFEST_ANALYSIS), 'network_security': python_list(db_entry[0].NETWORK_SECURITY), 'binary_analysis': python_list(db_entry[0].BINARY_ANALYSIS), 'file_analysis': python_list(db_entry[0].FILE_ANALYSIS), 'android_api': python_dict(db_entry[0].ANDROID_API), 'code_analysis': python_dict(db_entry[0].CODE_ANALYSIS), 'urls': python_list(db_entry[0].URLS), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EMAILS), 'strings': python_list(db_entry[0].STRINGS), 'firebase_urls': python_list(db_entry[0].FIREBASE_URLS), 'files': python_list(db_entry[0].FILES), 'exported_count': python_dict(db_entry[0].EXPORTED_COUNT), 'apkid': python_dict(db_entry[0].APKID), 'trackers': python_dict(db_entry[0].TRACKERS), 'playstore_details': python_dict(db_entry[0].PLAYSTORE_DETAILS), } return context except Exception: logger.exception('Fetching from DB')
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 = { 'title' : DB[0].TITLE, 'name' : DB[0].APP_NAME, 'size' : DB[0].SIZE, 'md5': DB[0].MD5, 'sha1' : DB[0].SHA1, 'sha256' : DB[0].SHA256, 'packagename' : DB[0].PACKAGENAME, 'mainactivity' : DB[0].MAINACTIVITY, 'targetsdk' : DB[0].TARGET_SDK, 'maxsdk' : DB[0].MAX_SDK, 'minsdk' : DB[0].MIN_SDK, 'androvername' : DB[0].ANDROVERNAME, 'androver': DB[0].ANDROVER, 'manifest': DB[0].MANIFEST_ANAL, 'permissions' : DB[0].PERMISSIONS, 'files' : python_list(DB[0].FILES), 'certz' : DB[0].CERTZ, 'activities' : python_list(DB[0].ACTIVITIES), 'receivers' : python_list(DB[0].RECEIVERS), 'providers' : python_list(DB[0].PROVIDERS), 'services' : python_list(DB[0].SERVICES), 'libraries' : python_list(DB[0].LIBRARIES), 'act_count' : DB[0].CNT_ACT, 'prov_count' : DB[0].CNT_PRO, 'serv_count' : DB[0].CNT_SER, 'bro_count' : DB[0].CNT_BRO, 'certinfo': DB[0].CERT_INFO, 'issued':DB[0].ISSUED, 'native' : DB[0].NATIVE, 'dynamic' : DB[0].DYNAMIC, 'reflection' : DB[0].REFLECT, 'crypto': DB[0].CRYPTO, 'obfus': DB[0].OBFUS, 'api': DB[0].API, 'dang': DB[0].DANG, 'urls': DB[0].URLS, 'domains': python_dict(DB[0].DOMAINS), 'emails': DB[0].EMAILS, 'strings': python_list(DB[0].STRINGS), 'zipped' : DB[0].ZIPPED, 'mani': DB[0].MANI } if TYP=='APK': template= get_template("static_analysis_pdf.html") else: template= get_template("static_analysis_zip_pdf.html") 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' : DB[0].STRINGS } template= get_template("ios_binary_analysis_pdf.html") 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 } template= get_template("ios_source_analysis_pdf.html") else: return HttpResponseRedirect('/error/') 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 HttpResponseRedirect('/error/') except: PrintException("[ERROR] PDF Report Generation Error") return HttpResponseRedirect('/error/')
def Report(request): print "\n[INFO] Dynamic Analysis Report Generation" try: if request.method == "GET": MD5 = request.GET["md5"] PKG = request.GET["pkg"] if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect("/error/") m = re.match("^[0-9a-f]{32}$", MD5) if m: DIR = settings.BASE_DIR APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + "/") # APP DIRECTORY DWD_DIR = settings.DWD_DIR DRDMONAPISLOC = os.path.join(APP_DIR, "x_logcat.txt") # Use check_outputs instead later. API_NET, API_BASE64, API_FILEIO, API_BINDER, API_CRYPTO, API_DEVICEINFO, API_CNTVL, API_SMS, API_SYSPROP, API_DEXLOADER, API_RELECT, API_ACNTMNGER, API_CMD = APIAnalysis( PKG, DRDMONAPISLOC ) URL, DOMAINS, EMAIL, HTTP, XML, SQLiteDB, OtherFiles = RunAnalysis(APP_DIR, MD5, PKG) Download(MD5, DWD_DIR, APP_DIR, PKG) # Only After Download Process is Done IMGS = [] ACTIMGS = [] ACT = {} EXPACTIMGS = [] EXPACT = {} if os.path.exists(os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): try: for img in os.listdir(os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): if img.endswith(".png"): if img.startswith("act"): ACTIMGS.append(img) elif img.startswith("expact"): EXPACTIMGS.append(img) else: IMGS.append(img) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Exported Activity & Activity List from DB" EXPORTED_ACT = python_list(DB[0].EXPORTED_ACT) ACTDESC = python_list(DB[0].ACTIVITIES) if ACTIMGS: if len(ACTIMGS) == len(ACTDESC): ACT = dict(zip(ACTIMGS, ACTDESC)) if EXPACTIMGS: if len(EXPACTIMGS) == len(EXPORTED_ACT): EXPACT = dict(zip(EXPACTIMGS, EXPORTED_ACT)) else: print "\n[WARNING] Entry does not exists in the DB." except: PrintException("[ERROR] Screenshot Sorting") context = { "emails": EMAIL, "urls": URL, "domains": DOMAINS, "md5": MD5, "http": HTTP, "xml": XML, "sqlite": SQLiteDB, "others": OtherFiles, "imgs": IMGS, "acttest": ACT, "expacttest": EXPACT, "net": API_NET, "base64": API_BASE64, "crypto": API_CRYPTO, "fileio": API_FILEIO, "binder": API_BINDER, "divinfo": API_DEVICEINFO, "cntval": API_CNTVL, "sms": API_SMS, "sysprop": API_SYSPROP, "dexload": API_DEXLOADER, "reflect": API_RELECT, "sysman": API_ACNTMNGER, "process": API_CMD, "pkg": PKG, "title": "Dynamic Analysis", } template = "dynamic_analysis.html" return render(request, template, context) else: return HttpResponseRedirect("/error/") else: return HttpResponseRedirect("/error/") except: PrintException("[ERROR] Dynamic Analysis Report Generation") return HttpResponseRedirect("/error/")
def api_analysis(package, location): """API Analysis""" api_analysis_result = {} print("\n[INFO] Dynamic API Analysis") dat = "" api_base64 = [] api_fileio = [] api_reflect = [] api_sysprop = [] api_cntvl = [] api_binder = [] api_crypto = [] api_acntmnger = [] api_deviceinfo = [] api_net = [] api_dexloader = [] api_cmd = [] api_sms = [] try: with open(location, "r") as flip: dat = flip.readlines() res_id = "Droidmon-apimonitor-" + package + ":" for line in dat: if res_id in line: # print "LINE: " + line _, value = line.split(res_id, 1) # print "PARAM is :" + param # print "Value is :"+ value try: apis = json.loads(value, strict=False) ret = '' args = '' mtd = str(apis["method"]) clss = str(apis["class"]) # print "Called Class: " + CLS # print "Called Method: " + MTD if apis.get('return'): ret = str(apis["return"]) # print "Return Data: " + RET else: # print "No Return Data" ret = "No Return Data" if apis.get('args'): args = str(apis["args"]) # print "Passed Arguments" + ARGS else: # print "No Arguments Passed" args = "No Arguments Passed" # XSS Safe call_data = "</br>METHOD: " + \ escape(mtd) + "</br>ARGUMENTS: " + escape(args) + \ "</br>RETURN DATA: " + escape(ret) if re.findall("android.util.Base64", clss): # Base64 Decode if "decode" in mtd: args_list = python_list(args) if isBase64(args_list[0]): call_data += '</br><span class="label label-info">' +\ 'Decoded String:</span> ' + \ escape(base64.b64decode(args_list[0])) api_base64.append(call_data) if re.findall('libcore.io|android.app.SharedPreferencesImpl\$EditorImpl', clss): api_fileio.append(call_data) if re.findall('java.lang.reflect', clss): api_reflect.append(call_data) if re.findall('android.content.ContentResolver|android.location.Location|android.media.AudioRecord|android.media.MediaRecorder|android.os.SystemProperties', clss): api_sysprop.append(call_data) if re.findall('android.app.Activity|android.app.ContextImpl|android.app.ActivityThread', clss): api_binder.append(call_data) if re.findall('javax.crypto.spec.SecretKeySpec|javax.crypto.Cipher|javax.crypto.Mac', clss): api_crypto.append(call_data) if re.findall('android.accounts.AccountManager|android.app.ApplicationPackageManager|android.app.NotificationManager|android.net.ConnectivityManager|android.content.BroadcastReceiver', clss): api_acntmnger.append(call_data) if re.findall('android.telephony.TelephonyManager|android.net.wifi.WifiInfo|android.os.Debug', clss): api_deviceinfo.append(call_data) if re.findall('dalvik.system.BaseDexClassLoader|dalvik.system.DexFile|dalvik.system.DexClassLoader|dalvik.system.PathClassLoader', clss): api_dexloader.append(call_data) if re.findall('java.lang.Runtime|java.lang.ProcessBuilder|java.io.FileOutputStream|java.io.FileInputStream|android.os.Process', clss): api_cmd.append(call_data) if re.findall('android.content.ContentValues', clss): api_cntvl.append(call_data) if re.findall('android.telephony.SmsManager', clss): api_sms.append(call_data) if re.findall('java.net.URL|org.apache.http.impl.client.AbstractHttpClient', clss): api_net.append(call_data) except: PrintException("[ERROR] Parsing JSON Failed for: " + value) except: PrintException("[ERROR] Dynamic API Analysis") api_analysis_result["api_net"] = list(set(api_net)) api_analysis_result["api_base64"] = list(set(api_base64)) api_analysis_result["api_fileio"] = list(set(api_fileio)) api_analysis_result["api_binder"] = list(set(api_binder)) api_analysis_result["api_crypto"] = list(set(api_crypto)) api_analysis_result["api_deviceinfo"] = list(set(api_deviceinfo)) api_analysis_result["api_cntvl"] = list(set(api_cntvl)) api_analysis_result["api_sms"] = list(set(api_sms)) api_analysis_result["api_sysprop"] = list(set(api_sysprop)) api_analysis_result["api_dexloader"] = list(set(api_dexloader)) api_analysis_result["api_reflect"] = list(set(api_reflect)) api_analysis_result["api_acntmnger"] = list(set(api_acntmnger)) api_analysis_result["api_cmd"] = list(set(api_cmd)) return api_analysis_result
def staticanalyzer_windows(request, api=False): """Analyse a windows app.""" try: # Input validation print "[INFO] Windows Static Analysis Started" app_dic = {} # Dict to store the binary attributes if api: typ = request.POST['scan_type'] rescan = str(request.POST.get('re_scan', 0)) checksum = request.POST['hash'] filename = request.POST['file_name'] else: typ = request.GET['type'] rescan = str(request.GET.get('rescan', 0)) checksum = request.GET['checksum'] filename = request.GET['name'] md5_regex = re.match('^[0-9a-f]{32}$', checksum) if (md5_regex) and (typ in ['appx']): app_dic['app_name'] = filename # APP ORGINAL NAME app_dic['md5'] = checksum app_dic['app_dir'] = os.path.join( settings.UPLD_DIR, app_dic['md5'] + '/') app_dic['tools_dir'] = os.path.join( settings.BASE_DIR, 'StaticAnalyzer/tools/windows/') if typ == 'appx': # DB db_entry = StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ) if db_entry.exists() and rescan == '0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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) } else: print "[INFO] Windows Binary Analysis Started" app_dic['app_path'] = os.path.join( app_dic['app_dir'], app_dic['md5'] + '.appx') # ANALYSIS BEGINS app_dic['size'] = str(file_size(app_dic['app_path'])) + 'MB' # Generate hashes app_dic['sha1'], app_dic[ 'sha256'] = hash_gen(app_dic['app_path']) # EXTRACT APPX print "[INFO] Extracting APPX" app_dic['files'] = unzip( app_dic['app_path'], app_dic['app_dir']) xml_dic = _parse_xml(app_dic['app_dir']) bin_an_dic = _binary_analysis(app_dic) # Saving to db print "\n[INFO] Connecting to DB" if rescan == '1': print "\n[INFO] Updating Database..." StaticAnalyzerWindows.objects.filter( # pylint: disable-msg=E1101 MD5=app_dic['md5'] ).update( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) elif rescan == '0': print "\n[INFO] Saving to Database" db_item = StaticAnalyzerWindows( TITLE='Static Analysis', APP_NAME=app_dic['app_name'], PUB_NAME=xml_dic['pub_name'], SIZE=app_dic['size'], MD5=app_dic['md5'], SHA1=app_dic['sha1'], SHA256=app_dic['sha256'], BINNAME=bin_an_dic['bin_name'], VERSION=xml_dic['version'], ARCH=xml_dic['arch'], COMPILER_VERSION=xml_dic['compiler_version'], VISUAL_STUDIO_VERSION=xml_dic[ 'visual_studio_version'], VISUAL_STUDIO_EDITION=xml_dic[ 'visual_studio_edition'], TARGET_OS=xml_dic['target_os'], APPX_DLL_VERSION=xml_dic['appx_dll_version'], PROJ_GUID=xml_dic['proj_guid'], OPTI_TOOL=xml_dic['opti_tool'], TARGET_RUN=xml_dic['target_run'], FILES=app_dic['files'], STRINGS=bin_an_dic['strings'], BIN_AN_RESULTS=bin_an_dic['results'], BIN_AN_WARNINGS=bin_an_dic['warnings'], ) db_item.save() context = { 'title': 'Static Analysis', 'name': app_dic['app_name'], 'pub_name': xml_dic['pub_name'], 'size': app_dic['size'], 'md5': app_dic['md5'], 'sha1': app_dic['sha1'], 'sha256': app_dic['sha256'], 'bin_name': bin_an_dic['bin_name'], 'version': xml_dic['version'], 'arch': xml_dic['arch'], 'compiler_version': xml_dic['compiler_version'], 'visual_studio_version': xml_dic['visual_studio_version'], 'visual_studio_edition': xml_dic['visual_studio_edition'], 'target_os': xml_dic['target_os'], 'appx_dll_version': xml_dic['appx_dll_version'], 'proj_guid': xml_dic['proj_guid'], 'opti_tool': xml_dic['opti_tool'], 'target_run': xml_dic['target_run'], 'files': app_dic['files'], 'strings': bin_an_dic['strings'], 'bin_an_results': bin_an_dic['results'], 'bin_an_warnings': bin_an_dic['warnings'], } template = "static_analysis/windows_binary_analysis.html" if api: return context else: return render(request, template, context) else: msg = "File type not supported" if api: return print_n_send_error_response(request, msg, True) else: return print_n_send_error_response(request, msg, False) else: msg = "Hash match failed or Invalid file extension" if api: return print_n_send_error_response(request, msg, True) else: return print_n_send_error_response(request, msg, False) except Exception as exception: msg = str(exception) exp_doc = exception.__doc__ if api: return print_n_send_error_response(request, msg, True, exp_doc) else: return print_n_send_error_response(request, msg, False, exp_doc)
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 Report(request): print "\n[INFO] Dynamic Analysis Report Generation" try: if request.method == 'GET': MD5 = request.GET['md5'] PKG = request.GET['pkg'] if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect('/error/') m = re.match('^[0-9a-f]{32}$', MD5) if m: DIR = settings.BASE_DIR APP_DIR = os.path.join( settings.UPLD_DIR, MD5 + '/') # APP DIRECTORY DWD_DIR = settings.DWD_DIR DRDMONAPISLOC = os.path.join(APP_DIR, 'x_logcat.txt') API_NET, API_BASE64, API_FILEIO, API_BINDER, API_CRYPTO, API_DEVICEINFO, API_CNTVL, API_SMS, API_SYSPROP, API_DEXLOADER, API_RELECT, API_ACNTMNGER, API_CMD = APIAnalysis( PKG, DRDMONAPISLOC) URL, DOMAINS, EMAIL, CLIPBOARD, HTTP, XML, SQLiteDB, OtherFiles = RunAnalysis( APP_DIR, MD5, PKG) Download(MD5, DWD_DIR, APP_DIR, PKG) # Only After Download Process is Done IMGS = [] ACTIMGS = [] ACT = {} EXPACTIMGS = [] EXPACT = {} if os.path.exists(os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): try: for img in os.listdir(os.path.join(DWD_DIR, MD5 + "-screenshots-apk/")): if img.endswith(".png"): if img.startswith("act"): ACTIMGS.append(img) elif img.startswith("expact"): EXPACTIMGS.append(img) else: IMGS.append(img) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Exported Activity & Activity List from DB" EXPORTED_ACT = python_list(DB[0].EXPORTED_ACT) ACTDESC = python_list(DB[0].ACTIVITIES) if ACTIMGS: if len(ACTIMGS) == len(ACTDESC): ACT = dict(zip(ACTIMGS, ACTDESC)) if EXPACTIMGS: if len(EXPACTIMGS) == len(EXPORTED_ACT): EXPACT = dict( zip(EXPACTIMGS, EXPORTED_ACT)) else: print "\n[WARNING] Entry does not exists in the DB." except: PrintException("[ERROR] Screenshot Sorting") context = {'emails': EMAIL, 'urls': URL, 'domains': DOMAINS, 'clipboard': CLIPBOARD, 'md5': MD5, 'http': HTTP, 'xml': XML, 'sqlite': SQLiteDB, 'others': OtherFiles, 'imgs': IMGS, 'acttest': ACT, 'expacttest': EXPACT, 'net': API_NET, 'base64': API_BASE64, 'crypto': API_CRYPTO, 'fileio': API_FILEIO, 'binder': API_BINDER, 'divinfo': API_DEVICEINFO, 'cntval': API_CNTVL, 'sms': API_SMS, 'sysprop': API_SYSPROP, 'dexload': API_DEXLOADER, 'reflect': API_RELECT, 'sysman': API_ACNTMNGER, 'process': API_CMD, 'pkg': PKG, 'title': 'Dynamic Analysis'} template = "dynamic_analysis/dynamic_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Dynamic Analysis Report Generation") return HttpResponseRedirect('/error/')
def activity_tester(request): """Activity Tester""" logger.info("Activity Tester") try: md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r";|\$\(|\|\||&&", package): logger.info("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if request.method == 'POST': base_dir = settings.BASE_DIR app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') screen_dir = os.path.join(app_dir, 'screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) data = {} adb = getADB() static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): logger.info("Fetching Activity List from DB") activities = python_list(static_android_db[0].ACTIVITIES) if activities: act_no = 0 logger.info("Starting Activity Tester...") logger.info("" + str(len(activities)) + " Activities Identified") for line in activities: try: act_no += 1 logger.info("Launching Activity - " + str(act_no) + ". " + line) adb_command([ "am", "start", "-n", package + "/" + line ], True) # AVD is much slower, it should get extra time if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": wait(8) else: wait(4) adb_command([ "screencap", "-p", "/data/local/screen.png" ], True) #? get appended from Air :-() if activity names are used adb_command([ "pull", "/data/local/screen.png", screen_dir + "act-" + str(act_no) + ".png" ]) logger.info("Activity Screenshot Taken") adb_command(["am", "force-stop", package], True) logger.info("Stopping App") except: PrintException("Activity Tester") data = {'acttest': 'done'} else: logger.info("Activity Tester - No Activity Found!") data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: logger.error("Entry does not exist in DB.") return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Activity Tester") return HttpResponseRedirect('/error/')
def get_context_from_db_entry_ios(db_entry): """Return the context for IOS ZIP from DB""" try: print( "\n[INFO] Analysis is already Done. Fetching data from the DB...") context = { 'title': db_entry[0].TITLE, 'file_name': db_entry[0].FILE_NAME, 'size': db_entry[0].SIZE, 'md5': db_entry[0].MD5, 'sha1': db_entry[0].SHA1, 'sha256': db_entry[0].SHA256, 'plist': db_entry[0].INFOPLIST, 'bin_name': db_entry[0].BINNAME, 'id': db_entry[0].IDF, 'build': db_entry[0].BUILD, 'version': db_entry[0].VERSION, 'sdk': db_entry[0].SDK, 'pltfm': db_entry[0].PLTFM, 'min': db_entry[0].MINX, 'files': python_list(db_entry[0].FILES), 'file_analysis': python_list(db_entry[0].SFILESX), 'api': python_dict(db_entry[0].API), 'insecure': python_dict(db_entry[0].CODEANAL), 'urls': python_list(db_entry[0].URLnFile), 'domains': python_dict(db_entry[0].DOMAINS), 'emails': python_list(db_entry[0].EmailnFile), 'permissions': python_list(db_entry[0].PERMISSIONS), 'insecure_connections': python_list(db_entry[0].INSECCON), 'bundle_name': db_entry[0].BUNDLE_NAME, 'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES), 'bundle_supported_platforms': python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS), 'bundle_localizations': python_list(db_entry[0].BUNDLE_LOCALIZATIONS), } return context except: PrintException("[ERROR] Fetching from DB")
def ExportedActivityTester(request): print "\n[INFO] Exported Activity Tester" try: MD5 = request.POST["md5"] PKG = request.POST["pkg"] m = re.match("^[0-9a-f]{32}$", MD5) if m: if re.findall(";|\$\(|\|\||&&", PKG): print "[ATTACK] Possible RCE" return HttpResponseRedirect("/error/") if request.method == "POST": DIR = settings.BASE_DIR APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + "/") TOOLS_DIR = os.path.join(DIR, "DynamicAnalyzer/tools/") # TOOLS DIR SCRDIR = os.path.join(APP_DIR, "screenshots-apk/") data = {} adb = getADB(TOOLS_DIR) DB = StaticAnalyzerAndroid.objects.filter(MD5=MD5) if DB.exists(): print "\n[INFO] Fetching Exported Activity List from DB" EXPORTED_ACT = python_list(DB[0].EXPORTED_ACT) if EXPORTED_ACT: n = 0 print "\n[INFO] Starting Exported Activity Tester..." print "\n[INFO] " + str(len(EXPORTED_ACT)) + " Exported Activities Identified" for line in EXPORTED_ACT: try: n += 1 print "\n[INFO] Launching Exported Activity - " + str(n) + ". " + line subprocess.call( [adb, "-s", getIdentifier(), "shell", "am", "start", "-n", PKG + "/" + line] ) Wait(4) subprocess.call( [adb, "-s", getIdentifier(), "shell", "screencap", "-p", "/data/local/screen.png"] ) # ? get appended from Air :-() if activity names are used subprocess.call( [ adb, "-s", getIdentifier(), "pull", "/data/local/screen.png", SCRDIR + "expact-" + str(n) + ".png", ] ) print "\n[INFO] Activity Screenshot Taken" subprocess.call([adb, "-s", getIdentifier(), "shell", "am", "force-stop", PKG]) print "\n[INFO] Stopping App" except: PrintException("[ERROR] Exported Activity Tester") data = {"expacttest": "done"} else: print "\n[INFO] Exported Activity Tester - No Activity Found!" data = {"expacttest": "noact"} return HttpResponse(json.dumps(data), content_type="application/json") else: print "\n[ERROR] Entry does not exist in DB." return HttpResponseRedirect("/error/") else: return HttpResponseRedirect("/error/") else: return HttpResponseRedirect("/error/") except: PrintException("ERROR] Exported Activity Tester") return HttpResponseRedirect("/error/")
def report(request): """Dynamic Analysis Report Generation""" logger.info("Dynamic Analysis Report Generation") try: if request.method == 'GET': md5_hash = request.GET['md5'] package = request.GET['pkg'] if re.findall(r";|\$\(|\|\||&&", package): logger.info("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if re.match('^[0-9a-f]{32}$', md5_hash): app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') # APP DIRECTORY download_dir = settings.DWD_DIR droidmon_api_loc = os.path.join(app_dir, 'x_logcat.txt') api_analysis_result = api_analysis(package, droidmon_api_loc) analysis_result = run_analysis(app_dir, md5_hash, package) download(md5_hash, download_dir, app_dir, package) # Only After Download Process is Done imgs = [] act_imgs = [] act = {} expact_imgs = [] exp_act = {} if os.path.exists( os.path.join(download_dir, md5_hash + "-screenshots-apk/")): try: imp_path = os.path.join(download_dir, md5_hash + "-screenshots-apk/") for img in os.listdir(imp_path): if img.endswith(".png"): if img.startswith("act"): act_imgs.append(img) elif img.startswith("expact"): expact_imgs.append(img) else: imgs.append(img) static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): logger.info( "\n[INFO] Fetching Exported Activity & Activity List from DB" ) exported_act = python_list( static_android_db[0].EXPORTED_ACT) act_desc = python_list( static_android_db[0].ACTIVITIES) if act_imgs: if len(act_imgs) == len(act_desc): act = dict(list(zip(act_imgs, act_desc))) if expact_imgs: if len(expact_imgs) == len(exported_act): exp_act = dict( list(zip(expact_imgs, exported_act))) else: logger.warning("Entry does not exists in the DB.") except: PrintException("[ERROR] Screenshot Sorting") context = { 'md5': md5_hash, 'emails': analysis_result["emails"], 'urls': analysis_result["urls"], 'domains': analysis_result["domains"], 'clipboard': analysis_result["clipboard"], 'http': analysis_result["web_data"], 'xml': analysis_result["xmlfiles"], 'sqlite': analysis_result["sqlite_db"], 'others': analysis_result["other_files"], 'imgs': imgs, 'acttest': act, 'expacttest': exp_act, 'net': api_analysis_result["api_net"], 'base64': api_analysis_result["api_base64"], 'crypto': api_analysis_result["api_crypto"], 'fileio': api_analysis_result["api_fileio"], 'binder': api_analysis_result["api_binder"], 'divinfo': api_analysis_result["api_deviceinfo"], 'cntval': api_analysis_result["api_cntvl"], 'sms': api_analysis_result["api_sms"], 'sysprop': api_analysis_result["api_sysprop"], 'dexload': api_analysis_result["api_dexloader"], 'reflect': api_analysis_result["api_reflect"], 'sysman': api_analysis_result["api_acntmnger"], 'process': api_analysis_result["api_cmd"], 'pkg': package, 'title': 'Dynamic Analysis' } template = "dynamic_analysis/dynamic_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Dynamic Analysis Report Generation") return HttpResponseRedirect('/error/')
def StaticAnalyzer_iOS(request): try: #Input validation print "[INFO] iOS Static Analysis Started" TYP=request.GET['type'] RESCAN= str(request.GET.get('rescan', 0)) m=re.match('^[0-9a-f]{32}$',request.GET['checksum']) if ((m) and (request.GET['name'].lower().endswith('.ipa') or request.GET['name'].lower().endswith('.zip')) and (TYP in ['ipa', 'ios'])): DIR=settings.BASE_DIR #BASE DIR APP_NAME=request.GET['name'] #APP ORGINAL NAME MD5=request.GET['checksum'] #MD5 APP_DIR=os.path.join(settings.UPLD_DIR, MD5+'/') #APP DIRECTORY TOOLS_DIR=os.path.join(DIR, 'StaticAnalyzer/tools/mac/') #TOOLS DIR if TYP=='ipa': #DB DB=StaticAnalyzerIPA.objects.filter(MD5=MD5) if DB.exists() and RESCAN=='0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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' : DB[0].STRINGS, } else: print "[INFO] iOS Binary (IPA) Analysis Started" APP_FILE=MD5 + '.ipa' #NEW FILENAME APP_PATH=APP_DIR+APP_FILE #APP PATH BIN_DIR=os.path.join(APP_DIR,"Payload/") #ANALYSIS BEGINS SIZE=str(FileSize(APP_PATH)) + 'MB' #FILE SIZE SHA1, SHA256= HashGen(APP_PATH) #SHA1 & SHA256 HASHES print "[INFO] Extracting IPA" Unzip(APP_PATH,APP_DIR) #EXTRACT IPA FILES,SFILES=iOS_ListFiles(BIN_DIR,MD5,True,'ipa') #Get Files, normalize + to x, and convert binary plist -> xml INFO_PLIST,BIN_NAME,ID,VER,SDK,PLTFM,MIN,LIBS,BIN_ANAL,STRINGS=BinaryAnalysis(BIN_DIR,TOOLS_DIR,APP_DIR) #Saving to DB print "\n[INFO] Connecting to DB" if RESCAN=='1': print "\n[INFO] Updating Database..." StaticAnalyzerIPA.objects.filter(MD5=MD5).update(TITLE='Static Analysis',APPNAMEX=APP_NAME,SIZE=SIZE,MD5=MD5,SHA1=SHA1,SHA256=SHA256,INFOPLIST=INFO_PLIST,BINNAME=BIN_NAME,IDF=ID,VERSION=VER,SDK=SDK,PLTFM=PLTFM,MINX=MIN,BIN_ANAL=BIN_ANAL,LIBS=LIBS,FILES=FILES,SFILESX=SFILES,STRINGS=STRINGS) elif RESCAN=='0': print "\n[INFO] Saving to Database" STATIC_DB=StaticAnalyzerIPA(TITLE='Static Analysis',APPNAMEX=APP_NAME,SIZE=SIZE,MD5=MD5,SHA1=SHA1,SHA256=SHA256,INFOPLIST=INFO_PLIST,BINNAME=BIN_NAME,IDF=ID,VERSION=VER,SDK=SDK,PLTFM=PLTFM,MINX=MIN,BIN_ANAL=BIN_ANAL,LIBS=LIBS,FILES=FILES,SFILESX=SFILES,STRINGS=STRINGS) STATIC_DB.save() context = { 'title' : 'Static Analysis', 'name' : APP_NAME, 'size' : SIZE, 'md5': MD5, 'sha1' : SHA1, 'sha256' : SHA256, 'plist' : INFO_PLIST, 'bin_name' : BIN_NAME, 'id' : ID, 'ver' : VER, 'sdk' : SDK, 'pltfm' : PLTFM, 'min' : MIN, 'bin_anal' : BIN_ANAL, 'libs' : LIBS, 'files' : FILES, 'file_analysis' : SFILES, 'strings' : STRINGS, } template="ios_binary_analysis.html" return render(request,template,context) elif TYP=='ios': DB=StaticAnalyzerIOSZIP.objects.filter(MD5=MD5) if DB.exists() and RESCAN=='0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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, 'strings' : DB[0].STRINGS } else: print "[INFO] iOS Source Code Analysis Started" APP_FILE=MD5 + '.zip' #NEW FILENAME APP_PATH=APP_DIR+APP_FILE #APP PATH #ANALYSIS BEGINS - Already Unzipped print "[INFO] ZIP Already Extracted" SIZE=str(FileSize(APP_PATH)) + 'MB' #FILE SIZE SHA1, SHA256= HashGen(APP_PATH) #SHA1 & SHA256 HASHES FILES,SFILES=iOS_ListFiles(APP_DIR,MD5,False,'ios') HTML,CODEANAL,URLnFile,DOMAINS,EmailnFile,INFO_PLIST,BIN_NAME,ID,VER,SDK,PLTFM,MIN=iOS_Source_Analysis(APP_DIR,MD5) LIBS,BIN_ANAL='','' #Saving to DB print "\n[INFO] Connecting to DB" if RESCAN=='1': print "\n[INFO] Updating Database..." StaticAnalyzerIOSZIP.objects.filter(MD5=MD5).update(TITLE = 'Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, HTML=HTML, CODEANAL=CODEANAL, URLnFile=URLnFile, DOMAINS=DOMAINS, EmailnFile=EmailnFile) elif RESCAN=='0': print "\n[INFO] Saving to Database" STATIC_DB=StaticAnalyzerIOSZIP(TITLE = 'Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, HTML=HTML, CODEANAL=CODEANAL, URLnFile=URLnFile, DOMAINS=DOMAINS, EmailnFile=EmailnFile) STATIC_DB.save() context = { 'title' : 'Static Analysis', 'name' : APP_NAME, 'size' : SIZE, 'md5': MD5, 'sha1' : SHA1, 'sha256' : SHA256, 'plist' : INFO_PLIST, 'bin_name' : BIN_NAME, 'id' : ID, 'ver' : VER, 'sdk' : SDK, 'pltfm' : PLTFM, 'min' : MIN, 'bin_anal' : BIN_ANAL, 'libs' : LIBS, 'files' : FILES, 'file_analysis' : SFILES, 'api' : HTML, 'insecure' : CODEANAL, 'urls' : URLnFile, 'domains': DOMAINS, 'emails' : EmailnFile } template="ios_source_analysis.html" return render(request,template,context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except Exception as e: PrintException("[ERROR] Static Analyzer iOS") context = { 'title' : 'Error', 'exp' : e.message, 'doc' : e.__doc__ } template="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), 'insecure_connections': python_list(DB[0].INSECCON), } 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), 'insecure_connections': python_list(DB[0].INSECCON), } 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): 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 = { 'title': DB[0].TITLE, 'name': DB[0].APP_NAME, 'size': DB[0].SIZE, 'md5': DB[0].MD5, 'sha1': DB[0].SHA1, 'sha256': DB[0].SHA256, 'packagename': DB[0].PACKAGENAME, 'mainactivity': DB[0].MAINACTIVITY, 'targetsdk': DB[0].TARGET_SDK, 'maxsdk': DB[0].MAX_SDK, 'minsdk': DB[0].MIN_SDK, 'androvername': DB[0].ANDROVERNAME, 'androver': DB[0].ANDROVER, 'manifest': DB[0].MANIFEST_ANAL, 'permissions': DB[0].PERMISSIONS, 'files': python_list(DB[0].FILES), 'certz': DB[0].CERTZ, 'activities': python_list(DB[0].ACTIVITIES), 'receivers': python_list(DB[0].RECEIVERS), 'providers': python_list(DB[0].PROVIDERS), 'services': python_list(DB[0].SERVICES), 'libraries': python_list(DB[0].LIBRARIES), 'act_count': DB[0].CNT_ACT, 'prov_count': DB[0].CNT_PRO, 'serv_count': DB[0].CNT_SER, 'bro_count': DB[0].CNT_BRO, 'certinfo': DB[0].CERT_INFO, 'issued': DB[0].ISSUED, 'native': DB[0].NATIVE, 'dynamic': DB[0].DYNAMIC, 'reflection': DB[0].REFLECT, 'crypto': DB[0].CRYPTO, 'obfus': DB[0].OBFUS, 'api': DB[0].API, 'dang': DB[0].DANG, 'urls': DB[0].URLS, 'domains': python_dict(DB[0].DOMAINS), 'emails': DB[0].EMAILS, 'strings': python_list(DB[0].STRINGS), 'zipped': DB[0].ZIPPED, 'mani': DB[0].MANI } if TYP == 'APK': template = get_template("static_analysis_pdf.html") else: template = get_template("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': DB[0].STRINGS } template = get_template("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 } template = get_template("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': 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( "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, 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 APIAnalysis(PKG, LOCATION): print "\n[INFO] Dynamic API Analysis" dat = "" API_BASE64 = [] API_FILEIO = [] API_RELECT = [] API_SYSPROP = [] API_CNTRSLVR = [] API_CNTVAL = [] API_BINDER = [] API_CRYPTO = [] API_ACNTMNGER = [] API_DEVICEINFO = [] API_NET = [] API_DEXLOADER = [] API_CMD = [] API_SMS = [] try: with open(LOCATION, "r") as f: dat = f.readlines() ID = "Droidmon-apimonitor-" + PKG + ":" for line in dat: line = line.decode('utf8', 'ignore') if (ID) in line: # print "LINE: " + line param, value = line.split(ID, 1) # print "PARAM is :" + param # print "Value is :"+ value try: APIs = json.loads(value, strict=False) RET = '' CLS = '' MTD = '' ARGS = '' MTD = str(APIs["method"]) CLS = str(APIs["class"]) # print "Called Class: " + CLS # print "Called Method: " + MTD if APIs.get('return'): RET = str(APIs["return"]) # print "Return Data: " + RET else: # print "No Return Data" RET = "No Return Data" if APIs.get('args'): ARGS = str(APIs["args"]) # print "Passed Arguments" + ARGS else: # print "No Arguments Passed" ARGS = "No Arguments Passed" # XSS Safe D = "</br>METHOD: " + \ escape(MTD) + "</br>ARGUMENTS: " + escape(ARGS) + \ "</br>RETURN DATA: " + escape(RET) if re.findall("android.util.Base64", CLS): # Base64 Decode if ("decode" in MTD): args_list = python_list(ARGS) if isBase64(args_list[0]): D += '</br><span class="label label-info">Decoded String:</span> ' + \ escape(base64.b64decode(args_list[0])) API_BASE64.append(D) if re.findall('libcore.io|android.app.SharedPreferencesImpl$EditorImpl', CLS): API_FILEIO.append(D) if re.findall('java.lang.reflect', CLS): API_RELECT.append(D) if re.findall('android.content.ContentResolver|android.location.Location|android.media.AudioRecord|android.media.MediaRecorder|android.os.SystemProperties', CLS): API_SYSPROP.append(D) if re.findall('android.app.Activity|android.app.ContextImpl|android.app.ActivityThread', CLS): API_BINDER.append(D) if re.findall('javax.crypto.spec.SecretKeySpec|javax.crypto.Cipher|javax.crypto.Mac', CLS): API_CRYPTO.append(D) if re.findall('android.accounts.AccountManager|android.app.ApplicationPackageManager|android.app.NotificationManager|android.net.ConnectivityManager|android.content.BroadcastReceiver', CLS): API_ACNTMNGER.append(D) if re.findall('android.telephony.TelephonyManager|android.net.wifi.WifiInfo|android.os.Debug', CLS): API_DEVICEINFO.append(D) if re.findall('dalvik.system.BaseDexClassLoader|dalvik.system.DexFile|dalvik.system.DexClassLoader|dalvik.system.PathClassLoader', CLS): API_DEXLOADER.append(D) if re.findall('java.lang.Runtime|java.lang.ProcessBuilder|java.io.FileOutputStream|java.io.FileInputStream|android.os.Process', CLS): API_CMD.append(D) if re.findall('android.content.ContentValues', CLS): API_CNTVAL.append(D) if re.findall('android.telephony.SmsManager', CLS): API_SMS.append(D) if re.findall('java.net.URL|org.apache.http.impl.client.AbstractHttpClient', CLS): API_NET.append(D) except: PrintException("[ERROR] Parsing JSON Failed for: " + value) except: PrintException("[ERROR] Dynamic API Analysis") pass return list(set(API_NET)), list(set(API_BASE64)), list(set(API_FILEIO)), list(set(API_BINDER)), list(set(API_CRYPTO)), list(set(API_DEVICEINFO)), list(set(API_CNTVAL)), list(set(API_SMS)), list(set(API_SYSPROP)), list(set(API_DEXLOADER)), list(set(API_RELECT)), list(set(API_ACNTMNGER)), list(set(API_CMD))
def StaticAnalyzer_iOS(request): try: # Input validation print "[INFO] iOS Static Analysis Started" TYP = request.GET['type'] RESCAN = str(request.GET.get('rescan', 0)) m = re.match('^[0-9a-f]{32}$', request.GET['checksum']) if ((m) and (request.GET['name'].lower().endswith('.ipa') or request.GET['name'].lower().endswith('.zip')) and (TYP in ['ipa', 'ios'])): DIR = settings.BASE_DIR # BASE DIR APP_NAME = request.GET['name'] # APP ORGINAL NAME MD5 = request.GET['checksum'] # MD5 APP_DIR = os.path.join(settings.UPLD_DIR, MD5 + '/') # APP DIRECTORY TOOLS_DIR = os.path.join(DIR, 'StaticAnalyzer/tools/mac/') # TOOLS DIR if TYP == 'ipa': # DB DB = StaticAnalyzerIPA.objects.filter(MD5=MD5) if DB.exists() and RESCAN == '0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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': DB[0].STRINGS, } else: print "[INFO] iOS Binary (IPA) Analysis Started" APP_FILE = MD5 + '.ipa' # NEW FILENAME APP_PATH = APP_DIR + APP_FILE # APP PATH BIN_DIR = os.path.join(APP_DIR, "Payload/") # ANALYSIS BEGINS SIZE = str(FileSize(APP_PATH)) + 'MB' # FILE SIZE SHA1, SHA256 = HashGen(APP_PATH) # SHA1 & SHA256 HASHES print "[INFO] Extracting IPA" Unzip(APP_PATH, APP_DIR) # EXTRACT IPA # Get Files, normalize + to x, and convert binary plist -> # xml FILES, SFILES = iOS_ListFiles(BIN_DIR, MD5, True, 'ipa') INFO_PLIST, BIN_NAME, ID, VER, SDK, PLTFM, MIN, LIBS, BIN_ANAL, STRINGS = BinaryAnalysis( BIN_DIR, TOOLS_DIR, APP_DIR) # Saving to DB print "\n[INFO] Connecting to DB" if RESCAN == '1': print "\n[INFO] Updating Database..." StaticAnalyzerIPA.objects.filter(MD5=MD5).update( TITLE='Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, STRINGS=STRINGS) elif RESCAN == '0': print "\n[INFO] Saving to Database" STATIC_DB = StaticAnalyzerIPA(TITLE='Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, STRINGS=STRINGS) STATIC_DB.save() context = { 'title': 'Static Analysis', 'name': APP_NAME, 'size': SIZE, 'md5': MD5, 'sha1': SHA1, 'sha256': SHA256, 'plist': INFO_PLIST, 'bin_name': BIN_NAME, 'id': ID, 'ver': VER, 'sdk': SDK, 'pltfm': PLTFM, 'min': MIN, 'bin_anal': BIN_ANAL, 'libs': LIBS, 'files': FILES, 'file_analysis': SFILES, 'strings': STRINGS, } template = "static_analysis/ios_binary_analysis.html" return render(request, template, context) elif TYP == 'ios': DB = StaticAnalyzerIOSZIP.objects.filter(MD5=MD5) if DB.exists() and RESCAN == '0': print "\n[INFO] Analysis is already Done. Fetching data from the DB..." 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, 'strings': DB[0].STRINGS } else: print "[INFO] iOS Source Code Analysis Started" APP_FILE = MD5 + '.zip' # NEW FILENAME APP_PATH = APP_DIR + APP_FILE # APP PATH # ANALYSIS BEGINS - Already Unzipped print "[INFO] ZIP Already Extracted" SIZE = str(FileSize(APP_PATH)) + 'MB' # FILE SIZE SHA1, SHA256 = HashGen(APP_PATH) # SHA1 & SHA256 HASHES FILES, SFILES = iOS_ListFiles(APP_DIR, MD5, False, 'ios') HTML, CODEANAL, URLnFile, DOMAINS, EmailnFile, INFO_PLIST, BIN_NAME, ID, VER, SDK, PLTFM, MIN = iOS_Source_Analysis( APP_DIR, MD5) LIBS, BIN_ANAL = '', '' # Saving to DB print "\n[INFO] Connecting to DB" if RESCAN == '1': print "\n[INFO] Updating Database..." StaticAnalyzerIOSZIP.objects.filter(MD5=MD5).update( TITLE='Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, HTML=HTML, CODEANAL=CODEANAL, URLnFile=URLnFile, DOMAINS=DOMAINS, EmailnFile=EmailnFile) elif RESCAN == '0': print "\n[INFO] Saving to Database" STATIC_DB = StaticAnalyzerIOSZIP( TITLE='Static Analysis', APPNAMEX=APP_NAME, SIZE=SIZE, MD5=MD5, SHA1=SHA1, SHA256=SHA256, INFOPLIST=INFO_PLIST, BINNAME=BIN_NAME, IDF=ID, VERSION=VER, SDK=SDK, PLTFM=PLTFM, MINX=MIN, BIN_ANAL=BIN_ANAL, LIBS=LIBS, FILES=FILES, SFILESX=SFILES, HTML=HTML, CODEANAL=CODEANAL, URLnFile=URLnFile, DOMAINS=DOMAINS, EmailnFile=EmailnFile) STATIC_DB.save() context = { 'title': 'Static Analysis', 'name': APP_NAME, 'size': SIZE, 'md5': MD5, 'sha1': SHA1, 'sha256': SHA256, 'plist': INFO_PLIST, 'bin_name': BIN_NAME, 'id': ID, 'ver': VER, 'sdk': SDK, 'pltfm': PLTFM, 'min': MIN, 'bin_anal': BIN_ANAL, 'libs': LIBS, 'files': FILES, 'file_analysis': SFILES, 'api': HTML, 'insecure': CODEANAL, 'urls': URLnFile, 'domains': DOMAINS, 'emails': EmailnFile } template = "static_analysis/ios_source_analysis.html" return render(request, template, context) else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except Exception as exp: PrintException("[ERROR] Static Analyzer iOS") context = {'title': 'Error', 'exp': exp.message, 'doc': exp.__doc__} template = "general/error.html" return render(request, template, context)