#!/usr/bin/python # # Copyright (c) 2019 Clementine Computing LLC. # # This file is part of PopuFare. # # PopuFare is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # PopuFare is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with PopuFare. If not, see . # # The output format is `|`, where the # and field are in ascii hex. # # Input is expected to come from stdin and as the result of the # `proxmark3` LUA script setup for low frequency read. # Input text is seached for a matching prefix of: # # #db# TAG ID: # # Once found, the ascii hex string is read, it's converted to binary # and parsed. # The first run of two '1' bits is removed from the 'left'. # The remaing number of bits is the bit length and the remaining # bit string is converted back to ascii. # Note the 'paylaod' can be a non exact multiple of 4 or 2. # # For example, if the following string was found: # # #db# TAG ID: 200712054a (677) # # This is converted to: # # 2 0 0 7 1 2 0 5 4 a # 0010 0000 0000 01 11 0001 0010 0000 0101 0100 1010 # | | # ----------------------------------- # 26 bits # # To evenually give the final result: # # 23|43F6311B2 # import os import re import sys import time import datetime RATE_LIMIT_MS = 1500.0 def convert_tagid(s): binstr = "" for c in s: v = int(c, 16) _b = bin(int(c, 16))[2:] __b = "0"*(4-len(_b)) + _b binstr = binstr + __b f, s, = -1, -1 for idx, b in enumerate(binstr): if (b == '1') and (f < 0): f = idx elif (b == '1') and (s < 0): s = idx break filt_binstr = binstr[s+1:] n = len(filt_binstr) bitlen = n fin_hex = "" while n >= 4: _b = filt_binstr[n-4:n] fin_hex = hex(int(_b, 2))[2:] + fin_hex n -= 4 if n>0: _b = filt_binstr[0:n] fin_hex = hex(int(_b, 2))[2:] + fin_hex return hex(bitlen)[2:] + "|" + fin_hex t_prv = time.time()*1000.0 t_now = t_prv LAST_TOK = "" while True: line = sys.stdin.readline() line = line.strip() m = re.match("#db# TAG ID: ([^ ]*)", line) if m: t_now = time.time()*1000.0 tok = convert_tagid(m.group(1)).upper() if LAST_TOK != tok: #sys.stdout.write( str(datetime.datetime.now()) + ": " + str(tok) + "\n") sys.stdout.write( str(int(time.time())) + ": " + str(tok) + "\n") sys.stdout.flush() t_prv = t_now LAST_TOK = tok elif (t_now - t_prv) >= RATE_LIMIT_MS: #sys.stdout.write( str(datetime.datetime.now()) + ": " + str(tok) + "\n") sys.stdout.write( str(int(time.time())) + ": " + str(tok) + "\n") sys.stdout.flush() t_prv = t_now LAST_TOK = tok else: pass