Пример #1
0
def get_domains(urls):
    """Get Domains"""
    try:
        domains = list()
        for url in urls:
            parsed_uri = urlparse(url)
            domain = '{uri.netloc}'.format(uri=parsed_uri)
            if ((domain not in domains) and (len(domain) > 2)
                    and ("." in domain)
                    and (domain.endswith(".") is False
                         and re.search('[a-zA-Z0-9]', domain))):
                domains.append(domain)
        return domains
    except:
        PrintException("[ERROR] Extracting Domain form URL")
        pass
def capfuzz_start(request):
    """Start CapFuzz UI"""
    print("[INFO] Starting CapFuzz Web UI")
    try:
        stop_capfuzz(settings.PORT)
        start_fuzz_ui(settings.PORT)
        time.sleep(3)
        print("[INFO] CapFuzz UI Started")
        if request.GET['project']:
            project = request.GET['project']
        else:
            project = ""
        return HttpResponseRedirect('http://localhost:' + str(settings.PORT) + "/dashboard/" + project)
    except:
        PrintException("[ERROR] Starting CapFuzz Web UI")
        return HttpResponseRedirect('/error/')
def delete_avd(avd_path, avd_name):
    """Delete AVD"""
    print "\n[INFO] Deleting emulator files"
    try:
        config_file = os.path.join(avd_path, avd_name + '.ini')
        if os.path.exists(config_file):
            os.remove(config_file)
        '''
        # todo: Sometimes there is an error here because of the locks that avd
        # does - check this out
        '''
        avd_folder = os.path.join(avd_path, avd_name + '.avd')
        if os.path.isdir(avd_folder):
            shutil.rmtree(avd_folder)
    except:
        PrintException("[ERROR] Deleting emulator files")
def get_icon(apk_path, res_dir):
    """Returns a dict with isHidden boolean and a relative path
        path is a full path (not relative to resource folder) """
    try:
        logger.info("Fetching icon path")
        a = apk.APK(apk_path)
        icon_resolution = 0xFFFE - 1
        icon_name = a.get_app_icon(max_dpi=icon_resolution)
        if icon_name:
            return {
                'path': os.path.join(os.path.dirname(apk_path), icon_name),
                'hidden': False
            }
        return {'path': guess_icon_path(res_dir), 'hidden': True}
    except:
        PrintException("Fetching icon function")
Пример #5
0
def adb_command(cmd_list, shell=False, silent=False):
    emulator = get_identifier()
    adb = getADB()

    args = [adb, "-s", emulator]
    if shell:
        args += ['shell']
    args += cmd_list

    try:
        result = subprocess.check_output(args)
        return result
    except:
        if not silent:
            PrintException("[ERROR] adb_command")
        return None
Пример #6
0
def strings_jar(app_file, app_dir):
    """Extract the strings from an app."""
    try:
        print("[INFO] Extracting Strings from APK")
        dat = []
        apk_file = os.path.join(app_dir, app_file)
        and_a = apk.APK(apk_file)
        rsrc = and_a.get_android_resources()
        pkg = rsrc.get_packages_names()[0]
        rsrc.get_strings_resources()
        for i in rsrc.values[pkg].keys():
            for duo in rsrc.values[pkg][i]['string']:
                dat.append('"' + duo[0] + '" : "' + duo[1] + '"')
        return dat
    except:
        PrintException("[ERROR] Extracting Strings from APK")
Пример #7
0
def run(request):
    """Show the java code."""
    try:
        match = re.match('^[0-9a-f]{32}$', request.GET['md5'])
        typ = request.GET['type']
        if match:
            md5 = request.GET['md5']
            if typ == 'eclipse':
                src = os.path.join(settings.UPLD_DIR, md5 + '/src/')
            elif typ == 'studio':
                src = os.path.join(settings.UPLD_DIR,
                                   md5 + '/app/src/main/java/')
            elif typ == 'apk':
                src = os.path.join(settings.UPLD_DIR, md5 + '/java_source/')
            else:
                return HttpResponseRedirect('/error/')
            html = ''
            # pylint: disable=unused-variable
            # Needed by os.walk
            for dir_name, sub_dir, files in os.walk(src):
                for jfile in files:
                    if jfile.endswith(".java"):
                        file_path = os.path.join(src, dir_name, jfile)
                        if "+" in jfile:
                            fp2 = os.path.join(src, dir_name,
                                               jfile.replace("+", "x"))
                            shutil.move(file_path, fp2)
                            file_path = fp2
                        fileparam = file_path.replace(src, '')
                        if any(cls in fileparam
                               for cls in settings.SKIP_CLASSES) is False:
                            html += ("<tr><td><a href='../ViewSource/?file=" +
                                     escape(fileparam) + "&md5=" + md5 +
                                     "&type=" + typ + "'>" +
                                     escape(fileparam) + "</a></td></tr>")
        context = {
            'title': 'Java Source',
            'files': html,
            'md5': md5,
            'type': typ,
        }

        template = "static_analysis/java.html"
        return render(request, template, context)
    except:
        PrintException("[ERROR] Getting Java Files")
        return HttpResponseRedirect('/error/')
Пример #8
0
def run(request):
    """View the source of a file."""
    try:
        fil = ''
        match = re.match('^[0-9a-f]{32}$', request.GET['md5'])
        if match and (
                request.GET['file'].endswith('.java') or
                request.GET['file'].endswith('.smali')
        ):
            fil = request.GET['file']
            md5 = request.GET['md5']
            if ("../" in fil) or ("%2e%2e" in fil) or (".." in fil) or ("%252e" in fil):
                return HttpResponseRedirect('/error/')
            else:
                if fil.endswith('.java'):
                    typ = request.GET['type']
                    if typ == 'eclipse':
                        src = os.path.join(settings.UPLD_DIR, md5+'/src/')
                    elif typ == 'studio':
                        src = os.path.join(settings.UPLD_DIR, md5+'/app/src/main/java/')
                    elif typ == 'apk':
                        src = os.path.join(settings.UPLD_DIR, md5+'/java_source/')
                    else:
                        return HttpResponseRedirect('/error/')
                elif fil.endswith('.smali'):
                    src = os.path.join(settings.UPLD_DIR, md5+'/smali_source/')
                sfile = os.path.join(src, fil)
                dat = ''
                with io.open(
                    sfile,
                    mode='r',
                    encoding="utf8",
                    errors="ignore"
                ) as file_pointer:
                    dat = file_pointer.read()
        else:
            return HttpResponseRedirect('/error/')
        context = {
            'title': escape(ntpath.basename(fil)),
            'file': escape(ntpath.basename(fil)),
            'dat': dat
        }
        template = "static_analysis/view_source.html"
        return render(request, template, context)
    except:
        PrintException("[ERROR] Viewing Source")
        return HttpResponseRedirect('/error/')
Пример #9
0
def get_env(request):
    """Get Dynamic Analysis Environment for Android"""
    print("\n[INFO] Setting up Dynamic Analysis Environment")
    try:
        if request.method == 'POST':
            data = {}
            md5_hash = request.POST['md5']
            package = request.POST['pkg']
            launcher = request.POST['lng']
            if re.findall(r";|\$\(|\|\||&&", package) or re.findall(r";|\$\(|\|\||&&", launcher):
                print("[ATTACK] Possible RCE")
                return HttpResponseRedirect('/error/')
            if re.match('^[0-9a-f]{32}$', md5_hash):
                base_dir = settings.BASE_DIR
                app_dir = os.path.join(
                    settings.UPLD_DIR, md5_hash + '/')  # APP DIRECTORY
                app_file = md5_hash + '.apk'  # NEW FILENAME
                app_path = app_dir + app_file  # APP PATH
                adb = getADB()
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    proxy_ip = '127.0.0.1'
                else:
                    proxy_ip = settings.PROXY_IP  # Proxy IP
                start_proxy(settings.PORT, package)
                # vm needs the connect function
                try:
                    if not settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                        connect()
                except Exception as exp:
                    data = {'ready': 'no',
                            'msg': 'Cannot Connect to the VM/Device.',
                            'error': str(exp)}
                    return HttpResponse(json.dumps(data), content_type='application/json')
                # Change True to support non-activity components
                install_and_run(app_path, package, launcher, True)
                screen_width, screen_width = get_res()
                data = {'ready': 'yes',
                        'screen_witdth': screen_width,
                        'screen_height': screen_width, }
                return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Setting up Dynamic Analysis Environment")
        return HttpResponseRedirect('/error/')
Пример #10
0
def cert_info(app_dir, tools_dir):
    """Return certificate information."""
    try:
        print("[INFO] Reading Code Signing Certificate")
        cert = os.path.join(app_dir, 'META-INF/')
        cp_path = tools_dir + 'CertPrint.jar'
        files = [f for f in os.listdir(
            cert) if os.path.isfile(os.path.join(cert, f))]
        certfile = None
        dat = ''
        manidat = ''
        manifestfile = None
        if "CERT.RSA" in files:
            certfile = os.path.join(cert, "CERT.RSA")
        else:
            for file_name in files:
                if file_name.lower().endswith(".rsa"):
                    certfile = os.path.join(cert, file_name)
                elif file_name.lower().endswith(".dsa"):
                    certfile = os.path.join(cert, file_name)
        if certfile:
            args = [settings.JAVA_PATH + 'java', '-jar', cp_path, certfile]
            issued = 'good'
            dat = subprocess.check_output(args)
            unicode_output = str(dat, encoding="utf-8", errors="replace")
            dat = escape(unicode_output).replace('\n', '</br>')
        else:
            dat = 'No Code Signing Certificate Found!'
            issued = 'missing'
        if re.findall(r"Issuer: CN=Android Debug|Subject: CN=Android Debug", dat):
            issued = 'bad'
        if re.findall(r"\[SHA1withRSA\]", dat):
            issued = 'bad hash'
        if "MANIFEST.MF" in files:
            manifestfile = os.path.join(cert, "MANIFEST.MF")
        if manifestfile:
            with open(manifestfile,'r') as manifile:
                manidat = manifile.read()
        sha256Digest = bool(re.findall(r"SHA-256-Digest", manidat))
        cert_dic = {
            'cert_info': dat,
            'issued': issued,
            'sha256Digest': sha256Digest
        }
        return cert_dic
    except:
        PrintException("[ERROR] Reading Code Signing Certificate")
def view(request):
    """View File"""
    logger.info("Viewing File")
    try:
        typ = ''
        fil = ''
        rtyp = ''
        dat = ''
        if re.match('^[0-9a-f]{32}$', request.GET['md5']):
            fil = request.GET['file']
            md5_hash = request.GET['md5']
            typ = request.GET['type']
            src = os.path.join(settings.UPLD_DIR,
                               md5_hash + '/DYNAMIC_DeviceData/')
            sfile = os.path.join(src, fil)
            # Prevent Directory Traversal Attacks
            if ("../" in fil) or ("%2e%2e"
                                  in fil) or (".." in fil) or ("%252e" in fil):
                return print_n_send_error_response(
                    request, "Path Traversal Attack Detected")
            else:
                with io.open(sfile, mode='r', encoding="utf8",
                             errors="ignore") as flip:
                    dat = flip.read()
                if (fil.endswith('.xml')) and (typ == 'xml'):
                    rtyp = 'xml'
                elif typ == 'db':
                    dat = handle_sqlite(sfile)
                    rtyp = 'asciidoc'
                elif typ == 'others':
                    rtyp = 'asciidoc'
                else:
                    return print_n_send_error_response(
                        request, "File Type not supported")
                context = {
                    'title': escape(ntpath.basename(fil)),
                    'file': escape(ntpath.basename(fil)),
                    'dat': dat,
                    'type': rtyp,
                }
                template = "general/view.html"
                return render(request, template, context)
        else:
            return print_n_send_error_response(request, "Invalid Scan Hash")
    except:
        PrintException("Viewing File")
        return print_n_send_error_response(request, "ERROR Viewing File")
Пример #12
0
def FinalTest(request):
    #Closing Services in VM/Device
    global tcp_server_mode
    print "\n[INFO] Collecting Data and Cleaning Up"
    try:
        if request.method == 'POST':
            data = {}
            MD5=request.POST['md5']
            PACKAGE=request.POST['pkg']
            if re.findall(";|\$\(|\|\||&&",PACKAGE):
                print "[ATTACK] Possible RCE"
                return HttpResponseRedirect('/error/') 
            m=re.match('^[0-9a-f]{32}$',MD5)
            if m:
                #Stop ScreenCast Client if it is running
                tcp_server_mode = "off"
                DIR=settings.BASE_DIR
                APKDIR=os.path.join(settings.UPLD_DIR, MD5+'/')
                TOOLSDIR=os.path.join(DIR, 'DynamicAnalyzer/tools/')  #TOOLS DIR
                adb=getADB(TOOLSDIR)
                #Change to check output of subprocess when analysis is done
                #Can't RCE
                os.system(adb+' -s '+getIdentifier()+' logcat -d dalvikvm:W ActivityManager:I > "'+APKDIR + 'logcat.txt"')
                print "\n[INFO] Downloading Logcat logs"
                #os.system(adb+' -s '+getIdentifier()+' logcat -d Xposed:I *:S > "'+APKDIR + 'x_logcat.txt"')
                subprocess.call([adb, "-s", getIdentifier(), "pull", "/data/data/de.robv.android.xposed.installer/log/error.log", APKDIR + "x_logcat.txt"])

                print "\n[INFO] Downloading Droidmon API Monitor Logcat logs"
                #Can't RCE
                os.system(adb+' -s '+getIdentifier()+' shell dumpsys > "'+APKDIR + 'dump.txt"');
                print "\n[INFO] Downloading Dumpsys logs"

                subprocess.call([adb, "-s", getIdentifier(), "shell", "am", "force-stop", PACKAGE])
                print "\n[INFO] Stopping Application"

                subprocess.call([adb, "-s", getIdentifier(), "shell", "am", "force-stop", "opensecurity.screencast"])
                print "\n[INFO] Stopping ScreenCast Service"

                data = {'final': 'yes'}
                return HttpResponse(json.dumps(data), content_type='application/json') 
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Clean Up")
        return HttpResponseRedirect('/error/')
Пример #13
0
def iOS_ListFiles(SRC, MD5, BIN, MODE):
    try:
        print "[INFO] Get Files, BIN Plist -> XML, and Normalize"
        # Multi function, Get Files, BIN Plist -> XML, normalize + to x
        filez = []
        certz = ''
        sfiles = ''
        db = ''
        plist = ''
        certz = ''
        for dirName, subDir, files in os.walk(SRC):
            for jfile in files:
                if not jfile.endswith(".DS_Store"):
                    file_path = os.path.join(SRC, dirName, jfile)
                    if "+" in jfile:
                        plus2x = os.path.join(SRC, dirName,
                                              jfile.replace("+", "x"))
                        shutil.move(file_path, plus2x)
                        file_path = plus2x
                    fileparam = file_path.replace(SRC, '')
                    filez.append(fileparam)
                    ext = jfile.split('.')[-1]
                    if re.search("cer|pem|cert|crt|pub|key|pfx|p12", ext):
                        certz += escape(file_path.replace(SRC, '')) + "</br>"
                    if re.search("db|sqlitedb|sqlite", ext):
                        db += "<a href='../ViewFile/?file=" + \
                            escape(fileparam) + "&type=db&mode=" + MODE + "&md5=" + \
                            MD5 + "''> " + escape(fileparam) + " </a></br>"
                    if jfile.endswith(".plist"):
                        if BIN:
                            readBinXML(file_path)
                        plist += "<a href='../ViewFile/?file=" + \
                            escape(fileparam) + "&type=xml&mode=" + MODE + "&md5=" + \
                            MD5 + "''> " + escape(fileparam) + " </a></br>"
        if len(db) > 1:
            db = "<tr><td>SQLite Files</td><td>" + db + "</td></tr>"
            sfiles += db
        if len(plist) > 1:
            plist = "<tr><td>Plist Files</td><td>" + plist + "</td></tr>"
            sfiles += plist
        if len(certz) > 1:
            certz = "<tr><td>Certificate/Key Files Hardcoded inside the App.</td><td>" + \
                certz + "</td><tr>"
            sfiles += certz
        return filez, sfiles
    except:
        PrintException("[ERROR] iOS List Files")
def install_and_run(apk_path, package, launcher, is_activity):
    """Install APK and Run it"""
    logger.info("Starting App for Dynamic Analysis")
    try:
        adb = getADB()
        logger.info("Installing APK")
        adb_command(["install", "-r", apk_path])
        if is_activity:
            run_app = package + "/" + launcher
            logger.info("Launching APK Main Activity")
            adb_command(["am", "start", "-n", run_app], True)
        else:
            logger.info("App Doesn't have a Main Activity")
            # Handle Service or Give Choice to Select in Future.
        logger.info("Testing Environment is Ready!")
    except:
        PrintException("Starting App for Dynamic Analysis")
def View(request):
    print "\n[INFO] Viewing File"
    try:
        typ = ''
        fil = ''
        rtyp = ''
        dat = ''
        m = re.match('^[0-9a-f]{32}$', request.GET['md5'])
        if m:
            fil = request.GET['file']
            MD5 = request.GET['md5']
            typ = request.GET['type']
            SRC = os.path.join(settings.UPLD_DIR, MD5 + '/DYNAMIC_DeviceData/')
            sfile = os.path.join(SRC, fil)
            #Prevent Directory Traversal Attacks
            if (("../" in fil) or ("%2e%2e" in fil) or (".." in fil)
                    or ("%252e" in fil)):
                return HttpResponseRedirect('/error/')
            else:
                with io.open(sfile, mode='r', encoding="utf8",
                             errors="ignore") as f:
                    dat = f.read()
                if ((fil.endswith('.xml')) and (typ == 'xml')):
                    rtyp = 'xml'
                elif typ == 'db':
                    dat = HandleSqlite(sfile)
                    dat = dat.decode("windows-1252").encode("utf8")
                    rtyp = 'plain'
                elif typ == 'others':
                    rtyp = 'plain'
                else:
                    return HttpResponseRedirect('/error/')
                context = {
                    'title': escape(ntpath.basename(fil)),
                    'file': escape(ntpath.basename(fil)),
                    'dat': dat,
                    'type': rtyp,
                }
                template = "view.html"
                return render(request, template, context)

        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Viewing File")
        return HttpResponseRedirect('/error/')
def RefreshVM(uuid, snapshot_uuid, vbox_exe):
    print "\n[INFO] Refreshing MobSF VM"
    try:
        #Close VM
        args = [vbox_exe, 'controlvm', uuid, 'poweroff']
        subprocess.call(args)
        print "\n[INFO] VM Closed"
        #Restore Snapshot
        args = [vbox_exe, 'snapshot', uuid, 'restore', snapshot_uuid]
        subprocess.call(args)
        print "\n[INFO] VM Restore Snapshot"
        #Start Fresh VM
        args = [vbox_exe, 'startvm', uuid]
        subprocess.call(args)
        print "\n[INFO] VM Starting"
    except:
        PrintException("[ERROR] Refreshing MobSF VM")
Пример #17
0
def strings_on_ipa(bin_path):
    """Extract Strings from IPA"""
    try:
        print "[INFO] Running strings against the Binary"
        unique_str = []
        list_of_strings = list(strings(bin_path))
        unique_str = list(set(list_of_strings))  # Make unique
        unique_str = [
            ipa_str if isinstance(ipa_str, unicode) else unicode(
                ipa_str, encoding="utf-8", errors="replace")
            for ipa_str in unique_str
        ]
        unique_str = [escape(ip_str)
                      for ip_str in unique_str]  # Escape evil strings
        return unique_str
    except:
        PrintException("[ERROR] - Running strings against the Binary")
Пример #18
0
def check_config():
    try:
        for path in [settings.AVD_EMULATOR, settings.ADB_BINARY]:
            if not path:
                print(
                    "\n[ERROR] ADB binary not configured, please refer to the official documentation"
                )
                return False
        if settings.ANDROID_DYNAMIC_ANALYZER != 'MobSF_AVD':
            print(
                "\n[ERROR] Wrong configuration - ANDROID_DYNAMIC_ANALYZER, please refer to the official documentation"
            )
            return False
        return True
    except:
        PrintException("[ERROR] check_config")
        return False
def ConnectInstallRun(TOOLSDIR, ADB_CON_ID, APKPATH, PACKAGE, LAUNCH, isACT):
    print "\n[INFO] Starting App for Dynamic Analysis"
    try:
        adb = getADB(TOOLSDIR)
        subprocess.call([adb, "kill-server"])
        subprocess.call([adb, "start-server"])
        print "\n[INFO] ADB Started"
        Wait(5)
        print "\n[INFO] Connecting to VM/Device"
        subprocess.call([adb, "connect", ADB_CON_ID])
        subprocess.call([adb, "wait-for-device"])
        print "\n[INFO] Mounting"
        if settings.REAL_DEVICE:
            subprocess.call([
                adb, "-s",
                getIdentifier(), "shell", "su", "-c",
                "mount -o rw,remount,rw /system"
            ])
        else:
            subprocess.call([
                adb, "-s",
                getIdentifier(), "shell", "su", "-c",
                "mount -o rw,remount,rw /system"
            ])
            #This may not work for VMs other than the default MobSF VM
            subprocess.call([
                adb, "-s",
                getIdentifier(), "shell", "mount", "-o", "rw,remount", "-t",
                "rfs", "/dev/block/sda6", "/system"
            ])
        print "\n[INFO] Installing APK"
        subprocess.call([adb, "-s", getIdentifier(), "install", "-r", APKPATH])
        if isACT:
            runApp = PACKAGE + "/" + LAUNCH
            print "\n[INFO] Launching APK Main Activity"
            subprocess.call([
                adb, "-s",
                getIdentifier(), "shell", "am", "start", "-n", runApp
            ])
        else:
            print "\n[INFO] App Doesn't have a Main Activity"
            #Handle Service or Give Choice to Select in Future.
            pass
        print "[INFO] Testing Environment is Ready!"
    except:
        PrintException("[ERROR]  Starting App for Dynamic Analysis")
def screencast_service():
    """Start or Stop ScreenCast Services"""
    global TCP_SERVER_MODE
    print("\n[INFO] ScreenCast Service Status: " + TCP_SERVER_MODE)
    try:
        screen_dir = settings.SCREEN_DIR
        if not os.path.exists(screen_dir):
            os.makedirs(screen_dir)

        screen_socket = socket.socket()
        if TCP_SERVER_MODE == "on":
            screen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                addr = ('127.0.0.1', settings.SCREEN_PORT)
            else:
                addr = (settings.SCREEN_IP, settings.SCREEN_PORT)
            screen_socket.bind(addr)
            screen_socket.listen(10)
            while TCP_SERVER_MODE == "on":
                screens, address = screen_socket.accept()
                print("Got Connection from: ", address[0])
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
                    ip_address = settings.DEVICE_IP
                else:
                    ip_address = settings.VM_IP
                if address[0] in [ip_address, '127.0.0.1']:
                    '''
                    Very Basic Check to ensure that only MobSF VM/Device/Emulator
                    is allowed to connect to MobSF ScreenCast Service.
                    '''
                    with open(screen_dir + 'screen.png', 'wb') as flip:
                        while True:
                            data = screens.recv(1024)
                            if not data:
                                break
                            flip.write(data)
                else:
                    print(
                        "\n[ATTACK] An unknown client :" + address[0] +
                        " is trying " +
                        "to make a connection with MobSF ScreenCast Service!")
        elif TCP_SERVER_MODE == "off":
            screen_socket.close()
    except:
        screen_socket.close()
        PrintException("[ERROR] ScreenCast Server")
def download(md5_hash, download_dir, apk_dir, package):
    """Generating Downloads"""
    logger.info("Generating Downloads")
    try:

        capfuzz_home = os.path.join(str(Path.home()), ".capfuzz")
        logcat = os.path.join(apk_dir, 'logcat.txt')
        xlogcat = os.path.join(apk_dir, 'x_logcat.txt')
        dumpsys = os.path.join(apk_dir, 'dump.txt')
        sshot = os.path.join(apk_dir, 'screenshots-apk/')
        web = os.path.join(capfuzz_home, 'flows', package + ".flows.txt")
        star = os.path.join(apk_dir, package + '.tar')

        dlogcat = os.path.join(download_dir, md5_hash + '-logcat.txt')
        dxlogcat = os.path.join(download_dir, md5_hash + '-x_logcat.txt')
        ddumpsys = os.path.join(download_dir, md5_hash + '-dump.txt')
        dsshot = os.path.join(download_dir, md5_hash + '-screenshots-apk/')
        dweb = os.path.join(download_dir, md5_hash + '-WebTraffic.txt')
        dstar = os.path.join(download_dir, md5_hash + '-AppData.tar')

        # Delete existing data
        dellist = [dlogcat, dxlogcat, ddumpsys, dsshot, dweb, dstar]
        for item in dellist:
            if os.path.isdir(item):
                shutil.rmtree(item)
            elif os.path.isfile(item):
                os.remove(item)
        # Copy new data
        shutil.copyfile(logcat, dlogcat)
        shutil.copyfile(xlogcat, dxlogcat)
        shutil.copyfile(dumpsys, ddumpsys)
        try:
            shutil.copytree(sshot, dsshot)
        except:
            pass
        try:
            shutil.copyfile(web, dweb)
        except:
            pass
        try:
            shutil.copyfile(star, dstar)
        except:
            pass
    except:
        PrintException("[ERROR] Generating Downloads")
Пример #22
0
def ios_list_files(src, md5_hash, binary_form, mode):
    """List iOS files"""
    try:
        print("[INFO] Get Files, BIN Plist -> XML, and Normalize")
        # Multi function, Get Files, BIN Plist -> XML, normalize + to x
        filez = []
        certz = []
        sfiles = []
        database = []
        plist = []
        for dirname, _, files in os.walk(src):
            for jfile in files:
                if not jfile.endswith(".DS_Store"):
                    file_path = os.path.join(src, dirname, jfile)
                    if "+" in jfile:
                        plus2x = os.path.join(
                            src, dirname, jfile.replace("+", "x"))
                        shutil.move(file_path, plus2x)
                        file_path = plus2x
                    fileparam = file_path.replace(src, '')
                    filez.append(fileparam)
                    ext = jfile.split('.')[-1]
                    if re.search("cer|pem|cert|crt|pub|key|pfx|p12", ext):
                        certz.append(escape(file_path.replace(src, '')))
                    if re.search("db|sqlitedb|sqlite", ext):
                        database.append("<a href='../ViewFile/?file=" + \
                            escape(fileparam) + "&type=" + mode + "&md5=" + \
                            md5_hash + "''> " + \
                            escape(fileparam) + " </a>")
                    if jfile.endswith(".plist"):
                        if binary_form:
                            convert_bin_xml(file_path)
                        plist.append("<a href='../ViewFile/?file=" + \
                            escape(fileparam) + "&type=" + mode + "&md5=" + \
                            md5_hash + "''> " + \
                            escape(fileparam) + " </a>")
        if len(database) > 0:
            sfiles.append({ "issue": "SQLite Files", "files": database })
        if len(plist) > 0:
            sfiles.append({ "issue": "Plist Files", "files": plist })
        if len(certz) > 0:
            sfiles.append({ "issue": "Certificate/Key Files Hardcoded inside the App.", "files": certz })
        return filez, sfiles
    except:
        PrintException("[ERROR] iOS List Files")
def _parse_xml(app_dir):
    """Parse the AppxManifest file to get basic informations."""
    print "[INFO] Starting Binary Analysis - XML"
    xml_file = os.path.join(app_dir, "AppxManifest.xml")
    xml_dic = {
        'version': '',
        'arch': '',
        'app_name': '',
        'pub_name': '',
        'compiler_version': '',
        'visual_studio_version': '',
        'visual_studio_edition': '',
        'target_os': '',
        'appx_dll_version': '',
        'proj_guid': '',
        'opti_tool': '',
        'target_run': ''
    }

    try:
        print "[INFO] Reading AppxManifest"
        config = etree.XMLParser(  # pylint: disable-msg=E1101
            remove_blank_text=True,
            resolve_entities=False)
        xml = etree.XML(open(xml_file).read(),
                        config)  # pylint: disable-msg=E1101
        for child in xml.getchildren():
            # } to prevent conflict with PhoneIdentity..
            if isinstance(child.tag, str) and child.tag.endswith("}Identity"):
                xml_dic['version'] = child.get("Version")
                xml_dic['arch'] = child.get("ProcessorArchitecture")
            elif isinstance(child.tag,
                            str) and child.tag.endswith("Properties"):
                for sub_child in child.getchildren():
                    if sub_child.tag.endswith("}DisplayName"):
                        # TODO(Needed? Compare to existing app_name)
                        xml_dic['app_name'] = sub_child.text
                    elif sub_child.tag.endswith("}PublisherDisplayName"):
                        xml_dic['pub_name'] = sub_child.text
            elif isinstance(child.tag,
                            str) and child.tag.endswith("}Metadata"):
                xml_dic = __parse_xml_metadata(xml_dic, child)
    except:
        PrintException("[ERROR] - Reading from AppxManifest.xml")
    return xml_dic
def GetEnv(request):

    print "\n[INFO] Setting up Dynamic Analysis Environment"
    try:
        if request.method == 'POST':
            data = {}
            MD5 = request.POST['md5']
            PKG = request.POST['pkg']
            LNCH = request.POST['lng']
            if re.findall(";|\$\(|\|\||&&", PKG) or re.findall(
                    ";|\$\(|\|\||&&", LNCH):
                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
                APP_FILE = MD5 + '.apk'  #NEW FILENAME
                APP_PATH = APP_DIR + APP_FILE  #APP PATH
                TOOLS_DIR = os.path.join(DIR,
                                         'DynamicAnalyzer/tools/')  #TOOLS DIR
                DWD_DIR = settings.DWD_DIR
                ADB_CON_ID = getIdentifier()
                PROXY_IP = settings.PROXY_IP  #Proxy IP
                PORT = str(settings.PORT)  #Proxy Port
                WebProxy(APP_DIR, PROXY_IP, PORT)
                ConnectInstallRun(
                    TOOLS_DIR, ADB_CON_ID, APP_PATH, PKG, LNCH,
                    True)  #Change True to support non-activity components
                SCREEN_WIDTH, SCREEN_HEIGHT = GetRes()
                data = {
                    'ready': 'yes',
                    'screen_witdth': SCREEN_WIDTH,
                    'screen_height': SCREEN_HEIGHT,
                }
                return HttpResponse(json.dumps(data),
                                    content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Setting up Dynamic Analysis Environment")
        return HttpResponseRedirect('/error/')
Пример #25
0
def res_analysis(app_dir, typ):
    """Perform the elf analysis."""
    try:
        print("[INFO] Static Android Resourse Analysis Started")
        elf_desc = {
            'html_infected':
            ('Found html files infected by malware.', 'high',
             'The built environment was probably infected by malware, The html file '
             'used in this APK is infected.'),
        }
        html_an_dic = {}
        for k in list(elf_desc.keys()):
            html_an_dic[k] = []
        resraw = os.path.join(app_dir, "res", "raw")
        assets = os.path.join(app_dir, "assets")
        for resdir in (resraw, assets):
            if os.path.exists(resdir) and os.path.isdir(resdir):
                for pdir, dirl, filel in os.walk(resdir):
                    for filename in filel:
                        if filename.endswith(".htm") or filename.endswith(
                                ".html"):
                            try:
                                filepath = os.path.join(pdir, filename)
                                buf = ""
                                with io.open(filepath, mode='rb') as filp:
                                    buf = filp.read()
                                if "svchost.exe" in buf:
                                    html_an_dic['html_infected'].append(
                                        filepath.replace(app_dir, ""))
                            except Exception as e:
                                pass
        res = []
        for k, filelist in list(html_an_dic.items()):
            if len(filelist):
                descs = elf_desc.get(k)
                res.append({
                    'title': descs[0],
                    'stat': descs[1],
                    'desc': descs[2],
                    'file': " ".join(filelist),
                })
        return res

    except:
        PrintException("[ERROR] Performing Resourse Analysis")
def DynamicAnalyzer(request):

    print "\n[INFO] Dynamic Analysis Started"
    try:
        if request.method == 'POST':
            MD5 = request.POST['md5']
            PKG = request.POST['pkg']
            LNCH = request.POST['lng']
            if re.findall(";|\$\(|\|\||&&", PKG) or re.findall(
                    ";|\$\(|\|\||&&", LNCH):
                print "[ATTACK] Possible RCE"
                return HttpResponseRedirect('/error/')
            m = re.match('^[0-9a-f]{32}$', MD5)
            if m:
                # Delete ScreenCast Cache
                SCREEN_FILE = os.path.join(settings.SCREEN_DIR, 'screen.png')
                if os.path.exists(SCREEN_FILE):
                    os.remove(SCREEN_FILE)
                # Delete Contents of Screenshot Dir
                SCRDIR = os.path.join(settings.UPLD_DIR,
                                      MD5 + '/screenshots-apk/')
                if os.path.isdir(SCRDIR):
                    shutil.rmtree(SCRDIR)
                #Start DM
                Proxy("", "", "", "")
                if settings.REAL_DEVICE:
                    print "\n[INFO] MobSF will perform Dynamic Analysis on real Android Device"
                else:
                    #Refersh VM
                    RefreshVM(settings.UUID, settings.SUUID, settings.VBOX)
                context = {
                    'md5': MD5,
                    'pkg': PKG,
                    'lng': LNCH,
                    'title': 'Start Testing',
                }
                template = "start_test.html"
                return render(request, template, context)
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] DynamicAnalyzer")
        return HttpResponseRedirect('/error/')
def HashGen(APP_PATH):
    """Generate and return sha1 and sha256 as a tupel."""
    try:
        print "[INFO] Generating Hashes"
        sha1 = hashlib.sha1()
        sha256 = hashlib.sha256()
        BLOCKSIZE = 65536
        with io.open(APP_PATH, mode='rb') as afile:
            buf = afile.read(BLOCKSIZE)
            while buf:
                sha1.update(buf)
                sha256.update(buf)
                buf = afile.read(BLOCKSIZE)
        sha1val = sha1.hexdigest()
        sha256val = sha256.hexdigest()
        return sha1val, sha256val
    except:
        PrintException("[ERROR] Generating Hashes")
def dex_2_smali(app_dir, tools_dir):
    """Run dex2smali"""
    try:
        print "[INFO] DEX -> SMALI"
        dex_path = app_dir + 'classes.dex'
        if len(settings.BACKSMALI_BINARY) > 0 and isFileExists(
                settings.BACKSMALI_BINARY):
            bs_path = settings.BACKSMALI_BINARY
        else:
            bs_path = os.path.join(tools_dir, 'baksmali.jar')
        output = os.path.join(app_dir, 'smali_source/')
        args = [
            settings.JAVA_PATH + 'java', '-jar', bs_path, dex_path, '-o',
            output
        ]
        subprocess.call(args)
    except:
        PrintException("[ERROR] Converting DEX to SMALI")
Пример #29
0
def hash_gen(app_path):
    """Generate and return sha1 and sha256 as a tupel."""
    try:
        print "[INFO] Generating Hashes"
        sha1 = hashlib.sha1()
        sha256 = hashlib.sha256()
        block_size = 65536
        with io.open(app_path, mode='rb') as afile:
            buf = afile.read(block_size)
            while buf:
                sha1.update(buf)
                sha256.update(buf)
                buf = afile.read(block_size)
        sha1val = sha1.hexdigest()
        sha256val = sha256.hexdigest()
        return sha1val, sha256val
    except:
        PrintException("[ERROR] Generating Hashes")
def InstallRun(TOOLSDIR, APKPATH, PACKAGE, LAUNCH, isACT):
    print "\n[INFO] Starting App for Dynamic Analysis"
    try:
        adb = getADB(TOOLSDIR)
        print "\n[INFO] Installing APK"
        subprocess.call([adb, "-s", getIdentifier(), "install", "-r", APKPATH])
        if isACT:
            runApp = PACKAGE + "/" + LAUNCH
            print "\n[INFO] Launching APK Main Activity"
            subprocess.call([adb, "-s", getIdentifier(),
                             "shell", "am", "start", "-n", runApp])
        else:
            print "\n[INFO] App Doesn't have a Main Activity"
            # Handle Service or Give Choice to Select in Future.
            pass
        print "[INFO] Testing Environment is Ready!"
    except:
        PrintException("[ERROR]  Starting App for Dynamic Analysis")