StaticAnalyzer/views/android/manifest_analysis.py
def get_manifest(app_dir, tools_dir, typ, binary):
    """Get the manifest file."""
    dat = read_manifest(app_dir, tools_dir, typ, binary).replace("\n", "")
    # changed by davidblus
    new_AndroidManifest = os.path.join(app_dir, 'new_AndroidManifest.xml')
    with open(new_AndroidManifest, 'w') as file:
        file.write(dat)
        
    try:
        manifest = minidom.parseString(dat)
    except Exception as err:
        try:
            dat_windows = dat.decode('gb2312', 'ignore')
            manifest = minidom.parseString(dat_windows)
        except Exception as err:
            try:
                apktool = os.path.join(os.path.join(tools_dir, 'apktool2.2.4'), 'apktool')
                apktool_dir = os.path.join(app_dir, 'apktool')
                app_apk = os.path.join(app_dir, 'app.apk')
                cmd_list = [apktool, "d", "-o", apktool_dir, "-s", app_apk]
                print cmd_list
                if platform.system() == 'Windows':
                    temp = subprocess.call(cmd_list, shell=True)
                else:
                    temp = subprocess.call(cmd_list)
                with open(os.path.join(apktool_dir, 'AndroidManifest.xml')) as fp:
                    dat = fp.read()
                manifest = minidom.parseString(dat)
            except Exception as err:
                print traceback.format_exc()
                raise Exception('Parsing Manifest Error')
            
    return manifest
DynamicAnalyzer/pyWebProxy/pywebproxy.py
def Proxy(IP, PORT, LOG, STAT):
    global kill, log
    if STAT == "on":
        log = LOG
        kill = False
        print "\n[INFO] Started Web Proxy at " + IP + ":" + PORT
        threading.Thread(target=startTornado, kwargs=dict(
            IP=IP, PORT=PORT, log=log)).start()
    else:
        print "\n[INFO] Stopping any running instance of WebProxy"
        kill = True
DynamicAnalyzer/views/android/android_dyn_shared.py
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!"
    # except:
    #     PrintException("[ERROR]  Starting App for Dynamic Analysis")
mass_static_analysis.py
def genMD5(app):

    BLOCKSIZE = 65536
    hasher = hashlib.md5()
    with open(app, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while buf:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)
    return (hasher.hexdigest())
DynamicAnalyzer/views/android/android_dyn_shared.py
def web_proxy(apk_dir, ip_address, port):
    """Run MITM Proxy"""
    print "\n[INFO] Starting Web Proxy"
    try:
        Proxy(ip_address, port, apk_dir, "on")
    except:
        PrintException("[ERROR] Starting Web Proxy")
DynamicAnalyzer/views/android/android_dyn_shared.py
def get_identifier():
    """Get Device Type"""
    try:
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE":
            return settings.DEVICE_IP + ":" + str(settings.DEVICE_ADB_PORT)
        elif settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD":
            return 'emulator-' + str(settings.AVD_ADB_PORT)
        else:
            return settings.VM_IP + ":" + str(settings.VM_ADB_PORT)
    except:
        PrintException(
            "[ERROR] Getting ADB Connection Identifier for Device/VM")
StaticAnalyzer/views/shared_func.py
def Unzip(APP_PATH, EXT_PATH):
    print "[INFO] Unzipping"
    try:
        files = []
        with zipfile.ZipFile(APP_PATH, "r") as z:
            for fileinfo in z.infolist():
                filename = fileinfo.filename
                if not isinstance(filename, unicode):
                    filename = unicode(filename, encoding="utf-8", errors="replace")
                files.append(filename)
                z.extract(fileinfo, EXT_PATH)
        return files
    except:
        PrintException("[ERROR] Unzipping Error")
        if platform.system() == "Windows":
            print "\n[INFO] Not yet Implemented."
            return files
        else:
            print "\n[INFO] Using the Default OS Unzip Utility."
            try:
                subprocess.call(
                    ['unzip', '-o', '-q', APP_PATH, '-d', EXT_PATH])
                dat = subprocess.check_output(['unzip', '-qq', '-l', APP_PATH])
                dat = dat.split('\n')
                x = ['Length   Date   Time   Name']
                x = x + dat
                return x
            except:
                PrintException("[ERROR] Unzipping Error")
MobSF/utils.py
def getADB(TOOLSDIR):
    """Get ADB binary path"""
    try:
        if len(settings.ADB_BINARY) > 0 and isFileExists(settings.ADB_BINARY):
            return settings.ADB_BINARY
        else:
            adb = 'adb'
            if platform.system() == "Darwin":
                adb_dir = os.path.join(TOOLSDIR, 'adb/mac/')
                subprocess.call(["chmod", "777", adb_dir])
                adb = os.path.join(TOOLSDIR, 'adb/mac/adb')
            elif platform.system() == "Linux":
                adb_dir = os.path.join(TOOLSDIR, 'adb/linux/')
                subprocess.call(["chmod", "777", adb_dir])
                adb = os.path.join(TOOLSDIR, 'adb/linux/adb')
            elif platform.system() == "Windows":
                adb = os.path.join(TOOLSDIR, 'adb/windows/adb.exe')
            return adb
    except:
        PrintException("[ERROR] Getting ADB Location")
        return "adb"
StaticAnalyzer/views/android/manifest_analysis.py
def manifest_data(mfxml):
    """Extract manifest data."""
    try:
        print "[INFO] Extracting Manifest Data"
        svc = []
        act = []
        brd = []
        cnp = []
        lib = []
        perm = []
        dvm_perm = {}
        package = ''
        minsdk = '1'
        maxsdk = ''
        targetsdk = ''
        mainact = ''
        androidversioncode = ''
        androidversionname = ''
        application_name = ''
        permissions = mfxml.getElementsByTagName("uses-permission")
        manifest = mfxml.getElementsByTagName("manifest")
        activities = mfxml.getElementsByTagName("activity")
        services = mfxml.getElementsByTagName("service")
        providers = mfxml.getElementsByTagName("provider")
        receivers = mfxml.getElementsByTagName("receiver")
        libs = mfxml.getElementsByTagName("uses-library")
        sdk = mfxml.getElementsByTagName("uses-sdk")
        application = mfxml.getElementsByTagName("application")
        for node in application:
            application_name = node.getAttribute("android:name")
        for node in sdk:
            minsdk = node.getAttribute("android:minSdkVersion")
            maxsdk = node.getAttribute("android:maxSdkVersion")
            # Esteve 08.08.2016 - begin - If android:targetSdkVersion is not set, the default value is the one of the android:minSdkVersion
            # targetsdk=node.getAttribute("android:targetSdkVersion")
            if node.getAttribute("android:targetSdkVersion"):
                targetsdk = node.getAttribute("android:targetSdkVersion")
            else:
                targetsdk = node.getAttribute("android:minSdkVersion")
            # End
        for node in manifest:
            package = node.getAttribute("package")
            androidversioncode = node.getAttribute("android:versionCode")
            androidversionname = node.getAttribute("android:versionName")
        for activity in activities:
            act_2 = activity.getAttribute("android:name")
            act.append(act_2)
            if len(mainact) < 1:
                # ^ Fix for Shitty Manifest with more than one MAIN
                for sitem in activity.getElementsByTagName("category"):
                    val = sitem.getAttribute("android:name")
                    if val == "android.intent.category.LAUNCHER":
                        mainact = activity.getAttribute("android:name")
        for activity in activities:
            if not mainact:
                for sitem in activity.getElementsByTagName("action"):
                    val = sitem.getAttribute("android:name")
                    if val == "android.intent.action.MAIN":
                        mainact = activity.getAttribute("android:name")

        for service in services:
            service_name = service.getAttribute("android:name")
            svc.append(service_name)

        for provider in providers:
            provider_name = provider.getAttribute("android:name")
            cnp.append(provider_name)

        for receiver in receivers:
            rec = receiver.getAttribute("android:name")
            brd.append(rec)

        for _lib in libs:
            libary = _lib.getAttribute("android:name")
            lib.append(libary)

        for permission in permissions:
            perm.append(permission.getAttribute("android:name"))

        for i in perm:
            prm = i
            pos = i.rfind(".")
            if pos != -1:
                prm = i[pos + 1:]
            try:
                dvm_perm[i] = DVM_PERMISSIONS["MANIFEST_PERMISSION"][prm]
            except KeyError:
                dvm_perm[i] = [
                    "dangerous",
                    "Unknown permission from android reference",
                    "Unknown permission from android reference"
                ]

        man_data_dic = {
            'services': svc,
            'activities': act,
            'receivers': brd,
            'providers': cnp,
            'libraries': lib,
            'perm': dvm_perm,
            'packagename': package,
            'mainactivity': mainact,
            'min_sdk': minsdk,
            'max_sdk': maxsdk,
            'target_sdk': targetsdk,
            'androver': androidversioncode,
            'androvername': androidversionname,
            'application_name': application_name
        }

        return man_data_dic
    except:
        PrintException("[ERROR] Extracting Manifest Data")
DynamicAnalyzer/views/android/android_avd.py
def avd_load_wait(adb):
    """Wait for AVD Load"""
    try:
        emulator = get_identifier()

        print "[INFO] Wait for emulator to load"
        args = [adb,
                "-s",
                emulator,
                "wait-for-device"]
        subprocess.call(args)

        print "[INFO] Wait for dev.boot_complete loop"
        while True:
            args = [adb,
                    "-s",
                    emulator,
                    "shell",
                    "getprop",
                    "dev.bootcomplete"]
            try:
                result = subprocess.check_output(args)
            except:
                result = None
            if result is not None and result.strip() == "1":
                break
            else:
                time.sleep(1)

        print "[INFO] Wait for sys.boot_complete loop"
        while True:
            args = [adb,
                    "-s",
                    emulator,
                    "shell",
                    "getprop",
                    "sys.boot_completed"]
            try:
                result = subprocess.check_output(args)
            except:
                result = None
            if result is not None and result.strip() == "1":
                break
            else:
                time.sleep(1)

        print "[INFO] Wait for svc.boot_complete loop"
        while True:
            args = [adb,
                    "-s",
                    emulator,
                    "shell",
                    "getprop",
                    "init.svc.bootanim"]
            try:
                result = subprocess.check_output(args)
            except:
                result = None
            if result is not None and result.strip() == "stopped":
                break
            else:
                time.sleep(1)
        time.sleep(5)
        # Remount the partitions for RW
        subprocess.call([adb, "-s", emulator, "remount"])
        return True
    except:
        PrintException("[ERROR] emulator did not boot properly")
        return False
Analysis_x_logcat/analysis.py
def analysis_x_logcat(x_file_name, app_info):
    package_name = app_info['packagename']
    
    # 新的 app_info 包含所有可能的manifest文件中提到的java代码所在的包名
    app_info = set_java_package_names(app_info)
    
    # func_timeflow 表示以时间顺序记录的函数调用列表。 TODO: 供后续制定以时间序列调用api的规则，进而检测分析。
    func_timeflow = load_x_file(x_file_name, package_name)
    file_timeflow = x_file_name + '_timeflow_list.json'
    save_file(file_timeflow, func_timeflow)
    
    # 把时间顺序记录的函数调用列表转换为二维特征数据
    try:
        timeflow_to_numpy(file_timeflow, FILE_S_JSON)
    except Exception as e:
        print u'把时间序列转换为二维特征数据时出异常：', traceback.format_exc()
    
    # hook_datas 表示数据处理过程中的中间结果。
    hook_datas = make_hooks_datas(func_timeflow, package_name, app_info['java_package_names'])
    #save_file(x_file_name + '_hook_result.json', hook_datas)
    
    # func_statistic 表示以api为关键字的函数调用列表。 TODO: 供后续制定以api调用详细信息的规则，进而检测分析。
    func_statistic = count_function(hook_datas, package_name)
    file_count_function = x_file_name + '_count_function.json'
    save_file(file_count_function, func_statistic)
    
    # 根据 api调用->敏感行为 规则，查出其具有的敏感行为列表。
    sensitives = transfer_func_to_sen(func_statistic)
    sensitives = delete_empty_element(sensitives)
    save_file(x_file_name + '_sensitives.json', sensitives)
    
    # 根据 api调用->漏洞 规则，查出其具有的漏洞列表。
    vulnerabilities = transfer_func_to_vul(func_statistic, app_info)
    vulnerabilities = remove_white(vulnerabilities)
    vulnerabilities = delete_empty_element(vulnerabilities)
    save_file(x_file_name + '_vulnerabilities.json', vulnerabilities)

    # 由于临时文件比较大，当硬盘空间不足时，则删除临时文件。
    # os.remove(x_file_name)
    # os.remove(file_timeflow)
    os.remove(file_count_function)
    
    result = {'sensitives': sensitives, 'vulnerabilities': vulnerabilities}
    return result
DynamicAnalyzer/views/android/android_virtualbox_vm.py
def refresh_vm(uuid, snapshot_uuid, vbox_exe):
    """Refresh VirtualBox based VMs"""
    print "\n[INFO] Refreshing MobSF VM"
    try:
        # Close VM
        args = [vbox_exe, 'controlvm', uuid, 'poweroff']
        subprocess.call(args)
        # changed by davidblus
        time.sleep(2)
        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")
DynamicAnalyzer/views/android/android_dyn_shared.py
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"
        result = subprocess.call([adb, "connect", get_identifier()])
        if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE" and result != 0:
            subprocess.call([adb, "tcpip", str(settings.DEVICE_ADB_PORT)])
            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:
        print traceback.format_exc()
        PrintException("[ERROR]  Connecting to VM/Device")
DynamicAnalyzer/views/android/android_avd.py
def refresh_avd(adb, avd_path, reference_name, dup_name, emulator):
    """Refresh AVD"""
    print "\n[INFO] Refreshing MobSF Emulator"
    try:
        # Stop existing emulator on the spesified port
        stop_avd(adb)

        # Windows has annoying lock system, it takes time for it to remove the locks after we stopped the emulator
        if platform.system() == 'Windows':
            time.sleep(3)

        # Delete old emulator
        delete_avd(avd_path, dup_name)

        # Copy and replace the contents of the reference machine
        duplicate_avd(avd_path, reference_name, dup_name)

        # Start emulator
        start_avd(emulator, dup_name, settings.AVD_ADB_PORT)
    except:
        PrintException("[ERROR] Refreshing MobSF VM")


Question: import os
import shutil
import MobSF.settings as SETTINGS
import json
import signal
import subprocess
import threading
import time
import traceback
from DynamicAnalyzer.pyWebProxy.pywebproxy import Proxy
from DynamicAnalyzer.views.android.android_avd import avd_load_wait
from DynamicAnalyzer.views.android.android_avd import refresh_avd
from DynamicAnalyzer.views.android.android_dyn_shared import connect
from DynamicAnalyzer.views.android.android_dyn_shared import install_and_run
from DynamicAnalyzer.views.android.android_dyn_shared import web_proxy
from DynamicAnalyzer.views.android.android_dyn_shared import get_identifier
from DynamicAnalyzer.views.android.android_virtualbox_vm import refresh_vm
from mass_static_analysis import genMD5
from MobSF.utils import getADB
from StaticAnalyzer.views.android.manifest_analysis import get_manifest
from StaticAnalyzer.views.android.manifest_analysis import manifest_data as get_manifest_data
from StaticAnalyzer.views.shared_func import Unzip
from Analysis_x_logcat.analysis import analysis_x_logcat
    captureDispatchPointer(0,0,1,{screen_x_middle},1200,1,1,-1,1,1,0,0)
    UserWait(1000)
    captureDispatchPress(4)
    captureDispatchPress(4)
    captureDispatchPress(4)
    '''
    drag_wait = 750
    packagename = app_info['packagename']
    mainactivity = app_info['mainactivity']
    if mainactivity.startswith('.'):
        mainactivity = packagename + mainactivity
    screen_x_right = 750
    screen_y_middle = 640
    screen_x_left = 50
    screen_x_middle = 400
    
    monkey_script_data = monkey_script_pattern.format(drag_wait=drag_wait, 
        packagename=packagename, mainactivity=mainactivity, 
        screen_x_right=screen_x_right, screen_y_middle=screen_y_middle, 
        screen_x_left=screen_x_left, screen_x_middle=screen_x_middle)
    
    monkey_script_file_name = os.path.join(os.path.join(UPLOAD_DIR, app_info['file_md5']), 'monkey_script.txt')
    with open(monkey_script_file_name, 'w') as f:
        f.write(monkey_script_data)
    
    subprocess.call([adb,
                     "-s",
                     get_identifier(),
                     "push",
                     monkey_script_file_name,
                     "/data/local/tmp"])
    subprocess.call([adb,
                     "-s",
                     get_identifier(),
                     "shell",
                     "monkey", "-f", 
                     "/data/local/tmp/monkey_script.txt", "1"])
    print u'\n[INFO] 跳过初始化界面'
    return

def auto_app_test(adb, app_info):
    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', '1000'], 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 download_logs(adb, download_dir):
    subprocess.call([adb,
                     "-s",
                     get_identifier(),
                     "pull",
                     "/data/data/de.robv.android.xposed.installer/log/error.log",
                     download_dir + "x_logcat_temp.txt"])
    print "\n[INFO] Downloading Droidmon API Monitor Logcat logs"
    # TODO: 下载其他有用文件
    return

Is_Downloading = True
def download_logs_thread(adb, download_dir):
    if not os.path.isdir(download_dir):
        os.makedirs(download_dir)
    global Is_Downloading
    while Is_Downloading:
        download_logs(adb, download_dir)
        log_path = os.path.join(download_dir, 'x_logcat.txt')
        log_temp_path = os.path.join(download_dir, 'x_logcat_temp.txt')
        if os.path.exists(log_path):
            log_size = os.path.getsize(log_path)
            log_temp_size = os.path.getsize(log_temp_path)
            if log_size < log_temp_size:
                shutil.copy(log_temp_path, log_path)
        else:
            shutil.copy(log_temp_path, log_path)
        os.remove(log_temp_path)
        time.sleep(10)
    return

# 运行该 apk 文件，获取运行时特征并存储在 '该文件路径' + '_info_/' 目录中，
# 因此调用该函数时需要先检查以上目录是否存在，如果存在则认为已经运行过该 apk 文件。
def dynamic_main(file_path):
    file_md5 = genMD5(file_path)
    print 'file_md5:', file_md5
    
    # download_dir = ORIGIN_DOWNLOAD_DIR + app_info['file_md5'] + '/'
    download_dir = file_path + '_info_/'
    
    try:
        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

Answer:         install_and_run(DYNAMIC_TOOL_DIR, app_info['apk_path'], app_info['packagename'], app_info['mainactivity'], True)