diff --git a/client/pyscripts/findbits.py b/client/pyscripts/findbits.py new file mode 100755 index 000000000..809465a2e --- /dev/null +++ b/client/pyscripts/findbits.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +# findbits.py - find Binary, Octal, Decimal or Hex number in bitstream +# +# Adam Laurie +# http://rfidiot.org/ +# +# This code is copyright (c) Adam Laurie, 2009, All rights reserved. +# For non-commercial use only, the following terms apply - for all other +# uses, please contact the author: +# +# This code is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This code 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 General Public License for more details. +# + +import sys +import os + +# invert binary string +def invert(data): + return ''.join('0' if c == '1' else '1' for c in data) + +# do the actual search +def search(target,data): + location = data.find(target) + if location >= 0: + print('*** Match at bit {:d}: {}<{}>{}'.format(location, data[:location],target,data[location+len(target):])) + else: + print('Not found') + +# convert integer to binary string +def binstring(number): + return bin(number)[2:] if number > 0 else '' + +# reverse string order +def stringreverse(data): + return data[::-1] + +# match forward, backward and inverted +def domatch(binary,number): + reversed= stringreverse(number) + inverted= invert(binary) + + print(' Forward: (%s) ' % number, end = '') + search(binary,number) + print(' Reverse: (%s) ' % reversed, end = '') + search(binary,reversed) + print(' Inverse: (%s) ' % inverted) + print(' Forward: (%s) ' % number, end = '') + search(inverted,number) + print(' Reverse: (%s) ' % reversed, end = '') + search(inverted,reversed) + +def main(): + if(len(sys.argv) < 3): + print(""" +\t{0} - Search bitstream for a known number + +Usage: {0} + +\tNUMBER will be converted to it\'s BINARY equivalent for all valid +\tinstances of BINARY, OCTAL, DECIMAL and HEX, and the bitstream +\tand it\'s inverse will be searched for a pattern match. Note that +\tNUMBER must be specified in BINARY to match leading zeros. + +Example: + +\t{0} 73 0110010101110011 +""".format(sys.argv[0])) + os._exit(True) + + bases= { + 2:'BINARY', + 8:'OCTAL', + 10:'DECIMAL', + 16:'HEX', + } + + for base, base_name in sorted(bases.items()): + try: + number= int(sys.argv[1],base) + print('\nTrying ' + base_name) + # do BINARY as specified to preserve leading zeros + if base == 2: + domatch(sys.argv[1],sys.argv[2]) + else: + domatch(binstring(number),sys.argv[2]) + except: + continue + +if __name__ == '__main__': + main() diff --git a/client/pyscripts/parity.py b/client/pyscripts/parity.py new file mode 100644 index 000000000..6be9d979d --- /dev/null +++ b/client/pyscripts/parity.py @@ -0,0 +1,78 @@ +# This code is contributed by +# Shubham Singh(SHUBHAMSINGH10) +# 2020, modified (@iceman1001) + +import sys + +# Python3 program to illustrate Compute the +# parity of a number using XOR +# Generating the look-up table while pre-processing +def P2(n, table): + table.extend([n, n ^ 1, n ^ 1, n]) +def P4(n, table): + return (P2(n, table), P2(n ^ 1, table), + P2(n ^ 1, table), P2(n, table)) +def P6(n, table): + return (P4(n, table), P4(n ^ 1, table), + P4(n ^ 1, table), P4(n, table)) +def LOOK_UP(table): + return (P6(0, table), P6(1, table), + P6(1, table), P6(0, table)) + +# LOOK_UP is the macro expansion to generate the table +table = [0] * 256 +LOOK_UP(table) + +# Function to find the parity +def Parity(num) : + # Number is considered to be of 32 bits + max = 16 + + # Dividing the number o 8-bit + # chunks while performing X-OR + while (max >= 8): + num = num ^ (num >> max) + max = max // 2 + + # Masking the number with 0xff (11111111) + # to produce valid 8-bit result + return table[num & 0xff] + +def main(): + if(len(sys.argv) < 2): + print(""" + \t{0} - Calculate parity of a given number + + Usage: {0} <2,10,16> + + \t Specify type as in 2 Bin, 10 Decimal, 16 Hex, and number in that particular format + \t number can only be 32bit long. + + Example: + + \t{0} 10 1234 + + Should produce the output: + + \tOdd parity\n""".format(sys.argv[0])) + return 0 + + + numtype= int(sys.argv[1], 10) + print("numtype: {0}".format(numtype)) + input= int(sys.argv[2], numtype) + print("num: {0} 0x{0:X}".format(input)) + + #num = "001111100010100011101010111101011110" + # Result is 1 for odd parity + # 0 for even parity +# result = Parity( int(input, numtype) ) + result = Parity(input) + print("Odd parity") if result else print("Even parity") + + +if __name__ == "__main__": + main() + + + diff --git a/client/pyscripts/pm3_eml2mfd.py b/client/pyscripts/pm3_eml2mfd.py new file mode 100755 index 000000000..90803cf5e --- /dev/null +++ b/client/pyscripts/pm3_eml2mfd.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +''' +# Andrei Costin , 2011 +# pm3_eml2mfd.py +# Converts PM3 Mifare Classic emulator EML text file to MFD binary dump file +''' + +import sys +import binascii + +def main(argv): + argc = len(argv) + if argc < 3: + print('Usage:', argv[0], 'input.eml output.mfd') + return 1 + + with open(argv[1], "r") as file_inp, open(argv[2], "wb") as file_out: + for line in file_inp: + line = line.rstrip('\n').rstrip('\r') + print(line) + data = binascii.unhexlify(line) + file_out.write(data) + +if __name__ == '__main__': + main(sys.argv) diff --git a/client/pyscripts/pm3_eml_mfd_test.py b/client/pyscripts/pm3_eml_mfd_test.py new file mode 100755 index 000000000..8fae5965e --- /dev/null +++ b/client/pyscripts/pm3_eml_mfd_test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +from tempfile import mkdtemp +from shutil import rmtree +from string import hexdigits +import unittest, os +import pm3_eml2mfd, pm3_mfd2eml + +class TestEmlMfd(unittest.TestCase): + def setUp(self): + self.tmpdir = mkdtemp() + + def tearDown(self): + rmtree(self.tmpdir) + + EML2MFD_TESTCASES = [ + ('', ''), + ("41424344\r\n45464748\n494A4B4C\n", "ABCDEFGHIJKL") + ] + def test_eml2mfd(self): + self.three_argument_test(pm3_eml2mfd.main, self.EML2MFD_TESTCASES) + + def test_mfd2eml(self): + self.three_argument_test(pm3_mfd2eml.main, + map(reversed, self.EML2MFD_TESTCASES), c14n=hex_c14n) + + def three_argument_test(self, operation, cases, c14n=str): + for case_input, case_output in cases: + try: + inp_name = os.path.join(self.tmpdir, 'input') + out_name = os.path.join(self.tmpdir, 'output') + with open(inp_name, 'w') as in_file: + in_file.write(case_input) + operation(['', inp_name, out_name]) + with open(out_name, 'r') as out_file: + self.assertEqual(c14n(case_output), c14n(out_file.read())) + finally: + for file_name in inp_name, out_name: + if os.path.exists(file_name): + os.remove(file_name) + + +def hex_c14n(inp): + """ + Canonicalizes the input string by removing non-hexadecimal + characters and making everything uppercase + """ + return ''.join(c.upper() for c in inp if c in hexdigits) + +if __name__ == '__main__': + unittest.main() diff --git a/client/pyscripts/pm3_mfd2eml.py b/client/pyscripts/pm3_mfd2eml.py new file mode 100755 index 000000000..ae7a79825 --- /dev/null +++ b/client/pyscripts/pm3_mfd2eml.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +''' +# Andrei Costin , 2011 +# pm3_eml2mfd.py +# Converts PM3 Mifare Classic MFD binary dump file to emulator EML text file +''' +import sys + +READ_BLOCKSIZE = 16 + +def main(argv): + argc = len(argv) + if argc < 3: + print('Usage:', argv[0], 'input.mfd output.eml') + return 1 + + with open(argv[1], "rb") as file_inp, open(argv[2], "w") as file_out: + while True: + byte_s = file_inp.read(READ_BLOCKSIZE) + if not byte_s: + break + hex_char_repr = byte_s.hex() + file_out.write(hex_char_repr) + file_out.write("\n") + +if __name__ == '__main__': + main(sys.argv)