Skip to content

Instantly share code, notes, and snippets.

@iwalton3
Created October 3, 2024 03:31
Show Gist options
  • Save iwalton3/d68089355e6808b1492be98fc6df6711 to your computer and use it in GitHub Desktop.
Save iwalton3/d68089355e6808b1492be98fc6df6711 to your computer and use it in GitHub Desktop.
Example usage of pyscard to read and write second sector of xSiiD with password protection turned on.
#!/usr/bin/env python3
from smartcard.System import readers
from smartcard.CardRequest import CardRequest
from smartcard.Exceptions import CardRequestTimeoutException, CardConnectionException
import time
reader = readers()
conn = reader[0].createConnection()
accepted_cards = {
# card id(s) goes here
b'\x00\x00\x00\x00\x00\x00\x00'
}
class CardError(Exception):
def __init__(self, data):
self.data = data
def __repr__(self):
return f"CardError: Failed with data: {self.data}"
def send_data(conn, data, expected_code=0):
try:
payload = [0xFF, 0x00, 0x00, 0x00, len(data) + 2, 0xD4, 0x42] + data
data, sw1, sw2 = conn.transmit(payload)
if sw1 != 0x90 or sw2 != 0:
raise Exception(f"Failed with code: {sw1} {sw2}")
if data[0] == 213 and data[1] == 67 and data[2] == expected_code:
return data[3:]
else:
raise CardError(data)
except CardConnectionException as ex:
if str(ex) != "Card returned no valid response: Command successful. (0x00000000)":
raise
return None
while True:
cardrequest = CardRequest(timeout=1)
try:
cardrequest.waitforcard()
conn.connect()
result, sw1, sw2 = conn.transmit([0xFF, 0xCA, 0x00, 0x00, 0x00])
if bytes(result) in accepted_cards:
print("Accepted card detected.")
else:
continue
try:
# last 4 bytes in command are password
pwack = send_data(conn, [0x1B, 0x00, 0x00, 0x00, 0x00])
# two bytes here are pwack, which is only given with right password
if bytes(pwack) != b'\x00\x00':
print("Invalid PW ACK, could be tamper attempt.")
break
except CardError as ex:
if ex.data[2] == 1:
print("Password auth interrupted.")
continue
print("Password auth failed, could be tamper attempt.")
break
# select sector 2
send_data(conn, [0xC2, 0xFF], expected_code=2)
send_data(conn, [0x01, 0x00, 0x00, 0x00], expected_code=1)
# to write data
#send_data(conn, [0xA2, 0] + list(bytearray.fromhex("00000000")), expected_code=2)
#send_data(conn, [0xA2, 1] + list(bytearray.fromhex("00000000")), expected_code=2)
#send_data(conn, [0xA2, 2] + list(bytearray.fromhex("00000000")), expected_code=2)
#send_data(conn, [0xA2, 3] + list(bytearray.fromhex("00000000")), expected_code=2)
# read k, which is first 16 bytes of sector 2
k = bytes(send_data(conn, [0x30, 0]))
# do something with k
time.sleep(5)
except CardRequestTimeoutException:
pass
except Exception as ex:
import traceback
traceback.print_exc()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment