def get_env(md5_hash, package, launcher):
    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
    toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/')  # TOOLS DIR
    adb = getADB(toolsdir)
    #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)
    # AVD only needs to wait, vm needs the connect function
    try:
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
            avd_load_wait(adb)
        else:
            connect(toolsdir)
    except Exception as exp:
        print("\n[WARNING] ADB Load Wait Failed")
        return HttpResponseRedirect('/error/')
    # Change True to support non-activity components
    install_and_run(toolsdir, app_path, package, launcher, True)
    screen_width, screen_width = get_res()
    data = {
        'ready': 'yes',
        'screen_witdth': screen_width,
        'screen_height': screen_width,
    }
    return data
def TakeScreenShot(request):
    print "\n[INFO] Taking Screenshot"
    try:
        if request.method == 'POST':
            MD5 = request.POST['md5']
            m = re.match('^[0-9a-f]{32}$', MD5)
            if m:
                data = {}
                r = random.randint(1, 1000000)
                DIR = settings.BASE_DIR
                # make sure that list only png from this directory
                SCRDIR = os.path.join(
                    settings.UPLD_DIR, MD5 + '/screenshots-apk/')
                TOOLSDIR = os.path.join(
                    DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(TOOLSDIR)
                subprocess.call([adb, "-s", getIdentifier(), "shell",
                                 "screencap", "-p", "/data/local/screen.png"])
                subprocess.call([adb, "-s", getIdentifier(), "pull",
                                 "/data/local/screen.png", SCRDIR + "screenshot-" + str(r) + ".png"])
                print "\n[INFO] Screenshot Taken"
                data = {'screenshot': 'yes'}
                return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Taking Screenshot")
        return HttpResponseRedirect('/error/')
def execute_adb(request):
    """Execute ADB Commands"""
    print("\n[INFO] Executing ADB Commands")
    try:
        if request.method == 'POST':
            data = {}
            cmd = request.POST['cmd']
            '''
            Allow dangerous chars as it's functional
            TODO: Deal with it.
            '''
            adb = getADB()
            args = [adb, "-s", get_identifier()] + cmd.split(' ')
            resp = "error"
            try:
                resp = adb
            except:
                PrintException("[ERROR] Executing ADB Commands")
            data = {'cmd': 'yes', 'resp': resp.decode("utf8", "ignore")}
            return HttpResponse(json.dumps(data),
                                content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Executing ADB Commands")
        return HttpResponseRedirect('/error/')
def clip_dump(request):
    """
    Dump Android ClipBoard
    """
    print "\n[INFO] Starting Clipboard Dump Service in VM/Device"
    try:
        data = {}
        if request.method == 'POST':
            tools_dir = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(tools_dir)
            args = [adb, "-s", getIdentifier(), "shell", "am", "startservice",
                         "opensecurity.clipdump/.ClipDumper"]
            try:
                subprocess.call(args)
                data = {'status': 'success'}
            except:
                PrintException("[ERROR] Dumping Clipboard")
                data = {'status': 'error'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Dumping Clipboard")
        return HttpResponseRedirect('/error/')
def install_and_run(toolsdir, apk_path, package, launcher, is_activity):
    """Install APK and Run it"""
    print("\n[INFO] Starting App for Dynamic Analysis")
    adb = getADB(toolsdir)
    print("\n[INFO] Installing APK")
    install_result = subprocess.check_output(
        [adb, "-s", get_identifier(), "install", "-r", apk_path])
    print(install_result)
    # not signed error
    # sign example: jarsigner -verbose -keystore davidblus_android.keystore -storepass davidblus -signedjar app_signed.apk app.apk davidblus_android.keystore
    if b'INSTALL_PARSE_FAILED_NO_CERTIFICATES' in install_result:
        signed_apk_path = sign_apk(apk_path)
        install_result = subprocess.check_output(
            [adb, "-s",
             get_identifier(), "install", "-r", signed_apk_path])
        print(install_result)
    if b'Success' not in install_result:
        raise Exception('Install Error')
    if is_activity:
        run_app = package + "/" + launcher
        print("\n[INFO] Launching APK Main Activity")
        subprocess.call([
            adb, "-s",
            get_identifier(), "shell", "am", "start", "-n", run_app
        ])
    else:
        print("\n[INFO] App Doesn't have a Main Activity")
    print("[INFO] Testing Environment is Ready!")
def ExecuteADB(request):
    print "\n[INFO] Executing ADB Commands"
    try:
        if request.method == 'POST':
            data = {}
            CMD = request.POST['cmd']
            '''
            #Allow it Since it's functional
            if re.findall(";|\$\(|\|\||&&",CMD):
                print "[ATTACK] Possible RCE"
                return HttpResponseRedirect('/error/')
            '''
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(TOOLSDIR)
            args = [adb, "-s", getIdentifier()] + CMD.split(' ')
            resp = "error"
            try:
                resp = subprocess.check_output(args)
            except:
                PrintException("[ERROR] Executing ADB Commands")
            data = {'cmd': 'yes', 'resp': resp}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Executing ADB Commands")
        return HttpResponseRedirect('/error/')
def get_res():
    """Get Screen Resolution or Device or VM"""
    print "\n[INFO] Getting Screen Resolution"
    try:
        toolsdir = os.path.join(
            settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
        adb = getADB(toolsdir)
        resp = subprocess.check_output(
            [adb, "-s", get_identifier(), "shell", "dumpsys", "window"])
        resp = resp.split("\n")
        res = ""
        for line in resp:
            if "mUnrestrictedScreen" in line:
                res = line
                break
        res = res.split("(0,0)")[1]
        res = res.strip()
        res = res.split("x")
        if len(res) == 2:
            return res[0], res[1]
            # width, height
        return "", ""
    except:
        PrintException("[ERROR] Getting Screen Resolution")
        return "", ""
def install_and_run(toolsdir, apk_path, package, launcher, is_activity):
    """Install APK and Run it"""
    print "\n[INFO] Starting App for Dynamic Analysis"
    # try:
    adb = getADB(toolsdir)
    print "\n[INFO] Installing APK"
    install_result = subprocess.check_output(
        [adb, "-s", get_identifier(), "install", "-r", apk_path])
    print install_result
    # 如果是未签名的错误,则对其进行签名并安装,
    # 签名命令示例:jarsigner -verbose -keystore davidblus_android.keystore -storepass davidblus -signedjar app_signed.apk app.apk davidblus_android.keystore
    if 'INSTALL_PARSE_FAILED_NO_CERTIFICATES' in install_result:
        signed_apk_path = sign_apk(apk_path)
        install_result = subprocess.check_output(
            [adb, "-s",
             get_identifier(), "install", "-r", signed_apk_path])
        print install_result
    if 'Success' not in install_result:
        raise Exception('Install Error')
    if is_activity:
        run_app = package + "/" + launcher
        print "\n[INFO] Launching APK Main Activity"
        subprocess.call([
            adb, "-s",
            get_identifier(), "shell", "am", "start", "-n", run_app
        ])
    else:
        print "\n[INFO] App Doesn't have a Main Activity"
        # Handle Service or Give Choice to Select in Future.
    print "[INFO] Testing Environment is Ready!"
def MobSFCA(request):
    try:
        if request.method == 'POST':
            data = {}
            act = request.POST['action']
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            ROOTCA = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/pyWebProxy/ca.crt')
            adb = getADB(TOOLSDIR)
            if act == "install":
                print "\n[INFO] Installing MobSF RootCA"
                subprocess.call([adb, "-s", getIdentifier(), "push",
                                 ROOTCA, "/data/local/tmp/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c", "cp", "/data/local/tmp/" +
                                 settings.ROOT_CA, "/system/etc/security/cacerts/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c",
                                 "chmod", "644", "/system/etc/security/cacerts/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell",
                                 "rm", "/data/local/tmp/" + settings.ROOT_CA])
                data = {'ca': 'installed'}
            elif act == "remove":
                print "\n[INFO] Removing MobSF RootCA"
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c",
                                 "rm", "/system/etc/security/cacerts/" + settings.ROOT_CA])
                data = {'ca': 'removed'}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] MobSF RootCA Handler")
        return HttpResponseRedirect('/error/')
def touch(request):
    """Sending Touch Events"""
    logger.info("Sending Touch Events")
    try:
        data = {}
        if (request.method == 'POST') and (is_number(request.POST['x'])) and (is_number(request.POST['y'])):
            x_axis = request.POST['x']
            y_axis = request.POST['y']
            adb = getADB()
            args = ["input",
                    "tap",
                    x_axis,
                    y_axis]
            data = {'status': 'success'}
            try:
                adb_command(args, True)
            except:
                data = {'status': 'error'}
                PrintException("Performing Touch Action")
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("Sending Touch Events")
        return print_n_send_error_response(request, "Error Sending Touch Events", True)
def start_dm(md5_hash, package, launcher):
    # Start DM
    #stop_capfuzz(settings.PORT)
    toolsdir = os.path.join(settings.BASE_DIR,
                            'DynamicAnalyzer/tools/')  # TOOLS DIR
    adb = getADB(toolsdir)
    if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
        print(
            "\n[INFO] MobSF will perform Dynamic Analysis on real Android Device"
        )
        is_avd = False
    elif settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
        # adb, avd_path, reference_name, dup_name, emulator
        is_avd = True
        refresh_avd(adb, settings.AVD_PATH, settings.AVD_REFERENCE_NAME,
                    settings.AVD_DUP_NAME, settings.AVD_EMULATOR)
    else:
        # Refersh VM
        is_avd = False
        refresh_vm(settings.UUID, settings.SUUID, settings.VBOX)
    context = {
        'md5': md5_hash,
        'pkg': package,
        'lng': launcher,
        'title': 'Start Testing',
        'AVD': is_avd,
    }
    return context
def auto_app_test(app_info):
    base_dir = settings.BASE_DIR
    toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/')  # TOOLS DIR
    adb = getADB(toolsdir)

    print(u'\n[INFO] 开始自动化测试...')

    # monkey script 测试,用于进入初始化界面
    monkey_script_test(adb, app_info)

    packagename = app_info['packagename']
    # monkey 测试,输出太多,重定向输出
    p = subprocess.Popen([
        adb, '-s',
        get_identifier(), 'shell', 'monkey', '-p', packagename,
        '--ignore-crashes', '--ignore-timeouts', '--monitor-native-crashes',
        '-v', '-v', '-v', '300'
    ],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    # 设置超时检查
    start_time = time.time()
    while True:
        if p.poll() is not None:
            #useless_out, useless_err = p.communicate()
            break
        if time.time() - start_time > 60:
            p.terminate()
            break
        time.sleep(0.5)

    # TODO: 添加其他测试方法
    return
def clip_dump(request):
    """Dump Android ClipBoard"""
    print("\n[INFO] Starting Clipboard Dump Service in VM/Device")
    try:
        data = {}
        if request.method == 'POST':
            toolsdir = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(toolsdir)
            args = [adb,
                    "-s",
                    get_identifier(),
                    "shell",
                    "am",
                    "startservice",
                    "opensecurity.clipdump/.ClipDumper"]
            try:
                subprocess.call(args)
                data = {'status': 'success'}
            except:
                PrintException("[ERROR] Dumping Clipboard")
                data = {'status': 'error'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Dumping Clipboard")
        return HttpResponseRedirect('/error/')
示例#14
0
def MobSFCA(request):
    try:
        if request.method == 'POST':
            data = {}
            act = request.POST['action']
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            ROOTCA = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/pyWebProxy/ca.crt')
            adb = getADB(TOOLSDIR)
            if act == "install":
                print "\n[INFO] Installing MobSF RootCA"
                subprocess.call([adb, "-s", getIdentifier(), "push",
                                 ROOTCA, "/data/local/tmp/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c", "cp", "/data/local/tmp/" +
                                 settings.ROOT_CA, "/system/etc/security/cacerts/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c",
                                 "chmod", "644", "/system/etc/security/cacerts/" + settings.ROOT_CA])
                subprocess.call([adb, "-s", getIdentifier(), "shell",
                                 "rm", "/data/local/tmp/" + settings.ROOT_CA])
                data = {'ca': 'installed'}
            elif act == "remove":
                print "\n[INFO] Removing MobSF RootCA"
                subprocess.call([adb, "-s", getIdentifier(), "shell", "su", "-c",
                                 "rm", "/system/etc/security/cacerts/" + settings.ROOT_CA])
                data = {'ca': 'removed'}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] MobSF RootCA Handler")
        return HttpResponseRedirect('/error/')
def connect():
    """Connect to VM/Device"""
    logger.info("Connecting to VM/Device")
    adb = getADB()
    subprocess.call([adb, "kill-server"])
    subprocess.call([adb, "start-server"])
    logger.info("ADB Started")
    wait(5)
    logger.info("Connecting to VM/Device")
    out = subprocess.check_output([adb, "connect", get_identifier()])
    if b"unable to connect" in out:
        raise ValueError("ERROR Connecting to VM/Device. ",
                         out.decode("utf-8").replace("\n", ""))
    try:
        subprocess.call([adb, "-s", get_identifier(), "wait-for-device"])
        logger.info("Mounting")
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
            adb_command(["su", "-c", "mount", "-o",
                         "rw,remount,rw", "/system"], True)
        else:
            adb_command(["su", "-c", "mount", "-o",
                         "rw,remount,rw", "/system"], True)
            # This may not work for VMs other than the default MobSF VM
            adb_command(["mount", "-o", "rw,remount", "-t", "rfs",
                         "/dev/block/sda6", "/system"], True)
    except:
        PrintException("Connecting to VM/Device")
示例#16
0
def TakeScreenShot(request):
    print "\n[INFO] Taking Screenshot"
    try:
        if request.method == 'POST':
            MD5 = request.POST['md5']
            m = re.match('^[0-9a-f]{32}$', MD5)
            if m:
                data = {}
                r = random.randint(1, 1000000)
                DIR = settings.BASE_DIR
                # make sure that list only png from this directory
                SCRDIR = os.path.join(
                    settings.UPLD_DIR, MD5 + '/screenshots-apk/')
                TOOLSDIR = os.path.join(
                    DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(TOOLSDIR)
                subprocess.call([adb, "-s", getIdentifier(), "shell",
                                 "screencap", "-p", "/data/local/screen.png"])
                subprocess.call([adb, "-s", getIdentifier(), "pull",
                                 "/data/local/screen.png", SCRDIR + "screenshot-" + str(r) + ".png"])
                print "\n[INFO] Screenshot Taken"
                data = {'screenshot': 'yes'}
                return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Taking Screenshot")
        return HttpResponseRedirect('/error/')
示例#17
0
def ExecuteADB(request):
    print "\n[INFO] Executing ADB Commands"
    try:
        if request.method == 'POST':
            data = {}
            CMD = request.POST['cmd']
            '''
            #Allow it Since it's functional
            if re.findall(";|\$\(|\|\||&&",CMD):
                print "[ATTACK] Possible RCE"
                return HttpResponseRedirect('/error/')
            '''
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(TOOLSDIR)
            args = [adb, "-s", getIdentifier()] + CMD.split(' ')
            resp = "error"
            try:
                resp = subprocess.check_output(args)
            except:
                PrintException("[ERROR] Executing ADB Commands")
            data = {'cmd': 'yes', 'resp': resp}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Executing ADB Commands")
        return HttpResponseRedirect('/error/')
示例#18
0
文件: dynamic.py 项目: ays14/mobsf
def final_test(request):
    """Collecting Data and Cleanup"""
    global TCP_SERVER_MODE
    print("\n[INFO] Collecting Data and Cleaning Up")
    try:
        if request.method == 'POST':
            data = {}
            md5_hash = request.POST['md5']
            package = request.POST['pkg']
            if re.findall(r";|\$\(|\|\||&&", package):
                print("[ATTACK] Possible RCE")
                return HttpResponseRedirect('/error/')
            if re.match('^[0-9a-f]{32}$', md5_hash):
                # Stop ScreenCast Client if it is running
                TCP_SERVER_MODE = "off"
                base_dir = settings.BASE_DIR
                apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/')
                toolsdir = os.path.join(base_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 ' + get_identifier() +
                          ' logcat -d dalvikvm:W ActivityManager:I > "' +
                          apk_dir + 'logcat.txt"')
                print("\n[INFO] Downloading Logcat logs")
                subprocess.call([
                    adb, "-s",
                    get_identifier(), "pull",
                    "/data/data/de.robv.android.xposed.installer/log/error.log",
                    apk_dir + "x_logcat.txt"
                ])

                print("\n[INFO] Downloading Droidmon API Monitor Logcat logs")
                # Can't RCE
                os.system(adb + ' -s ' + get_identifier() +
                          ' shell dumpsys > "' + apk_dir + 'dump.txt"')
                print("\n[INFO] Downloading Dumpsys logs")
                subprocess.call([
                    adb, "-s",
                    get_identifier(), "shell", "am", "force-stop", package
                ])
                print("\n[INFO] Stopping Application")

                subprocess.call([
                    adb, "-s",
                    get_identifier(), "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/')
示例#19
0
文件: dynamic.py 项目: ays14/mobsf
def android_dynamic_analyzer(request):
    """Android Dynamic Analyzer View"""
    print("\n[INFO] Dynamic Analysis Started")
    try:
        if request.method == 'POST':
            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):
                # 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
                screen_dir = os.path.join(settings.UPLD_DIR,
                                          md5_hash + '/screenshots-apk/')
                if os.path.isdir(screen_dir):
                    shutil.rmtree(screen_dir)
                else:
                    os.makedirs(screen_dir)
                # Start DM
                stop_capfuzz(settings.PORT)
                toolsdir = os.path.join(settings.BASE_DIR,
                                        'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(toolsdir)
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
                    print(
                        "\n[INFO] MobSF will perform Dynamic Analysis on real Android Device"
                    )
                    is_avd = False
                elif settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    # adb, avd_path, reference_name, dup_name, emulator
                    is_avd = True
                    refresh_avd(adb, settings.AVD_PATH,
                                settings.AVD_REFERENCE_NAME,
                                settings.AVD_DUP_NAME, settings.AVD_EMULATOR)
                else:
                    # Refersh VM
                    is_avd = False
                    refresh_vm(settings.UUID, settings.SUUID, settings.VBOX)
                context = {
                    'md5': md5_hash,
                    'pkg': package,
                    'lng': launcher,
                    'title': 'Start Testing',
                    'AVD': is_avd,
                }
                template = "dynamic_analysis/start_test.html"
                return render(request, template, context)
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] DynamicAnalyzer")
        return HttpResponseRedirect('/error/')
def execute_adb(request):
    """Execute ADB Commands"""
    print("\n[INFO] Executing ADB Commands")
    try:
        if request.method == 'POST':
            data = {}
            cmd = request.POST['cmd']
            '''
            Allow dangerous chars as it's functional
            TODO: Deal with it.
            '''
            toolsdir = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(toolsdir)
            args = [adb,
                    "-s",
                    get_identifier()] + cmd.split(' ')
            resp = "error"
            try:
                resp = subprocess.check_output(args)
            except:
                PrintException("[ERROR] Executing ADB Commands")
            data = {'cmd': 'yes', 'resp': resp.decode("utf8", "ignore")}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Executing ADB Commands")
        return HttpResponseRedirect('/error/')
def touch(request):
    """Sending Touch Events"""
    print("\n[INFO] Sending Touch Events")
    try:
        data = {}
        if (request.method == 'POST') and (is_number(request.POST['x'])) and (is_number(request.POST['y'])):
            x_axis = request.POST['x']
            y_axis = request.POST['y']
            toolsdir = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(toolsdir)
            args = [adb,
                    "-s",
                    get_identifier(),
                    "shell",
                    "input",
                    "tap",
                    x_axis,
                    y_axis]
            data = {'status': 'success'}
            try:
                subprocess.call(args)
            except:
                data = {'status': 'error'}
                PrintException("[ERROR] Performing Touch Action")
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Sending Touch Events")
        return HttpResponseRedirect('/error/')
示例#22
0
def yield_dynamic_run(apk_path):
    try:
        #step1: app_info
        app_info = get_base_info(apk_path)

        #step2 init virtual android devices by virtualbox
        refresh_vm(SETTINGS.UUID, SETTINGS.SUUID, SETTINGS.VBOX)
        connect(DYNAMIC_TOOL_DIR)

        #step3 install, run
        install_and_run(DYNAMIC_TOOL_DIR, app_info['apk_path'],
                        app_info['packagename'], app_info['main_activity'],
                        True)

        #step4 auto_app_test and start download x_logcat.txt
        #auto_app_test in another thread, download in main thread
        set_run_state(True)
        adb = getADB(DYNAMIC_TOOL_DIR)
        monkey = threading.Thread(target=monkey_test, args=(adb, app_info))
        monkey.start()

        for cnt in yield_droidmon_download(adb, app_info['detail_dir'],
                                           app_info['packagename']):
            yield cnt
            if not check_run_state():
                break
        monkey.join()

    except Exception as e:
        result = {}
        traceback.print_exc()
def connect(toolsdir):
    """Connect to VM/Device"""
    print "\n[INFO] Connecting to VM/Device"
    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", get_identifier()])
        subprocess.call([adb, "-s", get_identifier(), "wait-for-device"])
        print "\n[INFO] Mounting"
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
            subprocess.call([
                adb, "-s",
                get_identifier(), "shell", "su", "-c", "mount", "-o",
                "rw,remount,rw", "/system"
            ])
        else:
            subprocess.call([
                adb, "-s",
                get_identifier(), "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",
                get_identifier(), "shell", "mount", "-o", "rw,remount", "-t",
                "rfs", "/dev/block/sda6", "/system"
            ])
    except:
        PrintException("[ERROR]  Connecting to VM/Device")
示例#24
0
def get_res():
    """Get Screen Resolution or Device or VM"""
    print("\n[INFO] Getting Screen Resolution")
    try:
        toolsdir = os.path.join(settings.BASE_DIR,
                                'DynamicAnalyzer/tools/')  # TOOLS DIR
        adb = getADB(toolsdir)
        resp = subprocess.check_output(
            [adb, "-s",
             get_identifier(), "shell", "dumpsys", "window"])
        resp = resp.decode("utf-8").split("\n")
        res = ""
        for line in resp:
            if "mUnrestrictedScreen" in line:
                res = line
                break
        res = res.split("(0,0)")[1]
        res = res.strip()
        res = res.split("x")
        if len(res) == 2:
            return res[0], res[1]
            # width, height
        return "", ""
    except:
        PrintException("[ERROR] Getting Screen Resolution")
        return "", ""
示例#25
0
def touch(request):
    """Sending Touch Events"""
    print("\n[INFO] Sending Touch Events")
    try:
        data = {}
        if (request.method == 'POST') and (is_number(request.POST['x'])) and (is_number(request.POST['y'])):
            x_axis = request.POST['x']
            y_axis = request.POST['y']
            adb = getADB()
            args = ["input",
                    "tap",
                    x_axis,
                    y_axis]
            data = {'status': 'success'}
            try:
                adb_command(args, True)
            except:
                data = {'status': 'error'}
                PrintException("[ERROR] Performing Touch Action")
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Sending Touch Events")
        return HttpResponseRedirect('/error/')
示例#26
0
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/')
示例#27
0
def dynamic_main(file_path):

    # download_dir = ORIGIN_DOWNLOAD_DIR + app_info['file_md5'] + '/'

    try:
        file_md5 = genMD5(file_path)
        print('file_md5:', file_md5)

        app_info = get_static_info(file_path, file_md5)

        # 开始动态分析
        adb = getADB(DYNAMIC_TOOL_DIR)
        init_environment(adb)

        #set_web_proxy(app_info['file_md5'])

        connect_device(adb)

        # Change True to support non-activity components
        install_and_run(DYNAMIC_TOOL_DIR, app_info['apk_path'],
                        app_info['packagename'], app_info['mainactivity'],
                        True)

        # 开启下载 log 线程, 60s
        download_dir = os.path.dirname(os.path.dirname(app_info["apk_path"]))
        #t = start_strace(adb, download_dir, app_info['packagename'])
        t = start_download(adb, download_dir, app_info['packagename'])

        #time.sleep(40)
        #至少运行60s
        auto_app_test(adb, app_info)

        # 停止代理服务器,另一个线程会把网络传输数据保存到 UPLOAD_DIR 对应的文件夹中的 urls, WebTraffic.txt, requestdb 文件。
        #Proxy('', '', '', '')

        # 关闭下载 log 线程
        t.join()

        droidmon_log = os.path.join(download_dir, 'x_logcat.txt')
        droidmon_analysis(droidmon_log, app_info['packagename'])

        time.sleep(1)

        # 复制 apk 运行时访问的 url 到结果目录
        #shutil.copy(os.path.join(os.path.join(UPLOAD_DIR, app_info['file_md5']), 'urls'), os.path.join(download_dir, 'urls'))

        #result = analysis_x_logcat(download_dir + 'x_logcat.txt', app_info)
        #print(u'分析结果目录:', download_dir)
        # 由于临时文件比较大,当硬盘空间不足时,则删除临时文件,比如:UPLOAD_DIR,
        shutil.rmtree(os.path.dirname(app_info['apk_path']),
                      ignore_errors=True)
        return 1
    except Exception as e:
        result = {}
        # Install Error           表示安装 apk 文件时报错。
        # Parsing Manifest Error  表示解析 AndroidManifest.xml 文件时报错。
        print(traceback.format_exc())
    #shutil.rmtree(os.path.dirname(app_info['apk_path']))
    return 0
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 mobsf_ca(request):
    """Install and Remove MobSF Proxy RootCA"""
    try:
        if request.method == 'POST':
            data = {}
            act = request.POST['action']
            rootca = get_ca_dir()
            adb = getADB()
            if act == "install":
                logger.info("Installing MobSF RootCA")
                adb_command(
                    ["push", rootca, "/data/local/tmp/" + settings.ROOT_CA])
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    # For some reason, avd emulator does not have cp binary
                    adb_command([
                        "/data/local/tmp/busybox", "cp",
                        "/data/local/tmp/" + settings.ROOT_CA,
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                    adb_command([
                        "chmod", "644",
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                else:
                    adb_command([
                        "su", "-c", "cp",
                        "/data/local/tmp/" + settings.ROOT_CA,
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                    adb_command([
                        "su", "-c", "chmod", "644",
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                adb_command(["rm", "/data/local/tmp/" + settings.ROOT_CA],
                            True)
                data = {'ca': 'installed'}
            elif act == "remove":
                logger.info("Removing MobSF RootCA")
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    adb_command([
                        "rm",
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                else:
                    adb_command([
                        "su", "-c", "rm",
                        "/system/etc/security/cacerts/" + settings.ROOT_CA
                    ], True)
                data = {'ca': 'removed'}
            return HttpResponse(json.dumps(data),
                                content_type='application/json')
        else:
            return print_n_send_error_response(request, "Only POST allowed",
                                               True)
    except:
        PrintException("MobSF RootCA Handler")
        return print_n_send_error_response(request, "Error in RootCA Handler",
                                           True)
示例#30
0
文件: dynamic.py 项目: ays14/mobsf
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
                toolsdir = os.path.join(base_dir,
                                        'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(toolsdir)
                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)
                # AVD only needs to wait, vm needs the connect function
                try:
                    if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                        avd_load_wait(adb)
                    else:
                        connect(toolsdir)
                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(toolsdir, 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/')
def get_env(request):
    """Get Dynamic Analysis Environment for Android"""
    logger.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):
                return print_n_send_error_response(request,
                                                   "Possible RCE Attack", True)
            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 print_n_send_error_response(request,
                                                   "Invalid Scan Hash", True)
        else:
            return print_n_send_error_response(request, "Only POST allowed",
                                               True)
    except:
        PrintException("Setting up Dynamic Analysis Environment")
        return print_n_send_error_response(request, "Environment Setup Failed",
                                           True)
def get_packages(toolsdir):
    """Get List of Pacakges"""
    adb = getADB(toolsdir)
    args = [adb, "-s", get_identifier(), "shell", "ls", "/data/data"]
    # prolly a better way to get packages is needed
    try:
        return subprocess.check_output(args)
    except:
        return "error"
示例#33
0
def RunFridaServer(tools_dir, frida_server):
    """Invoke Frida Server in VM/Device"""
    print "\n[INFO] Starting Frida Server"
    try:
        adb = getADB(tools_dir)
        subprocess.Popen([adb, '-s', getIdentifier(), 'shell', 'su', '-c', '/data/local/tmp/'+frida_server, '&'])
        Wait(3)
    except:
        PrintException("[ERROR] Running Frida Server in the Device/VM")
def screen_cast(request):
    """Start or Stop ScreenCast Feature"""
    print("\n[INFO] Invoking ScreenCast Service in VM/Device")
    try:
        global TCP_SERVER_MODE
        data = {}
        if request.method == 'POST':
            mode = request.POST['mode']
            toolsdir = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(toolsdir)
            if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                ip_address = '10.0.2.2'
            else:
                ip_address = settings.SCREEN_IP
            port = str(settings.SCREEN_PORT)
            if mode == "on":
                args = [adb,
                        "-s",
                        get_identifier(),
                        "shell",
                        "am",
                        "startservice",
                        "-a",
                        ip_address + ":" + port,
                        "opensecurity.screencast/.StartScreenCast"]
                data = {'status': 'on'}
                TCP_SERVER_MODE = "on"
            elif mode == "off":
                args = [adb,
                        "-s",
                        get_identifier(),
                        "shell",
                        "am",
                        "force-stop",
                        "opensecurity.screencast"]
                data = {'status': 'off'}
                TCP_SERVER_MODE = "off"
            if (mode in ["on", "off"]):
                try:
                    subprocess.call(args)
                    screen_trd = threading.Thread(target=screencast_service)
                    screen_trd.setDaemon(True)
                    screen_trd.start()
                except:
                    PrintException("[ERROR] Casting Screen")
                    data = {'status': 'error'}
                    return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                data = {'status': 'failed'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Casting Screen")
        return HttpResponseRedirect('/error/')
def final_test(request):
    """Collecting Data and Cleanup"""
    global TCP_SERVER_MODE
    logger.info("Collecting Data and Cleaning Up")
    try:
        if request.method == 'POST':
            data = {}
            md5_hash = request.POST['md5']
            package = request.POST['pkg']
            if re.findall(r";|\$\(|\|\||&&", package):
                return print_n_send_error_response(request,
                                                   "Possible RCE Attack", True)
            if re.match('^[0-9a-f]{32}$', md5_hash):
                # Stop ScreenCast Client if it is running
                TCP_SERVER_MODE = "off"
                base_dir = settings.BASE_DIR
                apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/')
                adb = getADB()
                # Change to check output of subprocess when analysis is done
                # Can't RCE
                os.system(adb + ' -s ' + get_identifier() +
                          ' logcat -d dalvikvm:W ActivityManager:I > "' +
                          apk_dir + 'logcat.txt"')
                logger.info("Downloading Logcat logs")
                adb_command([
                    "pull",
                    "/data/data/de.robv.android.xposed.installer/log/error.log",
                    apk_dir + "x_logcat.txt"
                ])

                logger.info("Downloading Droidmon API Monitor Logcat logs")
                # Can't RCE
                os.system(adb + ' -s ' + get_identifier() +
                          ' shell dumpsys > "' + apk_dir + 'dump.txt"')
                logger.info("Downloading Dumpsys logs")

                adb_command(["am", "force-stop", package], True)
                logger.info("Stopping Application")

                adb_command(["am", "force-stop", "opensecurity.screencast"],
                            True)
                logger.info("Stopping ScreenCast Service")

                data = {'final': 'yes'}
                return HttpResponse(json.dumps(data),
                                    content_type='application/json')
            else:
                return print_n_send_error_response(request,
                                                   "Invalid Scan Hash", True)
        else:
            return print_n_send_error_response(request, "Only POST allowed",
                                               True)
    except:
        PrintException("Data Collection & Clean Up")
        return print_n_send_error_response(
            request, "Data Collection & Clean Up failed", True)
def DumpData(request):
    # Closing External Services and Dumping data
    print "\n[INFO] Device Data Dump"
    try:
        if request.method == 'POST':
            data = {}
            PACKAGE = request.POST['pkg']
            MD5 = request.POST['md5']
            m = re.match('^[0-9a-f]{32}$', MD5)
            if m:
                if re.findall(";|\$\(|\|\||&&", PACKAGE):
                    print "[ATTACK] Possible RCE"
                    return HttpResponseRedirect('/error/')
                DIR = settings.BASE_DIR
                APKDIR = os.path.join(settings.UPLD_DIR, MD5 + '/')
                TOOLSDIR = os.path.join(
                    DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(TOOLSDIR)
                # Let's try to close Proxy a bit early as we don't have much
                # control on the order of thread execution
                Proxy("", "", "", "")
                print "\n[INFO] Deleting Dump Status File"
                subprocess.call([adb, "-s", getIdentifier(),
                                 "shell", "rm", "/sdcard/mobsec_status"])
                print "\n[INFO] Creating TAR of Application Files."
                subprocess.call([adb, "-s", getIdentifier(), "shell", "am", "startservice",
                                 "-a", PACKAGE, "opensecurity.ajin.datapusher/.GetPackageLocation"])
                print "\n[INFO] Waiting for TAR dump to complete..."
                if settings.REAL_DEVICE:
                    timeout = settings.DEVICE_TIMEOUT
                else:
                    timeout = settings.VM_TIMEOUT
                start_time = time.time()
                while True:
                    current_time = time.time()
                    if "MOBSEC-TAR-CREATED" in subprocess.check_output([adb, "-s", getIdentifier(), "shell", "cat", "/sdcard/mobsec_status"]):
                        break
                    if (current_time - start_time) > timeout:
                        print "\n[ERROR] TAR Generation Failed. Process timed out."
                        break
                print "\n[INFO] Dumping Application Files from Device/VM"
                subprocess.call([adb, "-s", getIdentifier(), "pull",
                                 "/data/local/" + PACKAGE + ".tar", APKDIR + PACKAGE + ".tar"])
                print "\n[INFO] Stopping ADB"
                subprocess.call([adb, "-s", getIdentifier(), "kill-server"])
                data = {'dump': 'yes'}
                return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Device Data Dump")
        return HttpResponseRedirect('/error/')
示例#37
0
def DumpData(request):
    # Closing External Services and Dumping data
    print "\n[INFO] Device Data Dump"
    try:
        if request.method == 'POST':
            data = {}
            PACKAGE = request.POST['pkg']
            MD5 = request.POST['md5']
            m = re.match('^[0-9a-f]{32}$', MD5)
            if m:
                if re.findall(";|\$\(|\|\||&&", PACKAGE):
                    print "[ATTACK] Possible RCE"
                    return HttpResponseRedirect('/error/')
                DIR = settings.BASE_DIR
                APKDIR = os.path.join(settings.UPLD_DIR, MD5 + '/')
                TOOLSDIR = os.path.join(
                    DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
                adb = getADB(TOOLSDIR)
                # Let's try to close Proxy a bit early as we don't have much
                # control on the order of thread execution
                Proxy("", "", "", "")
                print "\n[INFO] Deleting Dump Status File"
                subprocess.call([adb, "-s", getIdentifier(),
                                 "shell", "rm", "/sdcard/mobsec_status"])
                print "\n[INFO] Creating TAR of Application Files."
                subprocess.call([adb, "-s", getIdentifier(), "shell", "am", "startservice",
                                 "-a", PACKAGE, "opensecurity.ajin.datapusher/.GetPackageLocation"])
                print "\n[INFO] Waiting for TAR dump to complete..."
                if settings.REAL_DEVICE:
                    timeout = settings.DEVICE_TIMEOUT
                else:
                    timeout = settings.VM_TIMEOUT
                start_time = time.time()
                while True:
                    current_time = time.time()
                    if "MOBSEC-TAR-CREATED" in subprocess.check_output([adb, "-s", getIdentifier(), "shell", "cat", "/sdcard/mobsec_status"]):
                        break
                    if (current_time - start_time) > timeout:
                        print "\n[ERROR] TAR Generation Failed. Process timed out."
                        break
                print "\n[INFO] Dumping Application Files from Device/VM"
                subprocess.call([adb, "-s", getIdentifier(), "pull",
                                 "/data/local/" + PACKAGE + ".tar", APKDIR + PACKAGE + ".tar"])
                print "\n[INFO] Stopping ADB"
                subprocess.call([adb, "-s", getIdentifier(), "kill-server"])
                data = {'dump': 'yes'}
                return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] Device Data Dump")
        return HttpResponseRedirect('/error/')
def android_dynamic_analyzer(request):
    """Android Dynamic Analyzer View"""
    print("\n[INFO] Dynamic Analysis Started")
    try:
        if request.method == 'POST':
            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):
                # 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
                screen_dir = os.path.join(
                    settings.UPLD_DIR, md5_hash + '/screenshots-apk/')
                if os.path.isdir(screen_dir):
                    shutil.rmtree(screen_dir)
                else:
                    os.makedirs(screen_dir)
                # Start DM
                stop_capfuzz(settings.PORT)
                adb = getADB()
                is_avd = False
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
                    print(
                        "\n[INFO] MobSF will perform Dynamic Analysis on real Android Device")
                elif settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    # adb, avd_path, reference_name, dup_name, emulator
                    is_avd = True
                    if not os.path.exists(settings.AVD_EMULATOR):
                        return HttpResponseRedirect('/error/')
                    if not refresh_avd():
                        return HttpResponseRedirect('/error/')
                else:
                    # Refersh VM
                    refresh_vm(settings.UUID, settings.SUUID, settings.VBOX)
                context = {'md5': md5_hash,
                           'pkg': package,
                           'lng': launcher,
                           'title': 'Start Testing',
                           'AVD': is_avd, }
                template = "dynamic_analysis/start_test.html"
                return render(request, template, context)
            else:
                return HttpResponseRedirect('/error/')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] DynamicAnalyzer")
        return HttpResponseRedirect('/error/')
def clean():
    base_dir = settings.BASE_DIR
    toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/')  # TOOLS DIR
    adb = getADB(toolsdir)

    print("\n[INFO] Stopping ADB")
    subprocess.call([adb, "-s", get_identifier(), "kill-server"])
    # Close VM
    args = [settings.VBOX, 'controlvm', settings.UUID, 'poweroff']
    subprocess.call(args)
    print("\n[INFO] VM Closed")
    return
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/')
def mobsf_ca(request):
    """Install and Remove MobSF Proxy RootCA"""
    try:
        if request.method == 'POST':
            data = {}
            act = request.POST['action']
            rootca = get_ca_dir()
            adb = getADB()
            if act == "install":
                print("\n[INFO] Installing MobSF RootCA")
                adb_command(
                    ["push", rootca, "/data/local/tmp/" + settings.ROOT_CA])
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    # For some reason, avd emulator does not have cp binary
                    adb_command(["/data/local/tmp/busybox", "cp",
                                 "/data/local/tmp/" + settings.ROOT_CA,
                                 "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                    adb_command(["chmod", "644",
                                 "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                else:
                    adb_command(["su",
                                 "-c",
                                 "cp",
                                 "/data/local/tmp/" + settings.ROOT_CA,
                                 "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                    adb_command(["su",
                                 "-c",
                                 "chmod",
                                 "644",
                                 "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                adb_command(
                    ["rm", "/data/local/tmp/" + settings.ROOT_CA], True)
                data = {'ca': 'installed'}
            elif act == "remove":
                print("\n[INFO] Removing MobSF RootCA")
                if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
                    adb_command(
                        ["rm", "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                else:
                    adb_command(["su",
                                 "-c",
                                 "rm",
                                 "/system/etc/security/cacerts/" + settings.ROOT_CA], True)
                data = {'ca': 'removed'}
            return HttpResponse(json.dumps(data), content_type='application/json')
        else:
            return HttpResponseRedirect('/error/')
    except:
        PrintException("[ERROR] MobSF RootCA Handler")
        return HttpResponseRedirect('/error/')
def final_test(request):
    """Collecting Data and Cleanup"""
    global TCP_SERVER_MODE
    print("\n[INFO] Collecting Data and Cleaning Up")
    try:
        if request.method == 'POST':
            data = {}
            md5_hash = request.POST['md5']
            package = request.POST['pkg']
            if re.findall(r";|\$\(|\|\||&&", package):
                print("[ATTACK] Possible RCE")
                return HttpResponseRedirect('/error/')
            if re.match('^[0-9a-f]{32}$', md5_hash):
                # Stop ScreenCast Client if it is running
                TCP_SERVER_MODE = "off"
                base_dir = settings.BASE_DIR
                apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/')
                adb = getADB()
                # Change to check output of subprocess when analysis is done
                # Can't RCE
                os.system(adb + ' -s ' + get_identifier() +
                          ' logcat -d dalvikvm:W ActivityManager:I > "' + apk_dir + 'logcat.txt"')
                print("\n[INFO] Downloading Logcat logs")
                adb_command(["pull", "/data/data/de.robv.android.xposed.installer/log/error.log",
                             apk_dir + "x_logcat.txt"])

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

                adb_command(["am", "force-stop", package], True)
                print("\n[INFO] Stopping Application")

                adb_command(
                    ["am", "force-stop", "opensecurity.screencast"], True)
                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/')
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/')
def install_and_run(apk_path, package, launcher, is_activity):
    """Install APK and Run it"""
    print("\n[INFO] Starting App for Dynamic Analysis")
    try:
        adb = getADB()
        print("\n[INFO] Installing APK")
        adb_command(["install", "-r", apk_path])
        if is_activity:
            run_app = package + "/" + launcher
            print("\n[INFO] Launching APK Main Activity")
            adb_command(["am", "start", "-n", run_app], True)
        else:
            print("\n[INFO] App Doesn't have a Main Activity")
            # Handle Service or Give Choice to Select in Future.
        print("[INFO] Testing Environment is Ready!")
    except:
        PrintException("[ERROR]  Starting App for Dynamic Analysis")
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")
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
def install_and_run(toolsdir, apk_path, package, launcher, is_activity):
    """Install APK and Run it"""
    print "\n[INFO] Starting App for Dynamic Analysis"
    try:
        adb = getADB(toolsdir)
        print "\n[INFO] Installing APK"
        subprocess.call([adb, "-s", get_identifier(),
                         "install", "-r", apk_path])
        if is_activity:
            run_app = package + "/" + launcher
            print "\n[INFO] Launching APK Main Activity"
            subprocess.call([adb, "-s", get_identifier(),
                             "shell", "am", "start", "-n", run_app])
        else:
            print "\n[INFO] App Doesn't have a Main Activity"
            # Handle Service or Give Choice to Select in Future.
        print "[INFO] Testing Environment is Ready!"
    except:
        PrintException("[ERROR]  Starting App for Dynamic Analysis")
def ScreenCast(request):
    print "\n[INFO] Invoking ScreenCast Service in VM/Device"
    try:
        global tcp_server_mode
        data = {}
        if (request.method == 'POST'):
            mode = request.POST['mode']
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(TOOLSDIR)
            IP = settings.SCREEN_IP
            PORT = str(settings.SCREEN_PORT)
            if mode == "on":
                args = [adb, "-s", getIdentifier(), "shell", "am", "startservice",
                        "-a", IP + ":" + PORT, "opensecurity.screencast/.StartScreenCast"]
                data = {'status': 'on'}
                tcp_server_mode = "on"
            elif mode == "off":
                args = [adb, "-s", getIdentifier(), "shell", "am",
                        "force-stop", "opensecurity.screencast"]
                data = {'status': 'off'}
                tcp_server_mode = "off"
            if (mode in ["on", "off"]):
                try:
                    subprocess.call(args)
                    t = threading.Thread(target=ScreenCastService)
                    t.setDaemon(True)
                    t.start()
                except:
                    PrintException("[ERROR] Casting Screen")
                    data = {'status': 'error'}
                    return HttpResponse(json.dumps(data), content_type='application/json')
            else:
                data = {'status': 'failed'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Casting Screen")
        return HttpResponseRedirect('/error/')
def clip_dump(request):
    """Dump Android ClipBoard"""
    print("\n[INFO] Starting Clipboard Dump Service in VM/Device")
    try:
        data = {}
        if request.method == 'POST':
            adb = getADB()
            args = ["am",
                    "startservice",
                    "opensecurity.clipdump/.ClipDumper"]
            try:
                adb_command(args, True)
                data = {'status': 'success'}
            except:
                PrintException("[ERROR] Dumping Clipboard")
                data = {'status': 'error'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Dumping Clipboard")
        return HttpResponseRedirect('/error/')
def clip_dump(request):
    """Dump Android ClipBoard"""
    logger.info("Starting Clipboard Dump Service in VM/Device")
    try:
        data = {}
        if request.method == 'POST':
            adb = getADB()
            args = ["am",
                    "startservice",
                    "opensecurity.clipdump/.ClipDumper"]
            try:
                adb_command(args, True)
                data = {'status': 'success'}
            except:
                PrintException("Dumping Clipboard")
                data = {'status': 'error'}
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("Dumping Clipboard")
        return print_n_send_error_response(request, "Error Dumping Clipboard", True)
def get_res():
    """Get Screen Resolution or Device or VM"""
    print("\n[INFO] Getting Screen Resolution")
    try:
        adb = getADB()
        resp = subprocess.check_output(
            [adb, "-s", get_identifier(), "shell", "dumpsys", "window"])
        resp = resp.decode("utf-8").split("\n")
        res = ""
        for line in resp:
            if "mUnrestrictedScreen" in line:
                res = line
                break
        res = res.split("(0,0)")[1]
        res = res.strip()
        res = res.split("x")
        if len(res) == 2:
            return res[0], res[1]
            # width, height
        return "", ""
    except:
        PrintException("[ERROR] Getting Screen Resolution")
        return "", ""
def connect():
    """Connect to VM/Device"""
    print("\n[INFO] Connecting to VM/Device")
    adb = getADB()
    subprocess.call([adb, "kill-server"])
    subprocess.call([adb, "start-server"])
    print("\n[INFO] ADB Started")
    wait(5)
    print("\n[INFO] Connecting to VM/Device")
    out = subprocess.check_output([adb, "connect", get_identifier()])
    if b"unable to connect" in out:
        raise ValueError("ERROR Connecting to VM/Device. ", out.decode("utf-8").replace("\n",""))
    try:
        subprocess.call([adb, "-s", get_identifier(), "wait-for-device"])
        print("\n[INFO] Mounting")
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
            adb_command(["su", "-c", "mount", "-o", "rw,remount,rw", "/system"], True)
        else:
            adb_command(["su", "-c", "mount", "-o", "rw,remount,rw", "/system"], True)
            # This may not work for VMs other than the default MobSF VM
            adb_command(["mount", "-o", "rw,remount", "-t", "rfs", "/dev/block/sda6", "/system"], True)
    except:
        PrintException("[ERROR]  Connecting to VM/Device")
def Connect(TOOLSDIR):
    print "\n[INFO] Connecting to VM/Device"
    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", getIdentifier()])
        subprocess.call([adb, "-s", getIdentifier(), "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"])
    except:
        PrintException("[ERROR]  Connecting to VM/Device")
def Touch(request):
    print "\n[INFO] Sending Touch Events"
    try:
        data = {}
        if (request.method == 'POST') and (is_number(request.POST['x'])) and (is_number(request.POST['y'])):
            x_axis = request.POST['x']
            y_axis = request.POST['y']
            TOOLSDIR = os.path.join(
                settings.BASE_DIR, 'DynamicAnalyzer/tools/')  # TOOLS DIR
            adb = getADB(TOOLSDIR)
            args = [adb, "-s", getIdentifier(), "shell", "input",
                    "tap", x_axis, y_axis]
            data = {'status': 'success'}
            try:
                subprocess.call(args)
            except:
                data = {'status': 'error'}
                PrintException("[ERROR] Performing Touch Action")
        else:
            data = {'status': 'failed'}
        return HttpResponse(json.dumps(data), content_type='application/json')
    except:
        PrintException("[ERROR] Sending Touch Events")
        return HttpResponseRedirect('/error/')
def connect(toolsdir):
    """Connect to VM/Device"""
    print "\n[INFO] Connecting to VM/Device"
    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", get_identifier()])
        subprocess.call([adb, "-s", get_identifier(), "wait-for-device"])
        print "\n[INFO] Mounting"
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
            subprocess.call([adb, "-s", get_identifier(), "shell",
                             "su", "-c", "mount", "-o", "rw,remount,rw", "/system"])
        else:
            subprocess.call([adb, "-s", get_identifier(), "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", get_identifier(), "shell", "mount",
                             "-o", "rw,remount", "-t", "rfs", "/dev/block/sda6", "/system"])
    except:
        PrintException("[ERROR]  Connecting to VM/Device")
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 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)