Skip to content

Instantly share code, notes, and snippets.

@bseibold
Last active October 13, 2016 10:53
Show Gist options
  • Save bseibold/3627015 to your computer and use it in GitHub Desktop.
Save bseibold/3627015 to your computer and use it in GitHub Desktop.
Read Uni Ulm Mifare Cards
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from sys import exit
import struct
try:
from smartcard.System import readers
from smartcard.util import toHexString
except:
print("Dieses Script benötigt python-pyscard")
exit(1)
KEYA = [
[0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5],
[0x46, 0x97, 0x19, 0x7c, 0xf3, 0xa2],
[0xbb, 0x85, 0x9d, 0xde, 0x23, 0x19],
[0xad, 0x7b, 0x45, 0x71, 0x9c, 0x69],
[0x51, 0xfd, 0x7a, 0xcc, 0x61, 0x88],
[0xad, 0x7b, 0x45, 0x71, 0x9c, 0x69],
[0xad, 0x7b, 0x45, 0x71, 0x9c, 0x69],
[0xad, 0x7b, 0x45, 0x71, 0x9c, 0x69],
[0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
[0x0b, 0x63, 0x0f, 0x85, 0x5c, 0xd1],
[0x94, 0x99, 0xd4, 0xa2, 0x29, 0x28],
[0x24, 0x83, 0x45, 0xd9, 0xe1, 0x56],
[0xa0, 0xc6, 0xef, 0xf5, 0x41, 0x29],
[0xa3, 0x05, 0x9e, 0xf3, 0x48, 0xe2],
[0x9f, 0xe8, 0x35, 0xe5, 0x04, 0xfe],
[0x72, 0xb3, 0xbd, 0xf3, 0x74, 0xab],
]
r = readers()[0]
c = r.createConnection()
c.connect()
last_auth_sector = -1
def decode_str(data):
#return ''.join([chr(x) for x in data]) # urgs, das muss doch schöner gehen
return str(bytearray(data))
def decode_valueblock(data):
v0, v1, v2, a0, a1, a2, a3 = [b for b in struct.unpack('<iiibbbb', decode_str(data))]
v1 = ~v1
a1 = ~a1
a3 = ~a3
if (v0 != v1 != v2):
raise ValueError
if (a0 != a1 != a2 != a3):
raise ValueError
return v0, a0
def decode_int(data):
return struct.unpack('<i', decode_str(data))
def read_block(nr):
global last_auth_sector
# load key if necessary
if (last_auth_sector != (nr/4)):
data, sw1, sw2 = c.transmit([0xFF, 0x82, 0x00, 0x60, 0x06] + KEYA[nr/4])
if [sw1, sw2] != [0x90, 0x00]:
raise IOError
last_auth_sector = nr/4
# authenticate. nicht nötig mit SCL011, aber vermutlich kompatibler
data, sw1, sw2 = c.transmit([0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, nr, 0x60, 0x01])
if [sw1, sw2] != [0x90, 0x00]:
raise IOError
# read block
data, sw1, sw2 = c.transmit([0xFF, 0xB0, 0x00, nr, 0x10])
if [sw1, sw2] != [0x90, 0x00]:
raise IOError
return data
b0_raw = read_block(0)
b4 = decode_str(read_block(4))
b5 = decode_str(read_block(5))
b6 = decode_str(read_block(6))
print('Mifare UID: 0x%02x%02x%02x%02x' % (b0_raw[0], b0_raw[1], b0_raw[2], b0_raw[3]))
print('Maktrikelnummer: %s' % b4[0:8])
print('Immatrikuliert bis: %s.%s.%s' % (b4[8:10],b4[10:12],b4[12:16]))
print('')
print('PIN-Hash: %s' % b5[0:6])
print('SuperPIN-Hash: %s' % b5[8:16])
print('Übrige Fehlversuche: %s' % b5[6:8])
print('')
ulub = decode_str(read_block(8))
bibd = decode_str(read_block(9))
print('Bibliotheksnummer: %s' % ulub)
print('Gültig bis: %s.%s.%s' % (bibd[0:2],bibd[2:4],bibd[4:8]))
print('')
m1 = 'ERROR'
m2 = 'ERROR'
try:
(mensa, a) = decode_valueblock(read_block(48))
m1 = '%.2f EUR' % (mensa/100.)
except ValueError:
m1 = 'INVALID'
except:
pass
try:
(mensa, a) = decode_valueblock(read_block(48))
m2 = '%.2f EUR' % (mensa/100.)
except ValueError:
m2 = 'INVALID'
except:
pass
print('Mensa-Guthaben (1): %s' % m1)
print('Mensa-Guthaben (2): %s' % m2)
print('')
print('')
print('---- Unbekannte Felder ----')
print('-- Sektor 1 --')
print('block 6: "%s"' % b6)
print('')
print('-- Sektor 3 --')
print('block 12: %s' % toHexString(read_block(12)))
print('block 13: "%s"' % decode_str(read_block(13)))
print('block 14: "%s"' % decode_str(read_block(14)))
print('')
print('-- Sektor 7 --')
print('block 28: %s' % toHexString(read_block(28)))
print('block 29: "%s"' % decode_str(read_block(29)))
print('')
print('-- Sektor 11 --')
print('block 44: %s' % toHexString(read_block(44)))
print('block 45: %s' % toHexString(read_block(45)))
print('block 46: %s' % toHexString(read_block(46)))
print('')
print('-- Sektor 13 --')
print('block 52: %s' % toHexString(read_block(52)))
print('block 53: %s' % toHexString(read_block(53)))
print('block 54: %s' % toHexString(read_block(54)))
print('')
print('-- Sektor 14 --')
print('block 56: %s' % toHexString(read_block(56)))
print('block 57: %s' % toHexString(read_block(57)))
print('block 58: %s' % toHexString(read_block(58)))
print('')
print('-- Sektor 15 --')
print('block 60: value: %d, adr: %d' % decode_valueblock(read_block(60)))
print('')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment