Exemplo n.º 1
0
def gather_permissions_labels():
    # FIXME: would probably put in global db?
    cmd = '{cli} shell getprop ro.product.model'
    model = catch_err(run_command(cmd, outf=MAP)).strip().replace(' ', '_')
    cmd = '{cli} shell pm list permissions -g -f > {outf}'
    #perms = catch_err(run_command(cmd, outf=model+'.permissions'))
    perms = catch_err(
        run_command(cmd, outf='static_data/android_permissions.txt'))
Exemplo n.º 2
0
 def setup(self):
     p = run_command('{cli} kill-server; {cli} start-server')
     if p != 0:
         print(">> Setup failed with returncode={}. ~~ ex={!r}".format(
             p.returncode,
             p.stderr.read() + p.stdout.read()),
               file=sys.stderr)
Exemplo n.º 3
0
    def isrooted(self, serial):
        '''
            Doesn't return all reasons by default. First match will return.
            TODO: make consistent with iOS isrooted, which returns all reasons discovered.
        '''

        cmd = "{cli} -s {serial} shell 'command -v su'"
        s = catch_err(run_command(cmd, serial=shlex.quote(serial)))
        if not s or s == -1 or 'not found' in s or len(s) == 0 or (
                s == "[android]: Error running ''. Error (1):"):
            print(config.error())
            reason = "couldn't find 'su' tool on the phone."
            return (False, reason)
        else:
            reason = "found '{}' tool on the phone. Verify whether this is a su binary.".format(
                s.strip())
            return (True, reason)

        installed_apps = self.installed_apps
        if not installed_apps:
            installed_apps = self.get_apps(serial)

        # FIXME: load these from a private database instead.  from OWASP,
        # https://sushi2k.gitbooks.io/the-owasp-mobile-security-testing-guide/content/0x05j-Testing-Resiliency-Against-Reverse-Engineering.html
        root_pkgs = ['com.noshufou.android.su','com.thirdparty.superuser',\
                'eu.chainfire.supersu', 'com.koushikdutta.superuser',\
                'com.zachspong.temprootremovejb' ,'com.ramdroid.appquarantine']
        root_pkgs_check = list(set(root_pkgs) & set(installed_apps))
        if root_pkgs_check:
            reason = "found the following app(s) on the phone: '{}'."\
                    .format(str(root_pkgs_check))
            return (True, reason)
Exemplo n.º 4
0
    def _dump_phone(self, serial):
        print('DUMPING iOS INFO...')
        # FIXME: pathlib migration at some point
        hmac_serial = config.hmac_serial(serial)
        cmd = "'{}/ios_dump.sh' {} {Apps} {Info} {Jailbroken-FS} {Jailbroken-SSH}"\
            .format(config.SCRIPT_DIR, hmac_serial, **config.IOS_DUMPFILES)
        print(cmd)
        path = self.dump_path(serial, fkind='Dir')
        # dumped = catch_err(run_command(cmd)).strip()
        dumpf = os.path.join(path, config.IOS_DUMPFILES['Apps'])
        dumpfinfo = os.path.join(path, config.IOS_DUMPFILES['Info'])

        #dumped = catch_err(run_command(cmd)).strip()
        dumped = catch_err(run_command(cmd)).strip()
        print('iOS DUMP RESULTS for {}:'.format(hmac_serial))
        print(dumped)
        if dumped == serial or True:
            print("Dumped the data into: {}".format(dumpf))
            self.parse_dump = parse_dump.IosDump(dumpf, finfo=dumpfinfo)
            return True
        else:
            print(
                "Couldn't connect to the device. Trying to reconnect. This way."
            )
            #connected, connected_reason = self.setup()
            #if not connected:
            #    print(connected_reason)
            return False
Exemplo n.º 5
0
 def uninstall(self, serial, appid):
     cmd = '{cli} -s {serial} uninstall {appid!r}'
     s = catch_err(run_command(cmd,
                               serial=shlex.quote(serial),
                               appid=shlex.quote(appid)),
                   cmd=cmd,
                   msg="Could not uninstall")
     return s != -1
Exemplo n.º 6
0
 def uninstall(self, serial, appid):
     #cmd = '{cli} -i {serial} --uninstall_only --bundle_id {appid!r}'
     #cmd = 'ideviceinstaller --udid {} --uninstall {appid!r}'.format(serial, appid)
     cmd = '{}ideviceinstaller --uninstall {appid!r}'.format(self.cli)
     s = catch_err(run_command(cmd, appid=appid),
                   cmd=cmd,
                   msg="Could not uninstall")
     return s != -1
Exemplo n.º 7
0
    def device_info(self, serial):
        m = {}
        cmd = '{cli} -s {serial} shell getprop ro.product.brand'
        m['brand'] = run_command(
            cmd, serial=serial).stdout.read().decode('utf-8').title()

        cmd = '{cli} -s {serial} shell getprop ro.product.model'
        m['model'] = run_command(cmd,
                                 serial=serial).stdout.read().decode('utf-8')

        cmd = '{cli} -s {serial} shell getprop ro.build.version.release'
        m['version'] = run_command(
            cmd, serial=serial).stdout.read().decode('utf-8').strip()

        cmd = '{cli} -s {serial} shell dumpsys batterystats | grep -i "Start clock time:" | head -n1'
        runcmd = catch_err(run_command(cmd, serial=serial), cmd=cmd)
        #m['last_full_charge'] = datetime.strptime(runcmd.split(':')[1].strip(), '%Y-%m-%d-%H-%M-%S')
        m['last_full_charge'] = datetime.now()
        return "{brand} {model} (running Android {version})".format(**m), m
Exemplo n.º 8
0
 def _get_apps_(self, serialno, flag):
     cmd = "{cli} -s {serial} shell pm list packages {flag} | sed 's/^package://g' | sort"
     s = catch_err(run_command(cmd, serial=serialno, flag=flag),
                   msg="App search failed",
                   cmd=cmd)
     if not s:
         self.setup()
         return []
     else:
         installed_apps = [x for x in s.splitlines() if x]
         return installed_apps
Exemplo n.º 9
0
 def get_apps(self, serialno):
     installed_apps = self._get_apps_(serialno, '-u')
     hmac_serial = config.hmac_serial(serialno)
     if installed_apps:
         q = run_command(
             'bash scripts/android_scan.sh scan {ser} {hmac_serial}',
             ser=serialno,
             hmac_serial=hmac_serial,
             nowait=True)
         self.installed_apps = installed_apps
     return installed_apps
Exemplo n.º 10
0
 def setup(self, attempt_remount=False):
     ''' FIXME: iOS setup. '''
     if config.PLATFORM == 'linux' and attempt_remount:
         # should show GUI prompt for password. sudo apt install policykit-1 if not there.
         cmd = "pkexec '" + config.SCRIPT_DIR + "/ios_mount_linux.sh' mount"
         #mountmsg = run_command(cmd).stderr.read().decode('utf-8')
         if catch_err(run_command(cmd)) == -1:
             return (False, "Couldn't detect device. See {}/ios_mount_linux.sh."\
                     .format(config.SCRIPT_DIR))
     cmd = '{}idevicepair pair'.format(self.cli)
     pairmsg = run_command(cmd).stdout.read().decode('utf-8')
     if "No device found, is it plugged in?" in pairmsg:
         return (False, pairmsg)
     elif "Please enter the passcode on the device and retry." in pairmsg:
         return (False, "Please unlock your device and follow the trust dialog"\
                 " (you will need to enter your passcode). Then try to scan again.")
     elif "SUCCESS: Paired with device" in pairmsg:
         return (True, "Device successfully paired. Setup complete.")
     elif "said that the user denied the trust dialog." in pairmsg:
         return (False, "The trust dialog was denied. Please unplug the device"\
                 ", reconnect it, and scan again -- accept the trust dialog to proceed.")
     return (True, "Follow trust dialog on iOS device to continue.")
Exemplo n.º 11
0
    def devices(self):
        def _is_device(x):
            """Is it looks like a serial number"""
            return re.match(r'[a-f0-9]+', x) is not None

        #cmd = '{cli} --detect -t1 | tail -n 1'
        cmd = '{}idevice_id -l | tail -n 1'.format(self.cli)
        self.serialno = None
        s = catch_err(run_command(cmd), cmd=cmd, msg="")
        d = [
            l.strip() for l in s.split('\n')
            if l.strip() and _is_device(l.strip())
        ]
        print("Devices found:", d)
        return d
Exemplo n.º 12
0
 def devices(self):
     # FIXME: check for errors related to err in runcmd.py.
     #cmd = '{cli} devices | tail -n +2 | cut -f2'
     #runcmd = catch_err(run_command(cmd), cmd=cmd).strip()
     #cmd = '{cli} kill-server; {cli} start-server'
     #s = catch_err(run_command(cmd), time=30, msg="ADB connection failed", cmd=cmd)
     cmd = '{cli} devices | tail -n +2'
     runcmd = catch_err(run_command(cmd), cmd=cmd).strip().split('\n')
     conn_devices = []
     for rc in runcmd:
         d = rc.split()
         if len(d) != 2: continue
         device, state = rc.split()
         device = device.strip()
         if state.strip() == 'device':
             conn_devices.append(device)
     return conn_devices
Exemplo n.º 13
0
def recent_permissions_used(appid):
    df = pd.DataFrame(
        columns=[
            'appId',
            'op',
            'mode',
            'timestamp',
            'time_ago',
            'duration'])
    cmd = '{cli} shell appops get {app}'
    recently_used = catch_err(run_command(cmd, app=appid))

    if 'No operations.' in recently_used:
        return df
    record = {'appId': appid}
    now = datetime.datetime.now()
    print(recently_used)
    for permission in recently_used.split('\n')[:-1]:
        permission_attrs = permission.split(';')
        record['op'] = permission_attrs[0].split(':')[0]
        record['mode'] = permission_attrs[0].split(':')[1].strip()

        if len(permission_attrs) == 2:
            record['timestamp'] = (
                now -
                _parse_time(
                    permission_attrs[1].split('=')[1].strip())).strftime(
                config.DATE_STR)

            # TODO: keep time_ago? that leaks when the consultation was.
            record['time_ago'] = permission_attrs[1].split('=')[1].strip()
        else:
            record['timestamp'] = 'unknown (op)'
            record['time_ago'] = 'unknown (op)'
            record['duration'] = 'unknown (op)'
            df.loc[df.shape[0]] = record
            continue

        # NOTE: can convert this with timestamp + _parse_time('duration')
        if len(permission_attrs) == 3:
            record['duration'] = permission_attrs[2].split('=')[1].strip()
        else:
            record['duration'] = 'unspecified'
        df.loc[df.shape[0]] = record
    return df.sort_values(by=['time_ago']).reset_index(drop=True)
Exemplo n.º 14
0
def recent_permissions_used(appid):
    cols = ['appId', 'op', 'mode', 'timestamp', 'time_ago', 'duration']
    df = pd.DataFrame([], columns=cols)
    cmd = '{cli} shell appops get {app}'
    recently_used = catch_err(run_command(cmd, app=appid))

    if 'No operations.' in recently_used:
        return df

    record = {'appId': appid}
    now = datetime.datetime.now()
    print(recently_used)
    for permission in recently_used.split('\n')[:-1]:
        permission_attrs = permission.split(';')
        t = permission_attrs[0].split(':')
        if len(t) != 2:  # Could not parse
            continue
        record = {c: '' for c in cols}
        record['op'] = t[0].strip()
        record['mode'] = t[1].strip()
        if len(permission_attrs) == 2:
            tt = permission_attrs[1].split('=')
            if len(tt) != 2:
                continue
            record['timestamp'] = (now - _parse_time(tt[1].strip()))\
                .strftime(config.DATE_STR)
            # TODO: keep time_ago? that leaks when the consultation was.
            record['time_ago'] = tt[1].strip()

        if len(permission_attrs) == 3:
            tt = permission_attrs[2].split('=')
            if len(tt) == 2:
                record['duration'] = tt[1].strip()

        df.loc[df.shape[0]] = record
    return df.sort_values(by=['time_ago']).reset_index(drop=True)
Exemplo n.º 15
0
DEVICE_PRIMARY_USER = {
    'me': 'Me',
    'child': 'A child of mine',
    'partner': 'My current partner/spouse',
    'family_other': 'Another family member',
    'other': 'Someone else'
}

ANDROID_PERMISSIONS_CSV = 'static_data/android_permissions.csv'
IOS_DUMPFILES = {'Jailbroken': 'ios_jailbroken.log',
                 'Apps': 'ios_apps.plist', 'Info': 'ios_info.xml'}

TEST_APP_LIST = 'static_data/android.test.apps_list'
#TITLE = "Anti-IPS: Stop Intimate Partner Surveillance"

VERSION_STABLE = catch_err(run_command(
    'git describe --abbrev=0 --tags')).strip()
VERSION_CURRENT = catch_err(run_command('git describe --tags')).strip()
TITLE = {'title': "Mobile Device Privacy Scanner{}".format(" (test)" if TEST else ''),
         'version_current': '',
         'version_stable': VERSION_STABLE}

APP_FLAGS_FILE = 'static_data/app-flags.csv'
APP_INFO_FILE = 'static_data/app-info.csv'
APP_INFO_SQLITE_FILE = 'sqlite:///static_data/app-info.db' + \
    ("~test" if TEST else "")
SQL_DB_PATH = 'sqlite:///data/fieldstudy.db' + ("~test" if TEST else "")


def set_test_mode(test):
    global TEST, APP_FLAGS_FILE, SQL_DB_PATH
    TEST = test
Exemplo n.º 16
0
def package_info(dumpf, appid):
    # FIXME: add check on all permissions, too.
    # need to get
    # requested permissions:
    # install permissions:
    # runtime permissions:
    cmd = "sed -n -e '/Package \[{appid}\]/,/Package \[/p' {dumpf}"\
        .format(appid=appid, dumpf=dumpf.replace('.json', '.txt'))
    print(cmd)
    # TODO: Need to udpate it once the catch_err function is fixed.
    package_dump = run_command(cmd).stdout.read().decode()

    # cmd = '{cli} shell dumpsys usagestats {app} | grep "App Standby States:" -A 1'\
    #     .format(cli=config.ADB_PATH, app=appid)
    # now = datetime.datetime.now()
    #usage_stats = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)\
    #        .stdout.read().decode('utf-8')#.strip()

    '''
     App Standby States:
        package=net.cybrook.trackview u=0 bucket=10 reason=u-mb used=+4m41s645ms usedScr=+2m19s198ms lastPred=+19d0h27m2s920ms activeLeft=+55m18s355ms wsLeft=-30d6h13m15s667ms lastJob=-24855d3h14m7s432ms idle=n

        totalElapsedTime=+305d6h7m59s376ms
        totalScreenOnTime=+67d8h56m19s585ms
    '''

    '''
    # switch to top method after tests
    package_dump = open(DUMPPKG, 'r').read()
    #print(package_dump)
    '''
    try:
        sp = simpleparse(package_dump)
    except AttributeError as e:
        print(package_dump)
        return []

    try:
        # FIXME: TypeError: list indices must be integers or slices, not str
        # FIXME: don't rely on rsonlite to parse correctly? Seems to miss the
        # Packages:.  for now, using sed to filter out potential hazards in
        # parsing output.
        if isinstance(sp, list):
            sp = sp[0]
        _, pkg = sp.popitem()
        if isinstance(pkg, list):
            pkg = pkg[0]
    except IndexError as e:
        print(e)
        print('Didn\'t parse correctly. Not sure why.')
        return [], {}
    print("pkg={}".format(json.dumps(pkg, indent=2)))
    install_perms = [k.split(':')[0] for k, v in
                     pkg.get('install permissions:', {}).items()]
    requested_perms = pkg.get('requested permissions:', [])

    #usage_stats = filter(None, usage_stats.split('\n')[1].split(' '))
    #usage_stats = dict(item.split('=') for item in usage_stats)
    # print(usage_stats)
    pkg_info = {}
    pkg_info['firstInstallTime'] = pkg.get('firstInstallTime', '')
    pkg_info['lastUpdateTime'] = pkg.get('lastUpdateTime', '')
    pkg_info['versionCode'] = pkg.get('versionCode', '')
    pkg_info['versionName'] = pkg.get('versionName', '')
    #pkg_info['used'] = now - _parse_time(usage_stats['used'])
    #pkg_info['usedScr'] = now - _parse_time(usage_stats['usedScr'])

    #('User 0:  installed', 'true hidden=false stopped=false notLaunched=false enabled=0\nlastDisabledCaller: com.android.vending\ngids=[3003]\nruntime permissions:')
    #inst_det_key = [v for k,v in pkg.items() if 'User 0:' in k][0]
    #install_details = dict(item.split('=') for item in inst_det_key.strip().split(' ')[1:])
    #install_details = {k:bool(strtobool(install_details[k])) for k in install_details}
    # print(install_details)

    all_perms = list(set(requested_perms) | set(install_perms))

    return all_perms, pkg_info
Exemplo n.º 17
0
 def devices_info(self):
     cmd = '{cli} devices -l'
     return run_command(cmd).stdout.read().decode('utf-8')