阅读 Mifare Classic 会返回奇怪的字符 [英] Reading Mifare Classic returns strange characters

查看:8

问题描述

在使用 Android 读取 MIFARE 卡并将数据转换为 UTF-8 时,我得到了奇怪的字符,例如 .我正在尝试构建一个可以读取我们正在使用的某种身份证的应用程序.现在的问题是我在单词之间得到了奇怪的字符,并且一些单词在块之间被分割了,所以我怎样才能安全地得到我正在寻找的单词?例如我的读数是这样的:

43224 19032019在第 2 区块 sektor 2 bindex :8

并在以 19 开头的其余数字位于新块的位置进行拆分:

...我的名字...M...19

在区块 1 sektor 1 bindex :4

930402...NO934951

在第 2 区块 sektor 1 bindex :4

<上一页>c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42 "Åbnid" "OOOOOO" "KB"44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39 "DDD DDDDD" "M" "19"39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31 "944342" "NO966651"00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 0030 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b 022" AS" 总 k"4f 4e 54 52 4f 4c 4c 20 41 53 20 00 c9 30 32 38 "ONTROLL AS" "028"37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00 "70433" "20210211"00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00

这是我从卡片中读取的方式:

标签 tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);MifareClassic mfc = MifareClassic.get(tagFromIntent);

这是我用于在 for 循环中读取的代码:

 data = mfc.readBlock(bIndex + block);

然后我使用将数据转换为 UTF8 进行打印:

 public String convertByteArrayToUTF8(byte[] bytes){字符串编码 = null;尝试 {编码 = 新字符串(字节,StandardCharsets.UTF_8);}捕获(异常 e){编码=新字符串(字节,Charset.defaultCharset());}返回编码;}

我尝试过使用 ASCII、UTF-16 等,但没有成功.

解决方案

所以你标签上的数据(不包括扇区预告片看起来有点像:

<上一页>C5 42 4E 49 44 00 07 4F 4F 4F 4F 4F 4F 00 4B 42 ÅBNID..OOOOOO.KB44 44 44 20 44 44 44 44 44 00 82 4D 00 C9 31 39 DDD DDDDD.,M.É1939 34 34 33 34 32 00 D0 4E 4F 39 36 36 36 35 31 944342.ÐNO96665130 32 32 20 20 41 53 00 D3 54 4F 54 41 4C 20 4B 022 AS.ÓTOTAL K4F 4E 54 52 4F 4C 4C 20 41 53 20 00 C9 30 32 38 ONTROLL AS .É02837 30 34 33 33 00 C9 32 30 32 31 30 32 31 31 00 70433.É20210211.

这似乎是某种形式的结构化数据.简单地将整个二进制 blob 转换为 UTF-8(或 ASCII)编码的字符串没有多大意义.相反,您需要对数据的结构方式进行逆向工程(或者,更好的是,您尝试从系统制造商处获取规范).

据我所见,该数据似乎由多个以空字符结尾的字符串组成,这些字符串嵌入到某种紧凑的 (Tag)-Length-Value 格式中.第一个字节似乎是标签(?)+长度,所以我们有

<上一页>C5 长度 = 542 4E 49 44 00 BNID"07 长度 = 74F 4F 4F 4F 4F 4F 00 OOOOOO"4B 长度 = 1142 44 44 44 20 44 44 44 44 44 00 KBDDD DDDDD"82 长度 = 24D 00M"C9 长度 = 931 39 39 34 34 33 34 32 00 19944342"D0 长度 = 164E 4F 39 36 36 36 35 31 30 32 32 20 20 41 53 00 NO966651022 AS"D3 长度 = 1954 4F 54 41 4C 20 4B 4F 4E 54 52 4F 4C 4C 20 41 53 20 00 TOTAL KONTROLL AS"C9 长度 = 930 32 38 37 30 34 33 33 00 02870433"C9 长度 = 932 30 32 31 30 32 31 31 00 20210211"

例如,第一个字节可以分成标签和长度,如下所示:TTTL LLLL(高 3 位编码标签,低 5 位编码后续值的长度).这将给出以下标签

  • 0x6 表示BNID"、19944342"、NO966651022 AS"、TOTAL KONTROLL AS"、02870433"和20210211"
  • 0x0 表示OOOOOO"
  • 0x2 表示KBDDD DDDDD"
  • 0x4 代表M"

因此,标签和长度之间的分割也可能是 TTLL ​​LLLL(高 2 位编码标签,低 6 位编码后面值的长度).

不幸的是,该格式与我所知道的任何流行格式都不相似.因此,您可以通过比较多张不同的卡片并从值中获取含义来继续您的逆向工程.

到目前为止,为了解码上述内容,您将从读取第一个字节开始,从该字节中提取长度,剪切后续字节的数量并将它们转换为字符串(基于您的示例提供,ASCII编码应该做).然后您可以继续下一个字节,从中提取长度信息,...

When reading a MIFARE card with Android and converting the data to UTF-8 I get strange characters like �. I'm trying to build an application that can read some kind of ID card we're using. The problem now is that I get weird characters between words and some words are split between blocks so how can I safely get a word I'm looking for? For instance my readings is something like this:

43224���19032019�� at block 2 sektor 2 bindex :8

and with splitting where rest of the number starting with 19 is at a new block:

�me Name���M���19

at block 1 sektor 1 bindex :4

930402���NO934951

at block 2 sektor 1 bindex :4

c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42   "Åbnid" "OOOOOO" "KB"
44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39   "DDD DDDDD" "M" "19"
39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31   "944342" "NO966651"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00
30 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b   "022" "AS" "Total k"
4f 4e 54 52 4f 4c 4c 20 41 53 20 00 c9 30 32 38   "ONTROLL AS" "028"
37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00   "70433" "20210211"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00

This is how I read from the card:

Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
MifareClassic mfc = MifareClassic.get(tagFromIntent);

Here is my code I use for reading inside a for loop:

 data = mfc.readBlock(bIndex + block); 

and then for converting data to UTF8 for printing I use:

   public String convertByteArrayToUTF8(byte[] bytes){
    String encoded = null;
    try {
        encoded = new String(bytes, StandardCharsets.UTF_8);
    }
    catch (Exception e){
        encoded = new String(bytes, Charset.defaultCharset());
    }
    return encoded;
}

I've tried with ASCII, UTF-16 etc with no luck.

解决方案

So the data on your tag (excluding the sector trailers looks somewhat like that:

C5 42 4E 49 44 00 07 4F 4F 4F 4F 4F 4F 00 4B 42        ÅBNID..OOOOOO.KB
44 44 44 20 44 44 44 44 44 00 82 4D 00 C9 31 39        DDD DDDDD.‚M.É19
39 34 34 33 34 32 00 D0 4E 4F 39 36 36 36 35 31        944342.ÐNO966651
30 32 32 20 20 41 53 00 D3 54 4F 54 41 4C 20 4B        022  AS.ÓTOTAL K
4F 4E 54 52 4F 4C 4C 20 41 53 20 00 C9 30 32 38        ONTROLL AS .É028
37 30 34 33 33 00 C9 32 30 32 31 30 32 31 31 00        70433.É20210211.

This seems to be some form of structured data. Simply converting the whole binary blob into a UTF-8 (or ASCII) encoded string doesn't make much sense. Instead, you will need to reverse engineer the way that the data is structured (or, even better, you try to obtain the specification from the system manufacturer).

From what I can see, it looks as if that data consisted of multiple null-terminated strings embedded into some compact (Tag)-Length-Value format. The first byte seems to be the tag(?) + length, so we have

C5    Length = 5
    42 4E 49 44 00                                               "BNID"
07    Length = 7
    4F 4F 4F 4F 4F 4F 00                                         "OOOOOO"
4B    Length = 11
    42 44 44 44 20 44 44 44 44 44 00                             "KBDDD DDDDD"
82    Length = 2
    4D 00                                                        "M"
C9    Length = 9
    31 39 39 34 34 33 34 32 00                                   "19944342"
D0    Length = 16
    4E 4F 39 36 36 36 35 31 30 32 32 20 20 41 53 00              "NO966651022  AS"
D3    Length = 19
    54 4F 54 41 4C 20 4B 4F 4E 54 52 4F 4C 4C 20 41 53 20 00     "TOTAL KONTROLL AS "
C9    Length = 9
    30 32 38 37 30 34 33 33 00                                   "02870433"
C9    Length = 9
    32 30 32 31 30 32 31 31 00                                   "20210211"

The first byte could, for instance, be split into tag and length like this: TTTL LLLL (upper 3 bits encode the tag, lower 5 bits encode the length of the following value). This would give the following tags

  • 0x6 for "BNID", "19944342", "NO966651022 AS", "TOTAL KONTROLL AS ", "02870433", and "20210211"
  • 0x0 for "OOOOOO"
  • 0x2 for "KBDDD DDDDD"
  • 0x4 for "M"

Hence, the split between tag and length might also be TTLL LLLL (upper 2 bits encode the tag, lower 6 bits encode the length of the following value).

Unfortunately, the format doesn't resemble any of the popular formats that I'm aware of. So you could just continue your reverse engineering by comparing multiple different cards and by deriving meaning from the values.

So far, in order to decode the above, you would start by reading the first byte, extract the length from that byte, cut that amount of follow-up bytes and convert them into a string (based on the sample that you provided, ASCII encoding should do). You can then continue with the next byte, extract the length information from it, ...

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆