Created
October 3, 2024 03:31
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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