ReverseD8
At work, we can use a NFC key to store money. Coffee machine is from "D8". NFC are Mifare 1K ones, so they have a security hole (Search mfoc).
1st, if you want to download the keys : http://x.mdk.fr/keys.tar.bz2
I will not post all dumps here, (1k dumps are big in hexadecimal on a wiki page) but I dumped a few keys with a few different values, and I'll post the diffs between dumps.
I got two keys, and two dumps per key. First key from 9.2€ to 8.35€. Second key from 0€ to 0.10€
Diff of the first key (Between a dump of 9.2€ and a dump of 8.35€)
< 2 060 b491 7e19 0000 0000 0000 0000 1801 003f 100 R:AB W:-B I:-- DTR:-- r/w block --- > 2 060 82bb 261a 0000 0000 0000 0000 1c01 0020 100 R:AB W:-B I:-- DTR:-- r/w block 26,27c26,27 < 0 080 9803 0000 67fc ffff 9803 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block < 1 090 c503 0000 3afc ffff c503 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block --- > 0 080 4303 0000 bcfc ffff 4303 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block > 1 090 7003 0000 8ffc ffff 7003 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block
Diff of the second key (Between a dump of 0€ and a dump of 0.10€)
< 2 060 daa0 9019 0000 0000 0000 0000 2200 0098 100 R:AB W:-B I:-- DTR:-- r/w block --- > 2 060 2eaf 261a 0000 0000 0000 0000 2300 00d2 100 R:AB W:-B I:-- DTR:-- r/w block 26,27c26,27 < 0 080 0000 0000 ffff ffff 0000 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block < 1 090 2d00 0000 d2ff ffff 2d00 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block --- > 0 080 0a00 0000 f5ff ffff 0a00 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block > 1 090 0000 0000 ffff ffff 0000 0000 09f6 09f6 110 R:AB W:-B I:-B DTR:AB r/w block
First we'll watch for the two-line diff, adresses 0x080 and 0x090 :
First step, data presentation, as I felt there was a 1 complement (ffff / 0000) I presented some binary, and dropped columns of data that were identical between two dumps :
9.2 : 9803 0000 67fc c503 0000 3afc | 10011000.00000011 ... 01100111.11111100 11000101.00000011 ... 00111010.11111100 8.3 : 4303 0000 bcfc 7003 0000 8ffc | 01000011.00000011 ... 10111100.11111100 01110000.00000011 ... 10001111.11111100 0.1 : 0a00 0000 f5ff 0000 0000 ffff | 00001010.00000000 ... 11110101.11111111 00000000.00000000 ... 11111111.11111111 0.0 : 0000 0000 ffff 2d00 0000 d2ff | 00000000.00000000 ... 11111111.11111111 00101101.00000000 ... 11010010.11111111
So, that's true, we have a complement, so half of the data is useless. Follow a simplified presentation witout duplicate (complemented) data) :
9.2 : 9803 c503 10011000.00000011 11000101.00000011 0398 -> 920 | 03c5 -> 965 8.3 : 4303 7003 01000011.00000011 01110000.00000011 0343 -> 835 | 0370 -> 880 0.1 : 0a00 0000 00001010.00000000 00000000.00000000 000A -> 10 | 0000 -> 0 0.0 : 0000 2d00 00000000.00000000 00101101.00000000 0000 -> 0 | 002d -> 45
Ok, 0a00 say all about the 0.10€ key, as 0a(16) is 10(10), 0a00 is 10 in big endian, so money is stored here, in big endian in 1/100 of euros. so 9803(16be) gives 920(10) that give 9.20€
This is the big part of the dump, the remaining part (top one) seems to store metadata but is not reversed yet :
Follow two tables, for the two keys, showing old_value -> new_value, with, for each value, its binay representation and its base 10 representation as if value is stored in big endian.
In the following table, 16be mean "From base 16 big endian to decimal", 16le for little endian.
9.2 -> 8.35 Value: As binary 16be 16le Value: As binary 16be 16le DAA0 : 11011010.10100000 41178 55968 -> 2EAF : 00101110.10101111 44846 11951 date ? 9019 : 10010000.00011001 6544 36889 -> 261A : 00100110.00011010 6694 9754 2200 : 00100010.00000000 34 8704 -> 2300 : 00100011.00000000 35 8960 count ? 0098 : 00000000.10011000 38912 152 -> 00D2 : 00000000.11010010 53760 210
0.0 -> 0.1 Value: As binary 16be 16le Value: As binary 16be 16le B491 : 10110100.10010001 37300 46225 -> 82BB : 10000010.10111011 48002 d33467 ate ? 7E19 : 01111110.00011001 6526 32281 -> 261A : 00100110.00011010 6694 9754 1801 : 00011000.00000001 280 6145 -> 1C01 : 00011100.00000001 284 7169 count ? 003F : 00000000.00111111 16128 63 -> 0020 : 00000000.00100000 8192 32
Non reversed data (to reverse) :
mandark@blanc$ grep 00000060 *.dmp.hex | column -t step1-0.dmp.hex:00000060 da a0 90 19 00 00 00 00 00 00 00 00 22 00 00 98 |............"...| step2-0.1.dmp.hex:00000060 2e af 26 1a 00 00 00 00 00 00 00 00 23 00 00 d2 |..&.........#...| step3-0.2.dmp.hex:00000060 53 1a 51 1a 00 00 00 00 00 00 00 00 24 00 00 98 |S.Q.........$...|
mandark@blanc$ grep 00000060 *.dmp.hex | column -t step1-9.2.dmp.hex:00000060 b4 91 7e 19 00 00 00 00 00 00 00 00 18 01 00 3f |..~............?| step2-8.35.dmp.hex:00000060 82 bb 26 1a 00 00 00 00 00 00 00 00 1c 01 00 20 |..&............ | step3-3.9.dmp.hex:00000060 c7 9a 59 1a 00 00 00 00 00 00 00 00 2a 01 00 91 |..Y.........*...|
Clearly 0022 0023 0024, and 0118 011C 012A are juste counters. I only add 10 cents on the key1 between each dumps, but I drink some coffee between each dumps on key2, so it's normal values. I now know I drank 18 coffees between first and last dump !
----------------------------------------------------------------------------------- |money | counter | Last byte ? | Fist long, kind of timestamp | |---------------------------------------------------------------------------------| |euro | hex dec | hex dec bin | hex little endian dec | |---------------------------------------------------------------------------------| |0 | 22 00 34 | 98 152 10011000 | da a0 90 19 19 90 a0 da 428908762 | |0.1 | 23 00 35 | D2 210 11010010 | 2e af 26 1a 1a 26 af 2e 438742830 | |0.2 | 24 00 36 | 98 152 10011000 | 53 1a 51 1a 1a 51 1a 53 441522771 | |---------------------------------------------------------------------------------| |9.2 | 18 01 280 | 3F 63 00111111 | b4 91 7e 19 19 7e 91 b4 427725236 | |8.35 | 1C 01 284 | 20 32 00100000 | 82 bb 26 1a 1a 26 bb 82 438745986 | |3.9 | 2A 01 298 | 91 145 10010001 | c7 9a 59 1a 1a 59 9a c7 442079943 | -----------------------------------------------------------------------------------
First long seems to be a kind of timestamp, but it's not a unix timestamp. It seems to count seconds, but I don't know the start point. Start point may be random ^-^
About last byte, I tried some crc's (namely crc-8, crc-8-darc, crc-8-i-code, crc-8-itu, crc-8-maxim, crc-8-rohc, crc-8-wcdma, crc-16, crc-16-buypass, crc-16-dds-110, crc-16-dect, crc-16-dnp, crc-16-en-13757, crc-16-genibus, crc-16-maxim, crc-16-mcrf4xx, crc-16-riello, crc-16-t10-dif, crc-16-teledisk, crc-16-usb, x-25, xmodem, modbus, kermit, crc-ccitt-false, crc-aug-ccitt, crc-24, crc-24-flexray-a, crc-24-flexray-b, crc-32, crc-32-bzip2, crc-32c, crc-32d, crc-32-mpeg, posix, crc-32q, jamcrc, xfer, crc-64, crc-64-we, crc-64-jones)
I tried with last byte set to any possible value and I '% 255'ed results, also tried without last byte, so I got a lot of false positive matches, for example, for step1-0.dmp.hex:00000060, I have 39 possibilities yielding to 98, but I found NO possibility working with the same params for two different dumps.
We may try to compute more value in CRC's, for example whole block, I just tried to CRC a single line (16 bytes).