rfid_filter 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #!/usr/bin/python
  2. #
  3. # Copyright (c) 2019 Clementine Computing LLC.
  4. #
  5. # This file is part of PopuFare.
  6. #
  7. # PopuFare is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # PopuFare is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. # The output format is `<bit-length>|<payload>`, where the
  21. # <bit-length> and <payload> field are in ascii hex.
  22. #
  23. # Input is expected to come from stdin and as the result of the
  24. # `proxmark3` LUA script setup for low frequency read.
  25. # Input text is seached for a matching prefix of:
  26. #
  27. # #db# TAG ID:
  28. #
  29. # Once found, the ascii hex string is read, it's converted to binary
  30. # and parsed.
  31. # The first run of two '1' bits is removed from the 'left'.
  32. # The remaing number of bits is the bit length and the remaining
  33. # bit string is converted back to ascii.
  34. # Note the 'paylaod' can be a non exact multiple of 4 or 2.
  35. #
  36. # For example, if the following string was found:
  37. #
  38. # #db# TAG ID: 200712054a (677)
  39. #
  40. # This is converted to:
  41. #
  42. # 2 0 0 7 1 2 0 5 4 a
  43. # 0010 0000 0000 01 11 0001 0010 0000 0101 0100 1010
  44. # | |
  45. # -----------------------------------
  46. # 26 bits
  47. #
  48. # To evenually give the final result:
  49. #
  50. # 23|43F6311B2
  51. #
  52. import os
  53. import re
  54. import sys
  55. import time
  56. import datetime
  57. RATE_LIMIT_MS = 1500.0
  58. def convert_tagid(s):
  59. binstr = ""
  60. for c in s:
  61. v = int(c, 16)
  62. _b = bin(int(c, 16))[2:]
  63. __b = "0"*(4-len(_b)) + _b
  64. binstr = binstr + __b
  65. f, s, = -1, -1
  66. for idx, b in enumerate(binstr):
  67. if (b == '1') and (f < 0):
  68. f = idx
  69. elif (b == '1') and (s < 0):
  70. s = idx
  71. break
  72. filt_binstr = binstr[s+1:]
  73. n = len(filt_binstr)
  74. bitlen = n
  75. fin_hex = ""
  76. while n >= 4:
  77. _b = filt_binstr[n-4:n]
  78. fin_hex = hex(int(_b, 2))[2:] + fin_hex
  79. n -= 4
  80. if n>0:
  81. _b = filt_binstr[0:n]
  82. fin_hex = hex(int(_b, 2))[2:] + fin_hex
  83. return hex(bitlen)[2:] + "|" + fin_hex
  84. t_prv = time.time()*1000.0
  85. t_now = t_prv
  86. LAST_TOK = ""
  87. while True:
  88. line = sys.stdin.readline()
  89. line = line.strip()
  90. m = re.match("#db# TAG ID: ([^ ]*)", line)
  91. if m:
  92. t_now = time.time()*1000.0
  93. tok = convert_tagid(m.group(1)).upper()
  94. if LAST_TOK != tok:
  95. #sys.stdout.write( str(datetime.datetime.now()) + ": " + str(tok) + "\n")
  96. sys.stdout.write( str(int(time.time())) + ": " + str(tok) + "\n")
  97. sys.stdout.flush()
  98. t_prv = t_now
  99. LAST_TOK = tok
  100. elif (t_now - t_prv) >= RATE_LIMIT_MS:
  101. #sys.stdout.write( str(datetime.datetime.now()) + ": " + str(tok) + "\n")
  102. sys.stdout.write( str(int(time.time())) + ": " + str(tok) + "\n")
  103. sys.stdout.flush()
  104. t_prv = t_now
  105. LAST_TOK = tok
  106. else:
  107. pass