导语:作为一个极客,你是不是有过这样的疑问,为什么我们所购买的廉价磁条读取器除了能读取信用卡或借记卡的信息外,其他磁条的信息,比如酒店钥匙卡的信息都读不出来?为找到答案,我特意选择了一个便宜的磁条读卡器,试图找到一种读取酒店钥
作为一个极客,你是不是有过这样的疑问,为什么我们所购买的廉价磁条读取器除了能读取信用卡或借记卡的信息外,其他磁条的信息,比如酒店钥匙卡的信息都读不出来?其原因很可能是读取器太过于廉价,只需要更好的读取器便能解决这一问题。不过我没有这么做,而是继续在廉价读取器上下功夫,看看能不能破解这一问题。为此,我特意选择了一个便宜的磁条读卡器,试图找到一种读取酒店钥匙卡上的原始数据的方法。
测试用的磁条读卡器的基本信息
我在2017年以11.85英镑购买了以下读卡器:
该读卡器会通过USB连接,连接后作为键盘输入装置被检测到。如果你通过该读卡器来刷信用卡或借记卡,那文本编辑器就像得到输入指令一样,将显示来自磁条的相应数据。如果你当时没有打开文本编辑器,那将看不到磁条上的任何信息。
测试证明,我买的读卡器在Windows和Linux下都能正常工作,但仅适用于读取信用卡或借记卡的信息。当我刷酒店钥匙卡时,根本看不到任何数据。
为什么不使用更好的读取器?
我本可以找一个更好的磁条读取器,比如专门针对酒店磁条的读取器,但这会破坏我的一些解决问题的能力。
我用的是一台MSR605X磁卡读写器。MSR605是USB接口123全轨道高抗磁卡写卡器,集低抗和高抗磁卡的读写功能于一体,可对磁卡进行磁条信息的编码和读取,对于磁条信息读写均一次刷卡完成,具有读、写双重校验功能,性能稳定可靠,并且兼容性好,有良好的通用性。可广泛用于金融、邮电、交通、海关等各个领域。
产品特点:
1.可同时读写多个磁道(第1、2、3磁道),读写状态有指示灯和蜂鸣器提示。
2.手动刷卡,支持高低速划卡。
3.程序软件Windows 98 / XP或Vista / Windows 7 / /我Windows 8 32位或64位。
4.读/写磁条卡符合ISO格式
主要技术指标:
1.拉卡速度:10 ~ 120cm/s
2.读写标准:ISO7810/7811
3.可读写矫顽力范围:300-4000 Oe的磁卡
4.卡片厚度:0.76-1.2MM
5.记录密度(字符):磁道:210BPI(76个字符);
第二磁道:75BPI(低密37个字符)/210BPI(高密104个字符);
第三磁道:210BPI(104个字符)
6.输出接口:USB
7.磁头寿命:> 80万次
8.电源:外部开关电源,输入:100 – 240伏交流电,输出:9 vdc 2 a
9.工作环境:温度-10℃~60℃,湿度 10% ~85%RH
10.重读写率:读卡<1/1000,写卡<1/100
11.尺寸:212×64×63mm,重量:1.4KG
虽然它的功能我还了解的不是很深,但知道它能够做原始读取就够了。
用示波器探测所读取的信号
我认为廉价读卡器中的读头几乎肯定能够从酒店钥匙卡或任何其他带有磁条的卡中读取数据。但经过测试,它们只能读取支付卡数据。如果我可以在读取器内的正确位置探测电子信号,我应该能够看到磁条上的1和0代码信息。
读取器内的读头
我有两种工具可以使用(这是一个基于家庭的项目,而不是基于办公室的项目):
1.便宜的手持式示波器(Sainsmart DS202);
2.Saleae logic分析仪;
我很快意识到,我可以把探头连接到读头上,上面有7个连接点。
读头背面的连接点
我想如果将读头直接连接到我的示波器上,我可以在刷卡时看到模拟信号。这样,我就可以用这个信号得到我想要的数据。
将读头直接连接到我的示波器上
我尝试将这7个探测点以不同的组合连接到我的示波器,但根本没有发现任何信号,或许是信号太弱,又或许是我做的探测工作还不到位。
这样,我不得不开始在谷歌上搜索所探测的芯片号码了,该芯片有一个2倍运算放大器和一个1倍模拟比较器:
· 2xLM2902DG(运算放大器)
· 1xLM2901DG(模拟比较器)
2倍运算放大器
模拟比较器(左),STM32微控制器(右)
这些芯片负责放大来自读头的信号,这样连接到每个输出,我都可能会看到信号,进而根据这些信号来确定磁条上的数据。通过数据表,我可以识别每个芯片的输出引脚。
2倍运算放大器的输出峰值为0.5-0.6v,使用我的示波器虽然可以轻松查看,但我无法将看到的内容输入到我的逻辑分析仪中。我需要大约3v的峰值。不过此时信号看起来也很没有规律,不是我希望的那种方波。
模拟比较器的输出正是我所要的,这时一个很有规律的3v或4v的峰值方波,仅在我刷卡时出现。此时,模拟比较器有4个输出,这对于可以读取3轨磁条的读头来说是合理的。现在,将这4个输出信号提供给逻辑分析仪,然后开始计算构成信号(0和1)的内容。
计算信号的内容分析
以下是Saleae logic软件中比较器观察到的输出信号:
通过Saleae logic查看到的输出信号
saleae logic是一款帮助saleae逻辑分析仪调试硬件的软件,你只需点击“开始”按钮,即可记录数字和模拟信号。您可以用数据填满整台计算机的内存,因此可以轻松采集冗长或罕见的事件。操作非常简单而且方便。
请注意,此时,我们只看到1个方波,而不是3个方波,这是因为所测试的酒店钥匙卡只有3个轨道中的1个。由于只有一个信号能分析,所以我还没有计算出信号的内容。
这时,我想到了早在1992年就出现的Phrack37。
关于1和0如何在磁条上编码的ASCII解释
本质上,0和1在编码时长度相同。只是1改变了状态,0没有改变。注意0可以是高的也可以是低的。
我没有靠着感觉来解码1和0,而是编写了一个Python脚本,用它来解析了逻辑分析仪中导出的数据并转储了1和0。以下是导出为CSV时“Logic”(Saleae软件)使用的格式:
从Saleae的Logic软件导出CSV格式
由于数据的波特率不是恒定的,因此编写Python代码很难,它随着读头读取钥匙卡的速度而变化。虽然在编写代码时,犯了几个错误,但最终还是找到了一个有效的解决方案。
以下是一个散点图,所显示的方波脉冲的持续时间并没有预期那样的2个值。相反,可以看到各种各样范围的值。它仍然是从1(短脉冲,蓝色或紫色点)到0(长脉冲,绿点),见上图。每个连续脉冲与最后一个脉冲的比率都是从1到0:
显示了脉冲持续时间(delta)需要多少值,而不是预期的两个值
分析字节或字符
由于信用卡使用2个轨道,其中一个字符由5位(4位+ 1个奇偶校验)组成,另一个字符由7位(6位+ 1个奇偶校验)组成。
我以前花了很多时间来编写信用卡解码器,部分原因是因为我需要确定我正确读取了1和o信号,另外一部分原因是因为我认为我需要一些代码来查看酒店钥匙卡中是否使用了相同的字符类型。
此编码的挑战之一是需要知道数据的开始位置和前导码何时结束,似乎 Sentinel 命令可以用于标记数据的开始或结束。这些是特殊字符(位模式),大家可以在条带的开头和结尾查找,然后它才有意义。这就是读卡器只能用于读取信用卡的原因:固件正在寻找信用卡使用的标记。它无法解码酒店钥匙卡,因为数据的开始或结束位置并不明显,或数据没有构成一个什么进程。此外,可能缺乏有效的纵向冗余校验(LRC)。
如何识别酒店磁条上的字符
我在读取的酒店磁条内容中运行了我的信用卡代码,看看是否有所有5位或所有7位的奇数奇偶校验。不幸的是没有,这也是便宜的磁条读取器读取钥匙卡失败的另一个原因。
然后我对1和0进行了一些频率分析,由于很多5位和7位的值都有自己的特点,我在信用卡磁条上看到了它们各自对应的内容。由于7位磁条上有20个空格。因此,使用频率分析,我应该能够猜到磁条使用了7位字符。
通过将一些酒店磁条数据分成8位模式,我注意到1和0的相同字符串发生的次数比预期的要多得多。所以我的猜测是,酒店磁条使用了8位字符。
下面是我编写的Python脚本的一些输出样本:
1.原始位;
2.字符串(带十六进制转储),如果使用5位、6位、7位或8位字符,则是正确的。虽然“正确性”取决于奇偶校验、位顺序以及位值映射到的字符集,但这里还有很多错误和改进的空间;
3.检查字符内的奇偶校验;
4.寻找常见字符的频率分析,以用于改变字符长度;
[+] Parsing file export.csv [-] Flips in channel 0: 3 [-] Flips in channel 1: 1652 [-] Flips in channel 2: 3 [+] Analysing swipes [-] Channel 0: [-] Channel 1: [-] Swipe 0: 693 bits [-] Swipe 1: 701 bits [-] Channel 2: [+] Creating Plots [-] creating plots with dimensions (1637, 1637), (1637, 1637) [-] saving plot to file: export.csv-plot-channel-1.png ----------------------- CHANNEL 1 SWIPE 0 ----------------------- [+] Length (bits) = 266 (%5 = 1, %6 = 2, %7 = 0, % 8= 2) [+] Data: 10100110001001100010011000100110001001100010011000100110001001100010011000100110001001100101011011100110101001001101100110100110001001100111110110111100111101100010000000100110011001101100001010010101001001001110110100000111001101011101100001100101101000101010011001 [+] Strings: [-] 5 bit: 5398621<4398621<43:>62<3539<;><=409<615549=1>6>36=1:6 [-] length: 53 [-] hex: 35 33 39 38 36 32 31 3c 34 33 39 38 36 32 31 3c 5398621<4398621< 34 33 3a 3e 36 32 3c 33 35 33 39 3c 3b 3e 3c 3d 43:>62<3539<;><= 34 30 39 3c 36 31 35 35 34 39 3d 31 3e 36 3e 33 409<615549=1>6>3 36 3d 31 3a 36 6=1:6 [-] 6 bit: E(1C&,9RD(1CFM92;+1S;G;"D,-**DMPLW8M4, [-] length: 38 [-] hex: 45 28 31 43 26 2c 39 52 44 28 31 43 46 4d 39 32 E(1C&,9RD(1CFM92 3b 2b 31 53 3b 47 3b 22 44 2c 2d 2a 2a 44 4d 50 ;+1S;G;"D,-**DMP 4c 57 38 4d 34 2c LW8M4, [-] 7 bit: %..#...2$..#&-.....3.'..$....$-0,7.-. [-] length: 37 [-] hex: 25 08 11 23 06 0c 19 32 24 08 11 23 26 2d 19 12 %..#...2$..#&-.. 1b 0b 11 33 1b 27 1b 02 24 0c 0d 0a 0a 24 2d 30 ...3.'..$....$-0 2c 37 18 2d 14 ,7.-. [-] 8 bit: .&&&&&&&&&&V....&}.. &[email protected] [-] length: 34 [-] hex: a6 26 26 26 26 26 26 26 26 26 26 56 e6 a4 d9 a6 .&&&&&&&&&&V.... 26 7d bc f6 20 26 66 c2 95 24 ed 07 35 d8 65 a2 &}.. &f..$..5.e. a6 40 [email protected] [+] Parity for 5 bit chars: odd: False, even: False) [+] Parity for 6 bit chars: odd: False, even: False) [+] Parity for 7 bit chars: odd: False, even: False) [+] Parity for 8 bit chars: odd: False, even: False) [+] Frequency analysis for potential char lengths: [-] 5 bits: 10011: 5 11000: 4 01100: 4 00110: 4 00100: 4 [-] 6 bits: 100110: 5 100010: 5 011000: 5 011001: 4 001001: 4 [-] 7 bits: 1000100: 3 0010011: 3 1101100: 2 1100010: 2 1011010: 2 [-] 8 bits: 00100110: 12 < common 8-bit patter implies 8-bit chars? 10100110: 3 ...snip...
以上数据来自实际的酒店钥匙卡。
我还开始关注了XORing、旋转字符(rot13格式),位顺序和偏移的整个位流(是为了防止我在错误的位置开始时将字符组合起来)。位流(bit stream)就是一个连续的位序列,表示在某个通信路径上串行(一次一位)传输的数据流。
分析到此为止,如果我能解码钥匙卡上的任何数据,我一定会及时发帖。我希望以明文形式查看我的房间号和结帐日期。
总结
以廉价的阅读器,耗时的来读取钥匙卡的过程非常具有挑战性,虽然没有达到目的,但我却编写了自己的代码,了解了matplotlib以及逻辑分析仪。如果你想了解更多有关磁条的信息请查看:
1.Samy Kamkar的magspoof工具,该工具可以帮助你的PC通过读头传输可能会很有用的坏数据。