예제 #1
0
def main():
    # List all connected TREZORs on USB
    devices = HidTransport.enumerate()

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = devices[0]
    debug_transport = devices[0].find_debug()

    # Creates object for manipulating TREZOR
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    arg1 = int(sys.argv[1], 16)
    arg2 = int(sys.argv[2], 16)
    step = 0x400 if arg2 >= 0x400 else arg2

    f = open('memory.dat', 'wb')

    for addr in range(arg1, arg1 + arg2, step):
        mem = debug.memory_read(addr, step)
        f.write(mem)

    f.close()

    client.close()
예제 #2
0
def find_debug():
    for device in enumerate_devices():
        try:
            debug_transport = device.find_debug()
            debug = DebugLink(debug_transport, auto_interact=False)
            debug.open()
            return debug
        except Exception:
            continue
    else:
        print("No suitable Trezor device found")
        sys.exit(1)
예제 #3
0
def find_debug():
    for device in enumerate_devices():
        try:
            debug_transport = device.find_debug()
            debug = DebugLink(debug_transport, auto_interact=False)
            debug.open()
            return debug
        except Exception:
            continue
    else:
        print("No suitable Trezor device found")
        sys.exit(1)
예제 #4
0
def decision():
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.press_yes()
    # time.sleep(SLEEP)
    client.close()
예제 #5
0
def main():
    # List all connected TREZORs on USB
    devices = HidTransport.enumerate()

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = HidTransport(devices[0])

    # Creates object for manipulating TREZOR
    debug_transport = HidTransport(devices[0], **{'debug_link': True})
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    mem = debug.memory_write(int(sys.argv[1],16), binascii.unhexlify(sys.argv[2]), flash=True)
    client.close()
예제 #6
0
def main():
    # List all connected TREZORs on USB
    devices = HidTransport.enumerate()

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = devices[0]
    debug_transport = devices[0].find_debug()

    # Creates object for manipulating TREZOR
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    debug.memory_write(int(sys.argv[1], 16), binascii.unhexlify(sys.argv[2]), flash=True)
    client.close()
예제 #7
0
def main():
    # List all debuggable TREZORs
    devices = [device for device in enumerate_devices() if hasattr(device, 'find_debug')]

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = devices[0]
    debug_transport = devices[0].find_debug()

    # Creates object for manipulating TREZOR
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    sector = int(sys.argv[1])
    f = open(sys.argv[2], "rb")
    content = f.read(sectorlens[sector])
    if (len(content) != sectorlens[sector]):
        print("Not enough bytes in file")
        return

    debug.flash_erase(sector)
    step = 0x400
    for offset in range(0, sectorlens[sector], step):
        debug.memory_write(sectoraddrs[sector] + offset, content[offset:offset + step], flash=True)
    client.close()
예제 #8
0
    def enter_shares_with_restarts(debug: DebugLink) -> None:
        shares = MNEMONIC_SLIP39_ADVANCED_20
        layout = debug.read_layout()
        expected_text = "Enter any share"
        remaining = len(shares)
        for share in shares:
            assert expected_text in layout.text
            layout = recovery.enter_share(debug, share)
            remaining -= 1
            expected_text = "Success You have entered"
            debug = _restart(device_handler, emulator)

        assert "You have successfully recovered your wallet" in layout.text
예제 #9
0
def main():
    # List all connected TREZORs on USB
    devices = HidTransport.enumerate()

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = HidTransport(devices[0])

    # Creates object for manipulating TREZOR
    debug_transport = HidTransport(devices[0], **{'debug_link': True})
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    mem = debug.memory_read(int(sys.argv[1],16), int(sys.argv[2],16))
    f = open('memory.dat', 'w')
    f.write(mem)
    f.close()

    client.close()
예제 #10
0
def main():
    # List all connected TREZORs on USB
    devices = HidTransport.enumerate()

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = HidTransport(devices[0])

    # Creates object for manipulating TREZOR
    debug_transport = HidTransport(devices[0], **{'debug_link': True})
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    mem = debug.memory_read(int(sys.argv[1], 16), int(sys.argv[2], 16))
    f = open('memory.dat', 'w')
    f.write(mem)
    f.close()

    client.close()
예제 #11
0
def main():
    # List all debuggable TREZORs
    devices = [
        device for device in enumerate_devices()
        if hasattr(device, 'find_debug')
    ]

    # Check whether we found any
    if len(devices) == 0:
        print('No TREZOR found')
        return

    # Use first connected device
    transport = devices[0]
    debug_transport = devices[0].find_debug()

    # Creates object for manipulating TREZOR
    client = TrezorClient(transport)
    debug = DebugLink(debug_transport)

    debug.memory_write(int(sys.argv[1], 16),
                       bytes.fromhex(sys.argv[2]),
                       flash=True)
    client.close()
예제 #12
0
def start(
    version: str,
    wipe: bool,
    output_to_logfile: bool = True,
    save_screenshots: bool = False,
) -> None:
    global version_running
    global EMULATOR

    if EMULATOR is not None:
        log(
            f"Before starting a new emulator - version {version}, "
            f"killing the already running one - version {version_running}",
            "red",
        )
        stop()

    # Conditionally redirecting the output to a logfile instead of terminal/stdout
    if output_to_logfile:
        logfile = open(helpers.EMU_BRIDGE_LOG, "a")
    else:
        logfile = sys.stdout

    if version[0] == "2":
        EMULATOR = CoreEmulator(
            FIRMWARE_DIR / f"trezor-emu-core-v{version}",
            profile_dir=FIRMWARE_DIR,
            logfile=logfile,
        )
    elif version[0] == "1":
        os.environ["TREZOR_OLED_SCALE"] = str(TREZOR_ONE_OLED_SCALE)
        EMULATOR = LegacyEmulator(
            FIRMWARE_DIR / f"trezor-emu-legacy-v{version}",
            profile_dir=FIRMWARE_DIR,
            logfile=logfile,
        )
    else:
        raise RuntimeError("Version can start only with 1 or 2")

    if wipe and EMULATOR.storage.exists():
        EMULATOR.storage.unlink()

    EMULATOR.start()

    version_running = version

    # Optionally saving the screenshots on any screen-change, so we can send the
    # current screen on demand
    # Only applicable to TT, T1 is not capable of screenshotting
    if save_screenshots and version[0] == "2":
        time.sleep(1)
        client = DebugLink(get_device().find_debug())
        client.open()
        client.start_recording(str(SCREEN_DIR))
예제 #13
0
def swipe(direction):
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    if direction == 'up':
        client.swipe_up()
    elif direction == 'right':
        client.swipe_right()
    elif direction == 'down':
        client.swipe_down()
    elif direction == 'left':
        client.swipe_left()
    client.close()
예제 #14
0
def read_and_confirm_mnemonic():
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.press_yes()
    time.sleep(SLEEP)

    # it appears that doing read_mnemonic_secret also skips otherwise necessary "swiping"
    mnem = client.read_mnemonic_secret().decode("utf-8")
    mnemonic = mnem.split()
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    client.press_yes()
    client.press_yes()
    client.close()
예제 #15
0
 def set_debuglink(self, debug_transport):
     self.debug = DebugLink(debug_transport)
예제 #16
0
class DebugLinkMixin(object):
    # This class implements automatic responses
    # and other functionality for unit tests
    # for various callbacks, created in order
    # to automatically pass unit tests.
    #
    # This mixing should be used only for purposes
    # of unit testing, because it will fail to work
    # without special DebugLink interface provided
    # by the device.

    def __init__(self, *args, **kwargs):
        super(DebugLinkMixin, self).__init__(*args, **kwargs)
        self.debug = None
        self.in_with_statement = 0
        self.button_wait = 0
        self.screenshot_id = 0

        # Always press Yes and provide correct pin
        self.setup_debuglink(True, True)

        # Do not expect any specific response from device
        self.expected_responses = None

        # Use blank passphrase
        self.set_passphrase('')

    def close(self):
        super(DebugLinkMixin, self).close()
        if self.debug:
            self.debug.close()

    def set_debuglink(self, debug_transport):
        self.debug = DebugLink(debug_transport)

    def set_buttonwait(self, secs):
        self.button_wait = secs

    def __enter__(self):
        # For usage in with/expected_responses
        self.in_with_statement += 1
        return self

    def __exit__(self, _type, value, traceback):
        self.in_with_statement -= 1

        if _type != None:
            # Another exception raised
            return False

        # return isinstance(value, TypeError)
        # Evaluate missed responses in 'with' statement
        if self.expected_responses != None and len(self.expected_responses):
            raise Exception("Some of expected responses didn't come from device: %s" % \
                    [ pprint(x) for x in self.expected_responses ])

        # Cleanup
        self.expected_responses = None
        return False

    def set_expected_responses(self, expected):
        if not self.in_with_statement:
            raise Exception("Must be called inside 'with' statement")
        self.expected_responses = expected

    def setup_debuglink(self, button, pin_correct):
        self.button = button  # True -> YES button, False -> NO button
        self.pin_correct = pin_correct

    def set_passphrase(self, passphrase):
        self.passphrase = unicode(
            str(bytearray(Mnemonic.normalize_string(passphrase), 'utf-8')),
            'utf-8')

    def set_mnemonic(self, mnemonic):
        self.mnemonic = unicode(
            str(bytearray(Mnemonic.normalize_string(mnemonic), 'utf-8')),
            'utf-8').split(' ')

    def call_raw(self, msg):

        if SCREENSHOT and self.debug:
            layout = self.debug.read_layout()
            im = Image.new("RGB", (128, 64))
            pix = im.load()
            for x in range(128):
                for y in range(64):
                    rx, ry = 127 - x, 63 - y
                    if (ord(layout[rx + (ry / 8) * 128]) & (1 <<
                                                            (ry % 8))) > 0:
                        pix[x, y] = (255, 255, 255)
            im.save('scr%05d.png' % self.screenshot_id)
            self.screenshot_id += 1

        resp = super(DebugLinkMixin, self).call_raw(msg)
        self._check_request(resp)
        return resp

    def _check_request(self, msg):
        if self.expected_responses != None:
            try:
                expected = self.expected_responses.pop(0)
            except IndexError:
                raise CallException(
                    types.Failure_Other,
                    "Got %s, but no message has been expected" % pprint(msg))

            if msg.__class__ != expected.__class__:
                raise CallException(
                    types.Failure_Other,
                    "Expected %s, got %s" % (pprint(expected), pprint(msg)))

            fields = expected.ListFields(
            )  # only filled (including extensions)
            for field, value in fields:
                if not msg.HasField(
                        field.name) or getattr(msg, field.name) != value:
                    raise CallException(
                        types.Failure_Other, "Expected %s, got %s" %
                        (pprint(expected), pprint(msg)))

    def callback_ButtonRequest(self, msg):
        log("ButtonRequest code: " + get_buttonrequest_value(msg.code))

        log("Pressing button " + str(self.button))
        if self.button_wait:
            log("Waiting %d seconds " % self.button_wait)
            time.sleep(self.button_wait)
        self.debug.press_button(self.button)
        return proto.ButtonAck()

    def callback_PinMatrixRequest(self, msg):
        if self.pin_correct:
            pin = self.debug.read_pin_encoded()
        else:
            pin = '444222'
        return proto.PinMatrixAck(pin=pin)

    def callback_PassphraseRequest(self, msg):
        log("Provided passphrase: '%s'" % self.passphrase)
        return proto.PassphraseAck(passphrase=self.passphrase)

    def callback_WordRequest(self, msg):
        (word, pos) = self.debug.read_recovery_word()
        if word != '':
            return proto.WordAck(word=word)
        if pos != 0:
            return proto.WordAck(word=self.mnemonic[pos - 1])

        raise Exception("Unexpected call")
예제 #17
0
 def set_debuglink(self, debug_transport):
     self.debug = DebugLink(debug_transport)
예제 #18
0
class DebugLinkMixin(object):
    # This class implements automatic responses
    # and other functionality for unit tests
    # for various callbacks, created in order
    # to automatically pass unit tests.
    #
    # This mixing should be used only for purposes
    # of unit testing, because it will fail to work
    # without special DebugLink interface provided
    # by the device.

    def __init__(self, *args, **kwargs):
        super(DebugLinkMixin, self).__init__(*args, **kwargs)
        self.debug = None
        self.in_with_statement = 0

        # Always press Yes and provide correct pin
        self.setup_debuglink(True, True)
        
        # Do not expect any specific response from device
        self.expected_responses = None

        # Use blank passphrase
        self.set_passphrase('')

    def close(self):
        super(DebugLinkMixin, self).close()
        if self.debug:
            self.debug.close()

    def set_debuglink(self, debug_transport):
        self.debug = DebugLink(debug_transport)

    def __enter__(self):
        # For usage in with/expected_responses
        self.in_with_statement += 1
        return self

    def __exit__(self, _type, value, traceback):
        self.in_with_statement -= 1

        if _type != None:
            # Another exception raised
            return False

        # return isinstance(value, TypeError)
        # Evaluate missed responses in 'with' statement
        if self.expected_responses != None and len(self.expected_responses):
            raise Exception("Some of expected responses didn't come from device: %s" % \
                    [ pprint(x) for x in self.expected_responses ])

        # Cleanup
        self.expected_responses = None
        return False

    def set_expected_responses(self, expected):
        if not self.in_with_statement:
            raise Exception("Must be called inside 'with' statement")
        self.expected_responses = expected

    def setup_debuglink(self, button, pin_correct):
        self.button = button  # True -> YES button, False -> NO button
        self.pin_correct = pin_correct

    def set_passphrase(self, passphrase):
        self.passphrase = unicode(str(bytearray(Mnemonic.normalize_string(passphrase), 'utf-8')), 'utf-8')

    def set_mnemonic(self, mnemonic):
        self.mnemonic = unicode(str(bytearray(Mnemonic.normalize_string(mnemonic), 'utf-8')), 'utf-8').split(' ')

    def call_raw(self, msg):
        resp = super(DebugLinkMixin, self).call_raw(msg)
        self._check_request(resp)
        return resp
        
    def _check_request(self, msg):
        if self.expected_responses != None:
            try:
                expected = self.expected_responses.pop(0)
            except IndexError:
                raise CallException(types.Failure_Other,
                        "Got %s, but no message has been expected" % pprint(msg))

            if msg.__class__ != expected.__class__:
                raise CallException(types.Failure_Other,
                            "Expected %s, got %s" % (pprint(expected), pprint(msg)))

            fields = expected.ListFields()  # only filled (including extensions)
            for field, value in fields:
                if not msg.HasField(field.name) or getattr(msg, field.name) != value:
                    raise CallException(types.Failure_Other,
                            "Expected %s, got %s" % (pprint(expected), pprint(msg)))
            
    def callback_ButtonRequest(self, msg):
        log("ButtonRequest code: " + get_buttonrequest_value(msg.code))

        log("Pressing button " + str(self.button))
        self.debug.press_button(self.button)
        return proto.ButtonAck()

    def callback_PinMatrixRequest(self, msg):
        if self.pin_correct:
            pin = self.debug.read_pin_encoded()
        else:
            pin = '444222'
        return proto.PinMatrixAck(pin=pin)

    def callback_PassphraseRequest(self, msg):
        log("Provided passphrase: '%s'" % self.passphrase)
        return proto.PassphraseAck(passphrase=self.passphrase)

    def callback_WordRequest(self, msg):
        (word, pos) = self.debug.read_recovery_word()
        if word != '':
            return proto.WordAck(word=word)
        if pos != 0:
            return proto.WordAck(word=self.mnemonic[pos - 1])

        raise Exception("Unexpected call")
예제 #19
0
def read_and_confirm_shamir_mnemonic(shares: int = 1, threshold: int = 1) -> None:
    """Performs a walkthrough of the whole Shamir backup on the device.

    NOTE: does not support Super Shamir.
    """
    MIN_SHARES = 1
    MAX_SHARES = 16
    if shares < MIN_SHARES or shares > MAX_SHARES:
        raise RuntimeError(
            f"Number of shares must be between {MIN_SHARES} and {MAX_SHARES}."
        )
    if threshold > shares:
        raise RuntimeError("Threshold cannot be bigger than number of shares.")

    # For setting the right amount of shares/thresholds, we need location of buttons
    MINUS_BUTTON_COORDS = (60, 70)
    PLUS_BUTTON_COORDS = (180, 70)

    # Connecting to the device
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)

    # Click Continue to begin Shamir setup process
    client.press_yes()
    time.sleep(SLEEP)

    # Clicking the minus/plus button to set right number of shares (it starts at 5)
    DEFAULT_SHARES = 5
    needed_clicks = abs(shares - DEFAULT_SHARES)
    if needed_clicks > 0:
        if shares < DEFAULT_SHARES:
            button_coords_to_click = MINUS_BUTTON_COORDS
        else:
            button_coords_to_click = PLUS_BUTTON_COORDS

        for _ in range(needed_clicks):
            client.click(button_coords_to_click)
            time.sleep(SLEEP)

    # Click Continue to confirm the number of shares
    client.press_yes()
    time.sleep(SLEEP)

    # Click Continue to set threshold
    client.press_yes()
    time.sleep(SLEEP)

    # When we have 1 or 2 shares, the threshold is set and cannot be changed
    # (it will be 1 and 2 respectively)
    # Otherise assign it correctly by clicking the plus/minus button
    if shares not in [1, 2]:
        # Default threshold can be calculated from the share number
        default_threshold = shares // 2 + 1
        needed_clicks = abs(threshold - default_threshold)
        if needed_clicks > 0:
            if threshold < default_threshold:
                button_coords_to_click = MINUS_BUTTON_COORDS
            else:
                button_coords_to_click = PLUS_BUTTON_COORDS

            for _ in range(needed_clicks):
                client.click(button_coords_to_click)
                time.sleep(SLEEP)

    # Click Continue to confirm our chosen threshold
    client.press_yes()
    time.sleep(SLEEP)

    # Click Continue to continue
    client.press_yes()
    time.sleep(SLEEP)

    # Click I understand
    client.press_yes()
    time.sleep(SLEEP)

    # Loop through all the shares and fulfill all checks
    for _ in range(shares):
        # Scrolling through all the 20 words on next 5 pages
        # While doing so, saving all the words on the screen for the "quiz" later
        mnemonic = []
        for _ in range(5):
            mnemonic.extend(client.read_reset_word().split())
            client.swipe_up()
            time.sleep(SLEEP)

        mnemonic.extend(client.read_reset_word().split())
        assert len(mnemonic) == 20

        # Confirming that I have written the seed down
        client.press_yes()
        time.sleep(SLEEP)

        # Answering 3 questions asking for a specific word
        for _ in range(3):
            index = client.read_reset_word_pos()
            client.input(mnemonic[index])
            time.sleep(SLEEP)

        # Click Continue to finish this quiz
        client.press_yes()
        time.sleep(SLEEP)

    # Click Continue to finish the backup
    client.press_yes()
    time.sleep(SLEEP)

    client.close()
예제 #20
0
def read_and_confirm_mnemonic() -> None:
    # Connecting to the device
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)

    # Clicking continue button
    client.press_yes()
    time.sleep(SLEEP)

    # Scrolling through all the 12 words on next three pages
    for _ in range(3):
        client.swipe_up()
        time.sleep(SLEEP)

    # Confirming that I have written the seed down
    client.press_yes()
    time.sleep(SLEEP)

    # Retrieving the seed words for next "quiz"
    mnem = client.state().mnemonic_secret.decode("utf-8")
    mnemonic = mnem.split()
    time.sleep(SLEEP)

    # Answering 3 questions asking for a specific word
    for _ in range(3):
        index = client.read_reset_word_pos()
        client.input(mnemonic[index])
        time.sleep(SLEEP)

    # Click Continue to finish the quiz
    client.press_yes()
    time.sleep(SLEEP)

    # Click Continue to finish the backup
    client.press_yes()
    time.sleep(SLEEP)

    client.close()
예제 #21
0
def swipe(direction: str) -> None:
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    if direction == "up":
        client.swipe_up()
    elif direction == "right":
        client.swipe_right()
    elif direction == "down":
        client.swipe_down()
    elif direction == "left":
        client.swipe_left()
    client.close()
예제 #22
0
def input(value: str) -> None:
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.input(value)
    client.close()
예제 #23
0
def press_no() -> None:
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.press_no()
    client.close()
예제 #24
0
def read_and_confirm_mnemonic():
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)

    client.press_yes()
    time.sleep(SLEEP)

    mnem = client.state().mnemonic_secret.decode("utf-8")
    mnemonic = mnem.split()
    time.sleep(SLEEP)

    client.swipe_up()
    time.sleep(SLEEP)

    client.swipe_up()
    time.sleep(SLEEP)

    client.swipe_up()
    time.sleep(SLEEP)

    client.press_yes()
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    index = client.read_reset_word_pos()
    client.input(mnemonic[index])
    time.sleep(SLEEP)

    client.press_yes()
    client.press_yes()
    client.close()
예제 #25
0
def click(x: int, y: int) -> None:
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.click((x, y))
    client.close()
예제 #26
0
def select_num_of_words(num_of_words: int = 12) -> None:
    client = DebugLink(get_device().find_debug())
    client.open()
    time.sleep(SLEEP)
    client.input(str(num_of_words))
    client.close()