if __name__ == '__main__': if len(sys.argv) < 2: sys.stderr.write('Usage: %s <ovc_dump> [<ovc_dump_2> [...]]\n'%sys.argv[0]) sys.exit(1) for fn in sys.argv[1:]: inp = open(fn, 'rb') data = inp.read() inp.close() if len(data) == 4096: # mifare classic 4k # card details # TODO make the card an object in itself with fixed-position templates # note that these data areas are not yet fully understood cardid = getbits(data[0:4], 0, 4*8) cardtype = OvcCardType(getbits(data[0x10:0x36], 18*8+4, 19*8)) validuntil = OvcDate(getbits(data[0x10:0x36], 11*8+6, 13*8+4)) s = 'OV-Chipkaart id %d, %s, valid until %s'%(cardid, cardtype, validuntil) if cardtype==2: birthdate = OvcBcdDate(getbits(mfclassic_getsector(data, 22), 14*8, 18*8)) s += ', birthdate %s'%birthdate print s # transactions for sector in range(32, 35): sdata = mfclassic_getsector(data, sector)[:-0x10] for chunk in range(0, len(sdata), 0x30): if ord(sdata[chunk]) == 0: continue print OvcClassicTransaction(sdata[chunk:chunk+0x30]) for sector in range(35, 39):
def printit(self): data = self.data # card details # note that these data areas are not yet fully understood cardid = getbits(data[0:4], 0, 4*8) cardtype = OvcCardType(getbits(data[0x10:0x36], 18*8+4, 19*8)) validuntil = OvcDate(getbits(data[0x10:0x36], 11*8+6, 13*8+4)) s = 'OV-Chipkaart id %d, %s, valid until %s'%(cardid, cardtype, validuntil) #if cardtype==2: # birthdate = OvcBcdDate(getbits(mfclassic_getsector(data, 22), 14*8, 18*8)) # s += ', birthdate %s'%birthdate print s for sector in range(22, 24): sdata = mfclassic_getsector(data, sector)[:-0x10] offset,size = mfclassic_getoffset(sector) sector22 = OvcSector22(sdata, ovc=self, cardtype=cardtype) print ("%3x:" % offset), sector22 print "" # subscriptions # Print the slot number value for this subscription before it and the idsubs after it. print "Subscriptions:" log_entry = 0 for sector in range(32, 35): sdata = mfclassic_getsector(data, sector)[:-0x10] offset,size = mfclassic_getoffset(sector) for chunk in range(0, len(sdata), 0x30): l = log_entry log_entry += 1 if ord(sdata[chunk]) == 0: continue addr = offset + chunk sys.stdout.write(('#%x=%03x: ' % (l, addr))) #Oldest method: #print OvcClassicTransaction(sdata[chunk:chunk+0x30]) #sys.stdout.write(' : ') #Method #2: #print OvcSubscriptionRecord.make(sdata[chunk:chunk+0x30], ovc=self) #sys.stdout.write(' : ') #Method #3: s = OvcVariableSubscription(sdata[chunk:chunk+0x30], ovc=self) print s aux_addr = OvcSubscriptionAux.addr(l) aux_sdata = data[aux_addr:aux_addr+0x10] sys.stdout.write((' %03x: ' % (aux_addr))) s_aux = OvcSubscriptionAux(aux_sdata, ovc=self) print s_aux, OvcSubscriptionId(self.find_subscr_id(l)) self.subscr[l] = s self.subscr_aux[l] = s_aux # transactions print "Transaction logs: (history, checkin/out, credit)" # Entries 0-10: for User, chronologic, may be erased? # Entries 11-23: for Conductor, not chronologic, only one check-in # Entries 24-27: add Credit transactions start_log_0 = 0 start_log_1 = 11 start_log_2 = 24 log_entry = 0 for sector in range(35, 39): sdata = mfclassic_getsector(data, sector)[:-0x10] offset,size = mfclassic_getoffset(sector) for chunk in range(0, len(sdata), 0x20): if (chunk + 0x20) > len(sdata): continue # last few bytes, not big enough l = log_entry log_entry += 1 if l == start_log_1 or l == start_log_2: print "--" if ord(sdata[chunk]) == 0: continue if l >= start_log_2: l = OvcMostRecentCreditIndex.map[l - start_log_2 - 1] elif l >= start_log_1: l = l - start_log_1 sys.stdout.write(('#%x=%03x: ' % (l, offset + chunk))) #print OvcClassicTransaction(sdata[chunk:chunk+0x20]) print OvcVariableTransaction(sdata[chunk:chunk+0x20], ovc=self) print print "Credit: (current and previous)" print self.saldo_curr_prefix, str(self.saldo_curr) print self.saldo_prev_prefix, str(self.saldo_prev) if not self.saldo_prev.id <= self.saldo_curr.id: print "Order bit 250 in 0xFB0/FD0 contradicted by id order" print print "Main index (current and previous):" print self.FB0_curr_prefix, str(self.FB0_curr) print self.FB0_prev_prefix, str(self.FB0_prev) print print "Check-in and check-out indexes (current and previous):" print self.F50_curr_prefix, str(self.F50_curr) print self.F50_prev_prefix, str(self.F50_prev) print print "Most recent subscription (current and previous):" print self.F10_curr_prefix, str(self.F10_curr) print self.F10_prev_prefix, str(self.F10_prev) if not self.F10_prev.size <= self.F10_curr.size: # Maybe this will also occur if nearly all slots are taken # and they are being re-used print "Order bit 248 in 0xFB0/FD0 contradicted by subscription order (list getting full?)"
if len(sys.argv) < 2: sys.stderr.write('Usage: %s <ovc_dump> [<ovc_dump_2> [...]]\n' % sys.argv[0]) sys.exit(1) for fn in sys.argv[1:]: inp = open(fn, 'rb') data = inp.read() inp.close() if len(data) == 4096: # mifare classic 4k # card details # TODO make the card an object in itself with fixed-position templates # note that these data areas are not yet fully understood cardid = getbits(data[0:4], 0, 4 * 8) cardtype = OvcCardType(getbits(data[0x10:0x36], 18 * 8 + 4, 19 * 8)) validuntil = OvcDate( getbits(data[0x10:0x36], 11 * 8 + 6, 13 * 8 + 4)) s = 'OV-Chipkaart id %d, %s, valid until %s' % (cardid, cardtype, validuntil) if cardtype == 2: birthdate = OvcBcdDate( getbits(mfclassic_getsector(data, 22), 14 * 8, 18 * 8)) s += ', birthdate %s' % birthdate print s # transactions for sector in range(32, 35): sdata = mfclassic_getsector(data, sector)[:-0x10]