mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
Add basic ISO14443 log data parser for Reader side traffic
Can parse: SELECT, HALE, RATS, PPS, DESELECT (cherry picked from commit aa46598)
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import binascii
|
||||
|
||||
ReaderTrafficTypes = {
|
||||
"SEL":{
|
||||
0x93: "SEL_CL1 ",
|
||||
0x95: "SEL_CL2 ",
|
||||
0x97: "SEL_CL3 ",
|
||||
},
|
||||
# 1 byte commands
|
||||
"SHORTFRAME": {
|
||||
0x26: "REQA",
|
||||
0x52: "WUPA",
|
||||
0x35: "Optional Timeslot Method",
|
||||
# 40 - 4F Proprietary
|
||||
# 78 - 7F proprietary
|
||||
# Other RFU
|
||||
},
|
||||
"FSDI":{
|
||||
0x0: "FSD:16 ",
|
||||
0x1: "FSD:24 ",
|
||||
0x2: "FSD:32 ",
|
||||
0x3: "FSD:40 ",
|
||||
0x4: "FSD:48 ",
|
||||
0x5: "FSD:64 ",
|
||||
0x6: "FSD:96 ",
|
||||
0x7: "FSD:128 ",
|
||||
0x8: "FSD:256 "
|
||||
},
|
||||
}
|
||||
|
||||
CardTrafficTypes = {
|
||||
|
||||
}
|
||||
def parseReader(data):
|
||||
byteCount = len(data)
|
||||
note = ""
|
||||
|
||||
# short frame commands
|
||||
if (byteCount == 1 and data[0] in ReaderTrafficTypes["SHORTFRAME"]):
|
||||
note += ReaderTrafficTypes["SHORTFRAME"][data[0]]
|
||||
|
||||
# ANTICOLLISION command
|
||||
elif (byteCount<9 and byteCount > 1 and data[0] in ReaderTrafficTypes["SEL"] and data[1] & 0x88 == 0 ):
|
||||
note += "ATCOLI - "
|
||||
note += ReaderTrafficTypes["SEL"][data[0]]
|
||||
# note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " "
|
||||
# note += str((data[1] >> 4) & 0x0f) + "bytes + " + str(data[1] & 0x0f) + "bits "
|
||||
|
||||
# SELECT Command
|
||||
elif (byteCount== 9 and data[0] in ReaderTrafficTypes["SEL"] and data[1] == 0x70):
|
||||
note += "SELECT - "
|
||||
note += ReaderTrafficTypes["SEL"][data[0]]
|
||||
note += "UID_CLn:" + binascii.hexlify(data[2:7]).decode() + " "
|
||||
# note += "7bytes + 0bits "
|
||||
# note += "CRC_A:"+data[8]
|
||||
# HALT Command
|
||||
elif (byteCount == 4 and data[0] == 0x50 and data[1] == 0x00):
|
||||
note += "HALT"
|
||||
# RATS
|
||||
elif (byteCount == 4 and data[0] == 0xe0 and ((data[1] & 0x0f) < 15) and ((data[1] & 0xf0 >> 8) in ReaderTrafficTypes["FSDI"])):
|
||||
note += "RATS - "
|
||||
note += ReaderTrafficTypes["FSDI"][data[1]>>8]
|
||||
note += "CID:" + str(data[1]&0x0f) + " "
|
||||
# PPS Protocol and parameter selection request
|
||||
# PSS0 only
|
||||
elif (byteCount == 4 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x01)):
|
||||
note += "PSS0 - "
|
||||
note += "CID:"+str(data[1]&0x0f) + " "
|
||||
# PSS0+1
|
||||
elif (byteCount == 5 and (data[0]&0xf0 == 0xd0) and (data[1] == 0x11) and (data[2]&0xf0 == 0x00)):
|
||||
note += "PSS0+1 - "
|
||||
note += "CID:"+str(data[1]&0x0f) + " "
|
||||
note += "DSI:"+str(pow(2,(data[2]>>2)&0x03)) + " "
|
||||
note += "DRI:"+str(pow(2,data[2]&0x03)) + " "
|
||||
# BLOCK S-block PCB DESELECT
|
||||
# Without CID
|
||||
elif (byteCount == 3 and data[0] == 0xc2):
|
||||
note += "DESEL"
|
||||
# With CID
|
||||
elif (byteCount == 4 and data[0] == 0xca and data[1]&0x30 == 0x00):
|
||||
note += "DESEL - "
|
||||
note += "CID:"+ str(data[1]&0x0f) + " "
|
||||
|
||||
return note
|
||||
|
||||
def parseCard(data):
|
||||
pass
|
||||
@@ -3,6 +3,7 @@
|
||||
import struct
|
||||
import binascii
|
||||
import math
|
||||
import Chameleon.ISO14443 as iso14443_3
|
||||
|
||||
def checkParityBit(data):
|
||||
byteCount = len(data)
|
||||
@@ -96,7 +97,7 @@ eventTypes = {
|
||||
TIMESTAMP_MAX = 65536
|
||||
eventTypes = { i : ({'name': 'UNKNOWN', 'decoder': binaryDecoder} if i not in eventTypes.keys() else eventTypes[i]) for i in range(256) }
|
||||
|
||||
def parseBinary(binaryStream):
|
||||
def parseBinary(binaryStream, decode=False):
|
||||
log = []
|
||||
|
||||
# Completely read file contents and process them byte by byte
|
||||
@@ -135,13 +136,20 @@ def parseBinary(binaryStream):
|
||||
if (deltaTimestamp < 0):
|
||||
deltaTimestamp += TIMESTAMP_MAX;
|
||||
|
||||
note = ""
|
||||
# If we need to decode the data
|
||||
if (decode):
|
||||
# Decode the data from Reader
|
||||
if(event == 0x44 or event == 0x45):
|
||||
note = iso14443_3.parseReader(binascii.a2b_hex(logData))
|
||||
# Create log entry as dict and append it to event list
|
||||
logEntry = {
|
||||
'eventName': eventTypes[event]['name'],
|
||||
'dataLength': dataLength,
|
||||
'timestamp': timestamp,
|
||||
'deltaTimestamp': deltaTimestamp,
|
||||
'data': logData
|
||||
'data': logData,
|
||||
'note': note
|
||||
}
|
||||
|
||||
log.append(logEntry)
|
||||
|
||||
+5
-3
@@ -19,10 +19,11 @@ def verboseLog(text):
|
||||
|
||||
def formatText(log):
|
||||
formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:'
|
||||
formatString += '{eventName:<16} ({dataLength:<3} bytes) [{data}]\n'
|
||||
formatString += '{eventName:<28} ({dataLength:<3} bytes)\t[{data:<20}]\t{note}\n'
|
||||
text = ''
|
||||
|
||||
for logEntry in log:
|
||||
|
||||
text += formatString.format(**logEntry)
|
||||
|
||||
return text
|
||||
@@ -46,6 +47,7 @@ def main():
|
||||
|
||||
argParser.add_argument("-t", "--type", choices=outputTypes.keys(), default='text',
|
||||
help="specifies output type")
|
||||
argParser.add_argument("-d", "--decode", dest="decode", action='store_true', default=False)
|
||||
argParser.add_argument("-l", "--live", dest="live", action='store_true', help="Use live logging capabilities of Chameleon")
|
||||
argParser.add_argument("-c", "--clear", dest="clear", action='store_true', help="Clear Chameleon's log memory when using -p")
|
||||
argParser.add_argument("-m", "--mode", dest="mode", metavar="LOGMODE", help="Additionally set Chameleon's log mode after reading it's memory")
|
||||
@@ -69,7 +71,7 @@ def main():
|
||||
|
||||
while True:
|
||||
stream = io.BytesIO(chameleon.read())
|
||||
log = Chameleon.Log.parseBinary(stream)
|
||||
log = Chameleon.Log.parseBinary(stream, args.decode)
|
||||
if (len(log) > 0):
|
||||
print(outputTypes[args.type](log))
|
||||
|
||||
@@ -95,7 +97,7 @@ def main():
|
||||
sys.exit(2)
|
||||
|
||||
# Parse actual logfile
|
||||
log = Chameleon.Log.parseBinary(handle)
|
||||
log = Chameleon.Log.parseBinary(handle, args.decode)
|
||||
|
||||
# Print to console using chosen output type
|
||||
print(outputTypes[args.type](log))
|
||||
|
||||
Reference in New Issue
Block a user