Ejemplo n.º 1
0
def find_devices(ctx, buses):
    results = []
    for bus in buses:
        log.note('Probing bus {:d}'.format(bus))
        try:

            cmd = 'i2c dev {:d}'.format(bus)
            # Raise an exception on error via check=True
            resp = ctx.send_command(cmd, check=True)

            # This may fail for buses (or pinmux settings) that are configured
            # appropriately. Thus, we drop check=True and just look results
            resp = ctx.send_command('i2c probe')

            match = re.match(r'Valid chip addresses: ([0-9a-fA-F\t ]+)', resp)
            if not match:
                # A failing bus will spew failures for a while. Keep trying
                # to interrupt it (Ctrl-C) until we know we're back at a prompt.
                log.warning('No devices or bus failing. Waiting for prompt.')
                ctx.interrupt(timeout=120)
                continue

            for addr in match.group(1).split():
                addr = int(addr, 16)
                log.info('Found device: Bus={:d}, Address=0x{:02x}'.format(
                    bus, addr))
                results.append((bus, addr))

        except OperationFailed as error:
            log.error('Command failed: ' + cmd + os.linesep + str(error))

    return results
Ejemplo n.º 2
0
def run_test(ctx, reader, writer, address, data, stratagem):
    # Just to avoid triggering our warning to users
    wr_data = data if stratagem is None else None

    if not isinstance(reader, DataAbortMemoryReader):
        ctx.write_memory(address, wr_data, impl=writer, stratagem=stratagem)
    else:
        _da_read_pre_info['writer'] = writer
        _da_read_pre_info['data'] = data
        _da_read_pre_info['address'] = address

    data_read = ctx.read_memory(address, len(data), impl=reader)

    if data != data_read:
        now = round(time.time())
        wfile = '{}.{}.bin'.format(writer.name, now)
        rfile = '{}.{}.bin'.format(reader.name, now)

        msg  = 'Test case failed. Saving written and readback data to:' + linesep
        msg += '      {} and {}'.format(wfile, rfile)
        log.error(msg)

        fail_dir = create_resource_dir('memory_test', 'failure')
        filename = os.path.join(fail_dir, wfile)

        with open(filename, 'wb') as outfile:
            outfile.write(data)

        filename = os.path.join(fail_dir, rfile)
        with open(filename, 'wb') as outfile:
            outfile.write(data_read)

        return 'Fail'

    return 'Pass'
Ejemplo n.º 3
0
def perform_unlock_bypass(ctx):
    if is_unlocked(ctx):
        log.info("Device is already using 'unlocked' command table.")
        return True

    if not is_vulnerable(ctx):
        log.error('Device does not appear to be vulnerable.')
        return False

    ctx.patch_memory(_patch_list, impl='i2c')
    success = is_unlocked(ctx)
    if success:
        log.info("Success! Device is now using 'unlocked' command table.")
    else:
        log.error("Failed to switch to 'unlocked' command table.")

    return success
Ejemplo n.º 4
0
def is_vulnerable(ctx):
    """
    Attempt to check if target is vulnerable to i2c-based unlock bypass,
    based upon the Sonos-provided (i.e. not the U-Boot) version number.
    """
    ver_regex = re.compile(
        r'U-Boot \d{4}\.\d{2}-Royale(-Strict)?-Rev(?P<rev>\d{1,}\.\d{1,})\s')
    for info in ctx.version():
        log.debug('Checking version string: ' + info)
        m = ver_regex.match(info)
        if m is not None:
            ver = float(m.group('rev'))
            if ver == 0.2:
                log.info('Vulnerable version detected: ' + info)
                return True

            if ver <= 0.3:
                msg = 'Version may be vulnerable, but our memory patches are specific to v0.2'
                log.error(msg)
            else:
                log.error('Patched or unknown version detected: ' + info)
            return False

    log.error('Did not detect "U-Boot Royale" version string.')
    return False
Ejemplo n.º 5
0
#!/usr/bin/env python3
import traceback
from depthcharge import Console, Depthcharge, log

ctx = None

try:
    console = Console('/dev/ttyUSB0', baudrate=115200)
    ctx = Depthcharge.load('my_device.cfg', console)

    # Comment out the above ctx creation and uncomment the following one in
    # order to possibly make more operations available to Depthcharge by allowing
    # it to deploy executable payloads to RAM and reboot/crash the platform.
    #ctx = Depthcharge(console, allow_deploy=True, allow_reboot=True)

    # Perform actions here

except Exception as error:
    log.error(str(error))

    # Shown if DEPTHCHARGE_LOG_LEVEL=debug in environment
    log.debug(traceback.format_exc())

finally:
    # Save any updates or new information to the device config
    if ctx:
        ctx.save('my_device.cfg')
Ejemplo n.º 6
0
        sim_memory[dst_off:dst_off + 4] = state.to_bytes(4, sys.byteorder)

        # Remaining iterations are performed in-place on the intermediate
        # result located in the destination memory location
        for i in range(1, iterations):
            state = crc32(sim_memory[dst_off:dst_off + 4])
            sim_memory[dst_off:dst_off + 4] = state.to_bytes(4, sys.byteorder)


if __name__ == '__main__':
    hunter = ReverseCRC32Hunter(THE_RAVEN, 0x0000_0000, revlut_maxlen=1024)
    stratagem = hunter.build_stratagem(TARGET_PAYLOAD, max_iterations=16384)

    filename = 'raven-stratagem.json'
    stratagem.to_json_file(filename)
    log.info('Saved stratagem to ' + filename)

    # Here's a good spot to set a breakpoint and inspect `stratagem`
    # breakpoint()

    # Simulate a memory space to write into
    sim_memory = bytearray(len(TARGET_PAYLOAD))

    execute_stratagem(stratagem, sim_memory)

    if sim_memory == TARGET_PAYLOAD:
        log.info('Result:\n' + sim_memory.decode('ascii'))
    else:
        log.error('Produced result does not match desired target payload!')
        # breakpoint()