예제 #1
0
파일: ios.py 프로젝트: timb-machine/mat
    def __init__(self, utils, app=None, ipa=None):
        Log.w('Creating Analysis for: {app} / {ipa}'.format(app=app, ipa=ipa))

        self.UTILS    = utils
        self.IPA      = ipa
        self.APP      = app
        self.PREPARED = self.prepare_analysis()
예제 #2
0
    def run_static_analysis(self):
        issues = []
        import mat.modules.android.static
        static_checks = [
            m.replace('.py', '')
            for m in listdir(mat.modules.android.static.__path__[0])
            if not m.endswith('.pyc') and not m.startswith('__')
        ]
        for check in static_checks:
            Log.d('Running Static {check}'.format(check=check))
            check_module = __import__(
                'mat.modules.android.static.{check}'.format(check=check),
                fromlist=['Issue'])

            issue = check_module.Issue(self)
            if issue.dependencies():
                issue.run()
            else:
                Log.e('Error: Dependencies not met.')
            if issue.REPORT:
                issues += [issue]

        issues += self._run_custom_static_analysis()

        return issues
예제 #3
0
    def clean_analysis(self):
        Log.w('Cleaning Android Analysis')

        if settings.uninstall:
            self.UTILS.ADB.uninstall(self.PACKAGE)

        if settings.clean:
            Utils.rmtree(self.LOCAL_WORKING_FOLDER)
예제 #4
0
    def prepare_analysis(self):
        Log.w('Getting latest cordova versions')

        import urllib2
        response = urllib2.urlopen(CordovaAnalysis.LATEST_VERSION_URL)
        html = response.read()
        for os in CordovaAnalysis.LATEST_VERSION:
            self.LATEST_VERSION[os] = html.split(
                '-{os}-'.format(os=os))[1].rsplit('.', 1)[0]
예제 #5
0
    def __init__(self, utils, apk=None, package=None):
        Log.w('Creating Analysis for: {app} / {apk}'.format(apk=apk,
                                                            app=package))

        self.UTILS = utils
        self.WORKING_APK_FILE = apk
        self.PACKAGE = package
        self.PREPARED = self.prepare_analysis()

        self.REMOTE_DATA_FOLDER = self.UTILS.data_path(self.PACKAGE)
        self.REMOTE_APP_FOLDER = self.UTILS.app_path(self.PACKAGE)
예제 #6
0
파일: ios.py 프로젝트: timb-machine/mat
    def _run_custom_modules(self, module_type):
        issues = []
        modules = self.get_custom_modules([module_type])
        for m in modules:
            Log.d('Running Static {check}'.format(check=m.__name__))
            issue = m.Issue(self)
            if issue.dependencies():
                issue.run()
            else:
                Log.e('Error: Dependencies not met.')
            if issue.REPORT:
                issues += [issue]

        return issues
예제 #7
0
    def run_analysis(self):
        Log.w('Starting Analysis.')
        self.prepare_analysis()

        if not self.CONFIG_FILE and not self.CORDOVA_FILE:
            Log.w('No cordova files found.')
            return []

        issues = []

        import mat.modules.cordova.static
        static_checks = [
            m.replace('.py', '')
            for m in listdir(mat.modules.cordova.static.__path__[0])
            if not m.endswith('.pyc') and not m.startswith('__')
        ]
        for check in static_checks:
            Log.d('Running Static {check}'.format(check=check))
            check_module = __import__(
                'mat.modules.cordova.static.{check}'.format(check=check),
                fromlist=['Issue'])

            issue = check_module.Issue(self)
            if issue.dependencies():
                issue.run()
            else:
                Log.e('Error: Dependencies not met.')
            if issue.REPORT:
                issues += [issue]

        issues += self._run_custom_static_analysis()

        return issues
예제 #8
0
    def run_dynamic_analysis(self):
        if not self.UTILS.ADB.unlocked(settings.device):
            Log.w('Please unlock the device')
        while not self.UTILS.ADB.unlocked(settings.device):
            sleep(5)

        # launch the app
        self.UTILS.launch_app(self.PACKAGE)

        issues = []
        import mat.modules.android.dynamic
        dynamic_checks = [
            m.replace('.py', '')
            for m in listdir(mat.modules.android.dynamic.__path__[0])
            if not m.endswith('.pyc') and not m.startswith('__')
        ]
        for check in dynamic_checks:
            Log.d('Running Dynamic {check}'.format(check=check))
            check_module = __import__(
                'mat.modules.android.dynamic.{check}'.format(check=check),
                fromlist=['Issue'])

            issue = check_module.Issue(self)
            if issue.dependencies():
                issue.run()
            else:
                Log.e('Error: Dependencies not met.')
            if issue.REPORT:
                issues += [issue]

        issues += self._run_custom_dynamic_analysis()

        return issues
예제 #9
0
파일: ios.py 프로젝트: timb-machine/mat
    def run_dynamic_analysis(self):
        # launch the app
        self.UTILS.launch_app(self.APP_INFO)

        issues = []
        import mat.modules.ios.dynamic
        dynamic_checks = [m.replace('.py', '') for m in listdir(mat.modules.ios.dynamic.__path__[0]) if not m.endswith('.pyc') and not m.startswith('__')]
        for check in dynamic_checks:
            Log.d('Running Dynamic {check}'.format(check=check))
            check_module = __import__('mat.modules.ios.dynamic.{check}'.format(check=check), fromlist=['Issue'])

            issue = check_module.Issue(self)
            if issue.dependencies():
                issue.run()
            else:
                Log.e('Error: Dependencies not met.')
            if issue.REPORT:
                issues += [issue]

        issues += self._run_custom_dynamic_analysis()

        return issues
예제 #10
0
    def __init__(self,
                 root=None,
                 data=None,
                 atype=None,
                 config=None,
                 cordova=None):

        self.ASSESSMENT_TYPE = atype
        self.ROOT = root
        self.CONFIG_FILE = config
        self.CORDOVA_FILE = cordova

        if self.ROOT and not self.CONFIG_FILE:
            for location in CordovaAnalysis.LOCATIONS['config']:
                if path.exists('{root}/{loc}'.format(root=self.ROOT,
                                                     loc=location)):
                    self.CONFIG_FILE = '{root}/{loc}'.format(root=self.ROOT,
                                                             loc=location)
                    break

        if self.ROOT and not self.CORDOVA_FILE:
            for location in CordovaAnalysis.LOCATIONS['cordova']:
                if path.exists('{root}/{loc}'.format(root=self.ROOT,
                                                     loc=location)):
                    self.CORDOVA_FILE = '{root}/{loc}'.format(root=self.ROOT,
                                                              loc=location)
                    break

        if not self.CORDOVA_FILE and data:
            self.CORDOVA_FILE = Utils.run(
                'find {data} -name cordova.js'.format(
                    data=data))[0].split('\n')[0].strip()

        if not self.CONFIG_FILE and self.ROOT:
            self.CONFIG_FILE = Utils.run('find {root} -name config.xml'.format(
                root=self.ROOT))[0].split('\n')[0].strip()

        Log.d('Root: {fpath}'.format(fpath=self.ROOT))
        Log.d('cordova.js: {fpath}'.format(fpath=self.CORDOVA_FILE))
        Log.d('config.xml: {fpath}'.format(fpath=self.CONFIG_FILE))
예제 #11
0
파일: ios.py 프로젝트: timb-machine/mat
    def prepare_analysis(self):
        Log.w('Preparing iOS Analysis')

        if not self.UTILS.check_dependencies(['full'], install=True, silent=True):
            Log.e('Error: Required dependencies not met')

        # create local output folder
        Log.d('Creating local output folders')
        self.LOCAL_WORKING_FOLDER = '{output}/{work}-{uuid}'.format(output=settings.output, work=self.LOCAL_WORKING_FOLDER, uuid=(self.APP or self.IPA.rsplit('/',1)[-1].rsplit('.',1)[0]))
        self.LOCAL_DATA_CONTENT   = '{main}/{data}'.format(main=self.LOCAL_WORKING_FOLDER, data=self.LOCAL_DATA_CONTENT)
        self.LOCAL_BIN_FOLDER     = '{main}/{data}'.format(main=self.LOCAL_WORKING_FOLDER, data=self.LOCAL_BIN_FOLDER)
        self.LOCAL_CLASS_DUMP     = '{main}/{data}'.format(main=self.LOCAL_WORKING_FOLDER, data=self.LOCAL_CLASS_DUMP)
        self.LOCAL_UNZIPED        = '{main}/{data}'.format(main=self.LOCAL_WORKING_FOLDER, data=self.LOCAL_UNZIPED)

        local_paths = ['LOCAL_WORKING_FOLDER', 'LOCAL_DATA_CONTENT', 'LOCAL_BIN_FOLDER', 'LOCAL_CLASS_DUMP']
        for local_path in local_paths:
            if not path.exists(getattr(self, local_path)):
                makedirs(getattr(self, local_path))

        if self.UTILS.check_dependencies(['connection'], silent=True):
            # create a temp folder to work with
            Log.d('Creating iOS Working folders')
            self.UTILS.run_on_ios('mkdir {working}'.format(working=self.IOS_WORKING_FOLDER))
            self.UTILS.run_on_ios('chmod 777 {working}'.format(working=self.IOS_WORKING_FOLDER))

            # push tools to the temp folder
            self.UTILS.push(settings.dump_log, self.IOS_WORKING_FOLDER)
            self.UTILS.push(settings.dump_fileprot, self.IOS_WORKING_FOLDER)
            self.UTILS.push(settings.dump_decrypt, self.IOS_WORKING_FOLDER)
            self.UTILS.push(settings.keychain_dump, self.IOS_WORKING_FOLDER)
            self.UTILS.push(settings.backup_excluded, self.IOS_WORKING_FOLDER)

            # update binary paths
            self.UTILS.DUMP_DECRYPT      = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=settings.dump_decrypt.rsplit('/', 1)[1])
            self.UTILS.KEYCHAIN_DUMP     = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=settings.keychain_dump.rsplit('/', 1)[1])
            self.UTILS.DUMP_FILE_PROTECT = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=settings.dump_fileprot.rsplit('/', 1)[1])
            self.UTILS.DUMP_LOG          = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=settings.dump_log.rsplit('/', 1)[1])
            self.UTILS.BACKUP_EXCLUDED   = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=settings.backup_excluded.rsplit('/', 1)[1])

        if self.APP: # no need to check if there's connection - it will return None if there's no connection
            apps = self.UTILS.list_apps(silent=True)
            self.APP = apps[self.APP] if self.APP in apps else None
            if not self.APP:
                Log.e("Error: The ID specified was not found in the applications list.")
                return False

        if self.IPA:
            self.LOCAL_IPA = '{binaries}/{ipa}'.format(binaries=self.LOCAL_BIN_FOLDER, ipa=self.IPA.rsplit('/', 1)[-1])
            Utils.run('cp {original} {dest}'.format(original=self.IPA, dest=self.LOCAL_IPA))

            if self.UTILS.check_dependencies(['connection'], silent=True):
                self.APP = self.UTILS.install(self.LOCAL_IPA)
                if not self.APP:
                    Log.e('Error: Couldn\'t install the app or retreive its details')
                    return False

        if not self.IPA:
            self.APP_INFO = self.UTILS.get_info(self.APP_INFO['Path'], ios=True)
            self.LOCAL_WORKING_BIN, self.LOCAL_IPA = self.UTILS.pull_ipa(self.APP, self.APP_INFO, self.LOCAL_BIN_FOLDER)

        if self.LOCAL_IPA:
            UNZIPED_APP, self.APP_INFO = self.UTILS.unzip_to(self.LOCAL_IPA, self.LOCAL_UNZIPED)
            if not hasattr(self, 'LOCAL_WORKING_BIN'):
                self.LOCAL_WORKING_BIN = '{app}/{binary}'.format(app=UNZIPED_APP, binary=self.APP_INFO['CFBundleExecutable'])

        # copy working bin to the device:
        if not hasattr(self, 'LOCAL_WORKING_BIN') and self.UTILS.check_dependencies(['connection'], silent=True):
            self.IOS_WORKING_BIN = '{working}/{binary}'.format(working=self.IOS_WORKING_FOLDER, binary=self.APP_INFO['CFBundleExecutable'])
            self.UTILS.push(self.LOCAL_WORKING_BIN, self.IOS_WORKING_FOLDER)

        if self.APP and 'Container' in self.APP:
            self.IOS_DATA_PATH = self.APP['Container'].replace(' ', '\ ')

        if self.APP and self.APP_INFO:
            self.IOS_BIN_PATH = self.UTILS.app_executable(self.APP, self.APP_INFO)

        self.LOCAL_CLASS_DUMP = '{base}/{app}'.format(base=self.LOCAL_CLASS_DUMP, app=self.APP_INFO['CFBundleExecutable'])

        # get classes
        ########################## TESTING #####################################
        if not path.exists(self.LOCAL_CLASS_DUMP): makedirs(self.LOCAL_CLASS_DUMP)
        self.UTILS.dump_classes_to_file(self.UTILS.dump_classes(self.LOCAL_WORKING_BIN), self.LOCAL_CLASS_DUMP)
        ########################## END     #####################################

        return True #and self.UTILS.check_dependencies(['full'], install=False, silent=True)
예제 #12
0
파일: ios.py 프로젝트: timb-machine/mat
    def run_analysis(self, analysis_type='full'):
        if not self.PREPARED:
            Log.e('Error: Analysis not prepared')
            return []

        Log.w("Starting iOS Analysis")
        ### checks start here
        if self.UTILS.check_dependencies(['static'], silent=True, install=False):
            issues = self.run_static_analysis()

        if analysis_type != 'static' and self.UTILS.check_dependencies(['dynamic'], silent=True, install=False):
            issues += self.run_dynamic_analysis()

            ### get data from device
            Log.d('Getting data from device')
            self.UTILS.pull(self.IOS_DATA_PATH, self.LOCAL_DATA_CONTENT)

        issues += self.run_cordova_checks()

        # calculate and save md5
        md5 = Utils.run('{md5sum} {ipa}'.format(md5sum=settings.md5sum, ipa=self.LOCAL_IPA))[0]
        with open('{working}/{ipa}.md5'.format(working=self.LOCAL_BIN_FOLDER, ipa=self.IPA.rsplit('/', 1)[-1]), 'w') as f:
            f.write(md5.split(' ', 1)[0].strip())

        # print app information
        Log.w('******************** Application Info ********************')
        Log.w('Application: {app}'.format(app=self.APP_INFO['CFBundleName']))
        Log.w('Version    : {version}'.format(version=self.APP_INFO['CFBundleShortVersionString']))
        Log.w('Binary     : {binary}'.format(binary= self.APP_INFO['CFBundleExecutable']))
        Log.w('MD5        : {md5}'.format(md5=md5.strip().split('\n')[0]))
        Log.w('********************     End Info     ********************')

        self.clean_analysis()
        return issues
예제 #13
0
    def prepare_analysis(self, decompile=True):
        Log.w('Preparing Android Analysis')

        if not self.UTILS.check_dependencies(
            ['static', 'dynamic'], install=True, silent=True):
            Log.e('Error: Not all ependencies met, run `-r` for more details')

        # Creates local folders to store the analysis data
        self.LOCAL_WORKING_FOLDER = '{output}/{work}-{uuid}'.format(
            output=settings.output,
            work=AndroidAnalysis.LOCAL_WORKING_FOLDER,
            uuid=(self.PACKAGE or self.WORKING_APK_FILE.rsplit(
                '/', 1)[-1].rsplit('.', 1)[0]))
        self.LOCAL_DATA_CONTENT = '{main}/{data}'.format(
            main=self.LOCAL_WORKING_FOLDER,
            data=AndroidAnalysis.LOCAL_DATA_CONTENT)
        self.LOCAL_DECOMPILED_APP = '{main}/{data}'.format(
            main=self.LOCAL_WORKING_FOLDER,
            data=AndroidAnalysis.LOCAL_DECOMPILED_APP)
        self.LOCAL_SOURCE = '{main}/{data}'.format(
            main=self.LOCAL_WORKING_FOLDER, data=AndroidAnalysis.LOCAL_SOURCE)
        local_paths = [
            'LOCAL_WORKING_FOLDER', 'LOCAL_DATA_CONTENT',
            'LOCAL_DECOMPILED_APP', 'LOCAL_SOURCE'
        ]
        for local_path in local_paths:
            if not path.exists(getattr(self, local_path)):
                makedirs(getattr(self, local_path))

        if self.WORKING_APK_FILE:
            original = self.WORKING_APK_FILE
            self.WORKING_APK_FILE = '{working}/{apk}'.format(
                working=self.LOCAL_WORKING_FOLDER,
                apk=self.WORKING_APK_FILE.rsplit('/', 1)[-1])
            Utils.run('cp {oapk} {apk}'.format(oapk=original,
                                               apk=self.WORKING_APK_FILE))

            if self.UTILS.device():
                Log.w('Installing application')
                self.UTILS.install(self.WORKING_APK_FILE)

        elif self.PACKAGE:
            device_apk = self.UTILS.get_apk(self.PACKAGE)
            if not device_apk:
                Log.e('Error: Package not found on the device')
                return False

            self.WORKING_APK_FILE = '{working}/{package}.apk'.format(
                working=self.LOCAL_WORKING_FOLDER, package=self.PACKAGE)
            self.UTILS.pull(device_apk, self.WORKING_APK_FILE)

        if not self.WORKING_APK_FILE or not path.exists(self.WORKING_APK_FILE):
            Log.e('Error: Local APK file not found.')
            return False

        # decompile apk
        if decompile:
            Log.w('Decompiling {apk} to {dir}'.format(
                apk=self.WORKING_APK_FILE, dir=self.LOCAL_DECOMPILED_APP))
            Utils.run('{apktool} -q d -f {apk} -o {out}'.format(
                apktool=settings.apktool,
                apk=self.WORKING_APK_FILE,
                out=self.LOCAL_DECOMPILED_APP))

        self.MANIFEST = Manifest(self.LOCAL_DECOMPILED_APP,
                                 settings.apkfilename)
        self.PACKAGE = self.MANIFEST.package
        self.JAR_FILE = '{working}/{package}.jar'.format(
            working=self.LOCAL_WORKING_FOLDER, package=self.PACKAGE)
        self.LOCAL_SMALI = '{decompiled}/smali'.format(
            decompiled=self.LOCAL_DECOMPILED_APP)

        if decompile:
            Log.w('Converting {apk} classes to {jar}'.format(
                apk=self.WORKING_APK_FILE, jar=self.JAR_FILE))
            Utils.run('{dex2jar} --force -o {jar} {apk}'.format(
                dex2jar=settings.dex2jar,
                apk=self.WORKING_APK_FILE,
                jar=self.JAR_FILE))

            Log.d('Extrating java classes from {jar} to {src}'.format(
                src=self.LOCAL_SOURCE, jar=self.JAR_FILE))
            Utils.run('{jdcli} {jar} -od {src}'.format(jdcli=settings.jdcli,
                                                       src=self.LOCAL_SOURCE,
                                                       jar=self.JAR_FILE))

        return True
예제 #14
0
    def run_analysis(self, analysis_type='full'):
        if not self.PREPARED:
            Log.e('Error: Analysis not prepared')
            return []

        issues = []

        Log.w('Starting Android Analysis')
        if self.UTILS.check_dependencies(['static'],
                                         silent=True,
                                         install=False):
            issues = self.run_static_analysis()
            issues += self.run_cordova_analysis()

        if analysis_type != 'static' and self.UTILS.check_dependencies(
            ['dynamic'], silent=True, install=False):
            Log.w('Starting Dynamic Analysis')
            issues += self.run_dynamic_analysis()

        # calculate and save md5
        md5 = Utils.run('{md5sum} {working}'.format(
            md5sum=settings.md5sum, working=self.WORKING_APK_FILE))[0]
        with open('{working}.md5'.format(working=self.WORKING_APK_FILE),
                  'w') as f:
            f.write(md5.split(' ', 1)[0].strip())

        # print app information
        Log.w('******************** Application Info ********************')
        Log.w('Package: {app}'.format(app=self.PACKAGE))
        Log.w('Version: {version}'.format(version=self.MANIFEST.version))
        Log.w('APK    : {binary}'.format(binary=self.WORKING_APK_FILE))
        Log.w('MD5    : {md5}'.format(md5=md5.strip().split('\n')[0]))
        Log.w('********************     End Info     ********************')

        self.clean_analysis()
        return issues
예제 #15
0
    def run(self):
        Log.w('Checking emulator detection (this may take a while)')
        if self.ANALYSIS.UTILS.check_dependencies(['avd'], install=True):
            # get devices
            devices = self.ANALYSIS.UTILS.devices()

            # start emulator
            sleep(2)
            process = Utils.emulator()
            Log.w('Waiting for emulator to start')
            sleep(30)

            if self.ANALYSIS.UTILS.CREATED_AVD:
                Log.w(
                    'AVD just created, allowing 3 more minutes before proceeding'
                )
                sleep(180)

            # diff devices -> get emulator
            emulator = list(set(self.ANALYSIS.UTILS.devices()) - set(devices))

            if len(emulator) == 1:
                emulator = emulator[0]
                Log.w('Waiting for {emulator}'.format(emulator=emulator))
                while not self.ANALYSIS.UTILS.online(emulator):
                    sleep(5)

                if not self.ANALYSIS.UTILS.unlocked(emulator):
                    Log.w('Please unlock the emulator')
                while not self.ANALYSIS.UTILS.unlocked(emulator):
                    sleep(5)

                # install and run the apk in emulator
                self.ANALYSIS.UTILS.install_on(emulator,
                                               self.ANALYSIS.WORKING_APK_FILE)
                self.ANALYSIS.UTILS.launch_app(device=emulator,
                                               package=self.ANALYSIS.PACKAGE)

                Log.w('Launching the app on the emulator')
                sleep(10)

                # check if app in ps
                if self.ANALYSIS.PACKAGE in self.ANALYSIS.UTILS.processes(
                        emulator, root=False):
                    self.REPORT = True

            else:
                Log.e(
                    'More than one new device detected - emulator checks not performed'
                )

            # terminate emulator
            process.kill()

        Log.d('Checking for code that references to emulator checks')
        self.DETAILS = ''
        result = Utils.grep_command(
            '-arin -e "generic.*Build\.FINGERPRINT" -e "Build\.FINGERPRINT.*generic -e "sdk.*Build\.PRODUCT" -e "Build\.PRODUCT.*sdk" -e "Secure\.ANDROID_ID" -e "getSensorList" {src}'
            .format(src=self.ANALYSIS.LOCAL_SOURCE),
            self.ANALYSIS.LOCAL_SOURCE)
        if result:
            self.DETAILS += Utils.grep_details(result,
                                               self.ANALYSIS.LOCAL_SOURCE)
            self.REPORT = True