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()
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)
def decision(): client = DebugLink(get_device().find_debug()) client.open() time.sleep(SLEEP) client.press_yes() # time.sleep(SLEEP) client.close()
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()
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()
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()
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
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()
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()
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()
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))
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()
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()
def set_debuglink(self, debug_transport): self.debug = DebugLink(debug_transport)
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")
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")
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()
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()
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()
def input(value: str) -> None: client = DebugLink(get_device().find_debug()) client.open() time.sleep(SLEEP) client.input(value) client.close()
def press_no() -> None: client = DebugLink(get_device().find_debug()) client.open() time.sleep(SLEEP) client.press_no() client.close()
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()
def click(x: int, y: int) -> None: client = DebugLink(get_device().find_debug()) client.open() time.sleep(SLEEP) client.click((x, y)) client.close()
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()