Example #1
0
def reboot_bootloader():
    """Reboots the device to the bootloader.
    """
    log.info('Rebooting %s to bootloader' % context.device)

    with Client() as c:
        c.reboot_bootloader()
Example #2
0
def read(path, target=None, callback=None):
    """Download a file from the device, and extract its contents.

    Arguments:
        path(str): Path to the file on the device.
        target(str): Optional, location to store the file.
            Uses a temporary file by default.
        callback(callable): See the documentation for
            ``adb.protocol.Client.read``.

    Examples:

        >>> print adb.read('/proc/version') # doctest: +ELLIPSIS
        Linux version ...
        >>> adb.read('/does/not/exist')
        Traceback (most recent call last):
        ...
        PwnlibException: Could not stat '/does/not/exist'
    """
    with Client() as c:
        stat = c.stat(path)
        if not stat:
            log.error('Could not stat %r' % path)
        data = c.read(path, stat['size'], callback=callback)

    if target:
        misc.write(target, data)

    return data
Example #3
0
def wait_for_device(kick=False):
    """Waits for a device to be connected.

    By default, waits for the currently-selected device (via ``context.device``).
    To wait for a specific device, set ``context.device``.
    To wait for *any* device, clear ``context.device``.

    Return:
        An ``AdbDevice`` instance for the device.

    Examples:

        >>> device = adb.wait_for_device()
    """
    with log.waitfor("Waiting for device to come online") as w:
        with Client() as c:
            if kick:
                try:
                    c.reconnect()
                except Exception:
                    pass

            serial = ''
            if context.device:
                serial = str(context.device)

        with Client() as c:
            c.wait_for_device(serial)

        for device in devices():
            if context.device == device:
                return device

            if not serial:
                break
        else:
            log.error("Could not find any devices")

        with context.local(device=device):
            # There may be multiple devices, so context.device is
            # insufficient.  Pick the first device reported.
            w.success('%s (%s %s %s)' %
                      (device, product(), build(), _build_date()))

            return context.device
Example #4
0
def unlock_bootloader():
    """Unlocks the bootloader of the device.

    Note:
        This requires physical interaction with the device.
    """
    Client().reboot_bootloader()
    fastboot(['oem', 'unlock'])
    fastboot(['continue'])
Example #5
0
def reboot(wait=True):
    """Reboots the device.
    """
    log.info('Rebooting device %s' % context.device)

    with Client() as c:
        c.reboot()

    if wait:
        wait_for_device()
Example #6
0
def remount():
    """Remounts the filesystem as writable."""
    with log.waitfor("Remounting filesystem on %s" % context.device) as w:
        disable_verity()
        root()

        with Client() as c:
            reply = c.remount()

        if 'remount succeeded' not in reply:
            log.error("Could not remount filesystem:\n%s" % reply)
Example #7
0
def walk(top, topdown=True):
    join = os.path.join
    isdir = lambda x: stat.S_ISDIR(x['mode'])
    client = Client()
    names = client.list(top)

    dirs, nondirs = [], []
    for name, metadata in names.items():
        if isdir(metadata):
            dirs.append(name)
        else:
            nondirs.append(name)

    if topdown:
        yield top, dirs, nondirs
    for name in dirs:
        new_path = join(top, name)
        for x in walk(new_path, topdown):
            yield x
    if not topdown:
        yield top, dirs, nondirs
Example #8
0
def listdir(directory='/'):
    """Returns a list containing the entries in the provided directory.

    Note:
        This uses the SYNC LIST functionality, which runs in the adbd
        SELinux context.  If adbd is running in the su domain ('adb root'),
        this behaves as expected.

        Otherwise, less files may be returned due to restrictive SELinux
        policies on adbd.
    """
    return list(sorted(Client().list(directory)))
Example #9
0
def unroot():
    """Restarts adbd as AID_SHELL."""
    log.info("Unrooting %s" % context.device)
    with context.quiet:
        with Client() as c:
            reply = c.unroot()

    if '0006closed' == reply:
        return  # Emulator doesnt care

    if 'restarting adbd as non root' not in reply:
        log.error("Could not unroot:\n%s" % reply)
Example #10
0
def exists(path):
    """Return :const:`True` if ``path`` exists on the target device.

    Examples:

        >>> adb.exists('/')
        True
        >>> adb.exists('/init')
        True
        >>> adb.exists('/does/not/exist')
        False
    """
    with Client() as c:
        return bool(c.stat(path))
Example #11
0
def isdir(path):
    """Return :const:`True` if ``path`` is a on the target device.

    Examples:

        >>> adb.isdir('/')
        True
        >>> adb.isdir('/init')
        False
        >>> adb.isdir('/does/not/exist')
        False
    """
    with Client() as c:
        st = c.stat(path)
        return bool(st and stat.S_ISDIR(st['mode']))
Example #12
0
def push(local_path, remote_path):
    """Upload a file to the device.

    Arguments:
        local_path(str): Path to the local file to push.
        remote_path(str): Path or directory to store the file on the device.

    Example:

        >>> write('./filename', 'contents')
        >>> _=adb.push('./filename', '/data/local/tmp')
        >>> adb.read('/data/local/tmp/filename')
        'contents'
        >>> adb.push('./filename', '/does/not/exist')
        Traceback (most recent call last):
        ...
        PwnlibException: Could not stat '/does/not/exist'
    """
    msg = "Pushing %r to %r" % (local_path, remote_path)
    remote_filename = os.path.basename(local_path)

    if log.isEnabledFor(logging.DEBUG):
        msg += ' (%s)' % context.device

    with log.waitfor(msg) as w:
        with Client() as c:

            # We need to discover whether remote_path is a directory or not.
            # If we cannot stat the full path, assume it's a path-plus-filename,
            # where the filename does not exist.
            stat_ = c.stat(remote_path)
            if not stat_:
                remote_filename = os.path.basename(remote_path)
                remote_path = os.path.dirname(remote_path)
                stat_ = c.stat(remote_path)

            # If we can't find the exact path, or its parent directory, bail!
            if not stat_:
                log.error('Could not stat %r' % remote_path)

            # If we found the parent directory, append the filename
            mode = stat_['mode']
            if stat.S_ISDIR(mode):
                remote_path = os.path.join(remote_path, remote_filename)

            return c.write(remote_path,
                           misc.read(local_path),
                           callback=_create_adb_push_pull_callback(w))
Example #13
0
def devices(serial=None):
    """Returns a list of ``Device`` objects corresponding to the connected devices."""
    with Client() as c:
        lines = c.devices(long=True)
    result = []

    for line in lines.splitlines():
        # Skip the first 'List of devices attached' line, and the final empty line.
        if 'List of devices' in line or not line.strip():
            continue
        device = AdbDevice.from_adb_output(line)
        if device.serial == serial:
            return device
        result.append(device)

    return tuple(result)
Example #14
0
def disable_verity():
    """Disables dm-verity on the device."""
    with log.waitfor("Disabling dm-verity on %s" % context.device) as w:
        root()

        with Client() as c:
            reply = c.disable_verity()

        if 'Verity already disabled' in reply:
            return
        elif 'Now reboot your device' in reply:
            reboot(wait=True)
        elif '0006closed' in reply:
            return  # Emulator doesnt support Verity?
        else:
            log.error("Could not disable verity:\n%s" % reply)
Example #15
0
def unlink(path, recursive=False):
    """Unlinks a file or directory on the target device.

    Examples:

        >>> adb.unlink("/does/not/exist")
        Traceback (most recent call last):
        ...
        PwnlibException: Could not unlink '/does/not/exist': Does not exist

        >>> filename = '/data/local/tmp/unlink-test'
        >>> adb.write(filename, 'hello')
        >>> adb.exists(filename)
        True
        >>> adb.unlink(filename)
        >>> adb.exists(filename)
        False

        >>> adb.mkdir(filename)
        >>> adb.write(filename + '/contents', 'hello')
        >>> adb.unlink(filename)
        Traceback (most recent call last):
        ...
        PwnlibException: Cannot delete non-empty directory '/data/local/tmp/unlink-test' without recursive=True

        >>> adb.unlink(filename, recursive=True)
        >>> adb.exists(filename)
        False
    """
    with Client() as c:
        st = c.stat(path)
        if not st:
            log.error("Could not unlink %r: Does not exist" % path)

        # If the directory is not empty, do not delete it
        if isdir(path) and c.list(path) and not recursive:
            log.error(
                "Cannot delete non-empty directory %r without recursive=True" %
                path)

        flags = '-rf' if recursive else '-r'

        output = c.execute(['rm', flags, path]).recvall()

        if output:
            log.error(output)
Example #16
0
def root():
    """Restarts adbd as root.

    >>> adb.root()
    """
    log.info("Enabling root on %s" % context.device)

    with context.quiet:
        with Client() as c:
            reply = c.root()

    if 'already running as root' in reply:
        return

    elif not reply or 'restarting adbd as root' in reply:
        with context.quiet:
            wait_for_device()

    else:
        log.error("Could not run as root:\n%s" % reply)
Example #17
0
def mkdir(path):
    """Create a directory on the target device.

    Note:
        Silently succeeds if the directory already exists.

    Arguments:
        path(str): Directory to create.

    Examples:

        >>> adb.mkdir('/')

        >>> path = '/data/local/tmp/mkdir_test'
        >>> adb.exists(path)
        False
        >>> adb.mkdir(path)
        >>> adb.exists(path)
        True

        >>> adb.mkdir('/init')
        Traceback (most recent call last):
        ...
        PwnlibException: mkdir failed for /init, File exists
    """
    if not path.startswith('/'):
        log.error("Must provide an absolute path: %r" % path)

    with Client() as c:
        st = c.stat(path)

        # Don't re-create existing directories
        if st and stat.S_ISDIR(st['mode']):
            return

        result = process(['mkdir', path]).recvall()

        # Any output at all is an error
        if result:
            log.error(result)
Example #18
0
def process(argv, *a, **kw):
    """Execute a process on the device.

    See :class:`pwnlib.tubes.process.process` documentation for more info.

    Returns:
        A :class:`pwnlib.tubes.process.process` tube.

    Examples:

        >>> adb.root()
        >>> print adb.process(['cat','/proc/version']).recvall() # doctest: +ELLIPSIS
        Linux version ...
    """
    if isinstance(argv, (str, unicode)):
        argv = [argv]

    message = "Starting %s process %r" % ('Android', argv[0])

    if log.isEnabledFor(logging.DEBUG):
        if argv != [argv[0]]: message += ' argv=%r ' % argv

    with log.progress(message) as p:
        return Client().execute(argv)