RFIDler:一款定义RFID的读、写、仿真器的开源软件

很多类似于RFID这样的技术看起来都很神秘,实际上他是依赖于很多物理学原理的,比如”电磁感应原理”。是的,这些现象产生的各种信号足以令人发狂,看完这些模拟模拟信号后,我忽然发现二进制信息多么干净美丽。

所以我一直在找一个工具,可以把这些模拟世界转化成友好的数据,RFID就是主要的对象。近些年来,越来越多RFID/NFC产品出现了,可能在你的口袋里就有好几个这样的东西——比如,你的车钥匙、门的钥匙、信用卡等等。当然,他们都有各自的RFID阅读器可以读取他们的信息,但是我关心的是,有没有一个RFID阅读器可以读取所有RFID上的信息,并且这个阅读器还很小且很便宜。

凭心而论,似乎有很多阅读器都可以达到我的要求,你可以买个很简单的RFID USB阅读器,大概也只需要10-15英镑。但是之后你就会发现,这些便宜的阅读器几乎都只能阅读一个标准下的RFID,你需要很多个这样的RFID阅读器才行。也有像Proxmark3这样的可以阅读所有RFID的,但是价格不菲呀。当然PM3确实是值得一看的,它被称为“RFID界的瑞士军刀”。它能够阅读很多版本的信号,无论是高频还是低频,稍后我们也将用它来举个例子。

RFID标签

所以,在开始前,我们不禁要发问,RFID标签是用来做什么的呢?

基本上他有两个作用:

1.基本上所有RFID标签都是唯一的,都可以用来特定的标识自身

2.一些标签具有数据存储功能

围绕着这两个基本的作用,可以展开很多——标签是盲目的展现ID或者DATA内容吗?或者换一句话说,在构建他们的时候是否有做一些安全措施?这些存储的都是些简要的信息,因此如果你想写入更长更多的信息,标签是否有空间可以写入?在这篇文章中,我的目的是讨论一些模拟世界中一些基础的通信过程,并且尽可能的把它们显示出来。

RFID&感应现象

这些技术基本都是依赖于”感应现象”。简单来说就是RFID/NFC都是依赖于你去激励一个线圈,同时让另一个线圈靠近它,第二个线圈就会通过感应从第一个线圈获取到部分能量,即两个线圈很神奇的发生了耦合(或者说是电磁感应)。同时,第二个线圈很有可能将会影响到第一个线圈的电压,例如靠近第一个线圈,第一个线圈的电压就下降了,我们称这种现象为“阻尼现象”。这就是RFID的工作原理,总结来说就是:线圈间相互的沟通是通过发送能量(从阅读器发出),或者引起了另一个线圈的能量变化(从RFID标签)来进行的。

在本文中,为了能得到更多的细节我们将会使用最简单的方式标记RFID标签——直接通过一个ID来识别,同时我们要先构建以下环境:阅读器通过反复激励线圈给线圈供能。作为一个标准的低频系统,它的频率将会是每秒125000次,也就是125KHz,这些被称为”载波信号”。RFID标签线圈被放在一定区域内的时候,将会从产生一些能量,变成电感耦合线圈并且进入激活状态。如果阅读器想要发送一个”唤醒(或者其他)”命令,可以通过开关把载波信号的电源关闭很短的一段时间。就算标签失去了电源,它依然可以依赖储存的能量继续工作一段时间,我们可以很容易的通过改变载波信号之间的缺口长短就可以代表0和1两种信号,基于这一特点,阅读器就能发送二进制信息了。

换一句话说,他们是通过幅移键控(ASK)来承载信息的,调整信号的振幅来代表不同的数据。更精确的一种方式是开关键控(OOK)。从阅读器发送给标签的信息被设计成ON和OFF两种载波,返回的信号响应的为阻尼和非阻尼两种。

信号分析

说了这么些个,大家好像一脸懵逼的样子,事实上我翻译的也有点懵逼了=。= 为了更容易理解,接下来我们用图来说明。下图是一个在示波器下观察到的125KHz的载波:

接下来是阅读器给标签发送的一个信号:

这种情况是,用一个长脉冲代表’1’ 用一个短脉冲代表’0’,因此,这里的信号的意思就是’11000’,或者如果你用HITAG2算法的话,意思就是’START_AUTH’

正如我们提到的,标签也会给阅读器返回信息,它是通过短路自己的线圈使阅读器的线圈发生阻尼现象。结果如下图:

这看起来好像是阅读器本身发送了一条信息。但是请注意,阅读器发送的波幅度一直在变化,但不可能减小到没有。相反,它要么是一个阻尼波要么是一个非阻尼波。这是因为并不是直接通过控制阅读器线圈上的电压达到的效果,而只是通过感应来影响波形。但它依然是可以读的。这个时候,如果我们把阻尼作用当成是”1”,非阻尼作用当成是”0”,我们就能得到’1010101010010110011010’,这也就是曼彻斯特编码的方式。

那么,曼彻斯特编码要做的事情是什么呢?好,这个时候它就开始变得有趣了——如果你仔细观察下这些不同规格标签,你会发现他们提到很多种调制方案,例如“曼彻斯特(Manchester)”,“双相(Bi-Phase)”,“移频键控(FSK)”,“相移键控(PSK)”,‘NRZI’,‘ASK’……

我们准备的设备只能做ASK,那 FSK/PSK/Manchester malarky这些方案是怎么样的呀?

这也是我一直很混乱的地方。如果你想做一个和现有供应商制定的RFID不一样的产品,恭喜你,你掉坑里了,因为各种调试方案是相互冲突的。尤其是想找出能解调所有方案的阅读器就更难了——如果你想找到一个阅读器可以访问到所有编码方式的数据,那是不可能的。如果阅读器想要进一步解调发送的信号。他们需要先确定信号是用什么方式编码的,为了达到这个目的,阅读器首先需要知道他们即将接受的标签是采用哪些方式编码的。

事实上我需要的仅仅只是最简化的RFID阅读器,所以只需要能得到一些最低等级的数据就可以了,但很奇怪的是,居然没有现成的。每一个调试方法都是一个不同的电路,而且网上的这些电路看起来就是用来炫耀的,比如这篇200页的文档

http://ww1.microchip.com/downloads/en/devicedoc/51115f.pdf

在一通乱找之后,我们找到了一个比较简单的设计:全世界最简单的RFID阅读器(链接:http://forums.parallax.com/showthread.php/105889-World-s-simplest-RFID-reader)。这有一个改进版的”DIT一个FSK的RFID阅读器”(链接:http://playground.arduino.cc/Main/DIYRFIDReader )。事实上,这些其实也并不很符合我们期待的那样。

我们使用PM3来阅读不同型号的标签发出的原始数据,PM3将作为阅读器的线圈,并且过滤掉载波,留下阻尼的影响。

下面是ASK调试信号:

正如我们所想的的那样,一个简单的由载波的阻尼和非阻尼影响产生了一个方波。

下面是FSK标签:

注意两种不同脉冲的形状,一个是瘦的,另一个长得比较胖。这样我们就能看到不同频率的脉冲了。

接下来的是PSK:

好吧,我也要疯了,这究竟是什么鬼???

首先,图中绿色的线表示标签的阻尼/非阻尼影响下的阅读器线圈上的电压。我们并不需要知道具体的代表什么,只需要知道屏幕地步是0V电压,或者说是全阻尼,而屏幕顶部是某一个电压值,或者说是无阻尼状态。电路产生的是125KHz的载波,并且可以提高或者降低输出。至于说他具体是怎么工作的,我他妈才不管,这是芯片的事情。

现在我们知道了每条线的意思,问题就剩下了这些线为什么会是这样形状的。第一个例子很简单:ASK/OOK调制不是ON就是OFF,因此我们在无阻尼的时候在屏幕顶部得到一条线,而在阻尼的时候,就会在地步得到一条线。

如下图,标签在阻尼阅读器线圈的地方我用红色标记出来了:

接下来让我们分析下FSK的:

现在,不是简单的用0和1表示阻尼了,我们用每个波的不同的周期来重新代表了经过阻尼和非阻尼的载波。如上如,红色标记一个波的一个周期。脉冲的宽度和数量携带了这段波要表达的内容。

好了,那么,最疯狂的PSK呢??

在相移键控中线圈的阻尼和载波的频率有关。在本例中,它会正好变成速度的一半,因此,它正好阻塞一半的载波脉冲,而大部分时间产生的信号都无法强到直接是结果到达屏幕顶部,同时也不会低到到达屏幕底部,而是正好在中间。然而,只要有相位的变化,只要有半个bit的变化就意味着阻尼和非阻尼的在一个载波周期内发生了变化,因此,我们可以看到一个小的跃迁,或者跃降。如图中的粉红色部分,表示阻尼了50%的时间,正常的相移是红色和黑色部分。

我们可以看到完全阻尼部分的低峰值和非阻尼时候的高峰值。这用肉眼很难读出来,但基本的相位变化(只要相的方向变了),bit值就发生变化,这点可以很容易观察到。相位如果不变的话,就是bit值保持不变。Bit的位数取决于相保持不变的时间,因此,只要在图中加上一个网格纸,你就能知道载波的周期了,通过这样的变化,你就可以得出比特流了。

假设我们开始的时候是“0”,那么我们通过上图就能得到如下比特流:

01101010001111100111000100010110000111010011100101101100001

好吧,确实有点难以理解。

但是好像我们找的电路可以实现这样的工作。

然而事实证明并不能,还有以下两个问题:

1.它无法处理相移键控的下相位峰值问题。

2.在我们一开始玩的时候,就忽略掉了功能的问题,我们想做到更多的事情。

首先,为什么是只有一个阅读器,我们是否还可以有一个写入器?和其他的技术不同,RFID的阅读和写入是两个几乎没什么差别的东西。在阅读器向标签发送信号的过程中,可以发送”write” 和”data” 两种命令,这和阅读标签一样的简单。

然后,为什么只有一个写入器,我们是否还可以有一个模拟器?所有的问题都只是阅读器/写入器与标签之间的激励与被激励的关系而已。

基于以上的种种问题的解决,于是RFIDler诞生了,现在它活跃在Kickstarter上:

http://www.kickstarter.com/projects/1708444109/rfidler-a-software-defined-rfid-reader-writer-emul

所有的工程详细内容都在文章末尾的链接里了,是一个用少于30英镑做的低频RFID研究以及一个精简版的版本可以嵌入到自己的硬件项目,这个只有不到20英镑。

我已经开始一个基于PIC32的固件项目,它运行在上述UBW32 BitWhacker,好了,最后将端口添加到其他平台吧。

项目地址如下:

https://github.com/ApertureLabsLtd/RFIDler

*参考来源adamsblog.aperturelabs

时间: 2024-10-19 10:54:46

RFIDler:一款定义RFID的读、写、仿真器的开源软件的相关文章

java并发读&写文件

最近在看Brian Goetz 的<<Java并发实战>>,这本书有两个版本,电子工业出版社的译本很糟糕,建议使用机械工业出版社出版出版的书籍. 在看到第三四章的时候突然想到了多线程读写文件,同时遇到一些书中没有的问题 1, 如何保证组合对象的安全性? 2, 如何判断不变性的约束条件 3, 如何不通过synchronized关键字和锁进行同步处理? 下面是一段代码, 用来从source 读取数据,通过多线程写入target文件中 思路: 1, 如何read/write文件? 2,

ubuntukylin基础 chmod 对一个文件的所有者,用户组,其他人分别添加或删除 读 写 执行 的权限

镇场文:       学儒家经世致用,行佛家普度众生,修道家全生保真,悟易理象数通变.以科技光耀善法,成就一良心博客.______________________________________________________________________________________________________ 我的系统:UbuntuKylin 16.04 LTS 64bit step0: 查看指定文件的权限 step1: 减去所有者的 读 写 执行的权限 step2: 查看执行效果

Hive整合HBase——通过Hive读/写 HBase中的表

写在前面一: 本文将Hive与HBase整合在一起,使Hive可以读取HBase中的数据,让Hadoop生态系统中最为常用的两大框架互相结合,相得益彰. 写在前面二: 使用软件说明 约定所有软件的存放目录: /home/yujianxin 一.Hive整合HBase原理 Hive与HBase整合的实现是利用两者本身对外的API接口互相进行通信,相互通信主要是依靠hive-hbase-handler-0.9.0.jar工具类,如下图 Hive与HBase通信示意图 二.具体步骤 安装前说明 1.关

asp.net 文件操作小例子(创建文件夹,读,写,删)

静态生成要在虚拟目录下创建文件夹 来保存生成的页面 那么就要对文件进行操作 一.创建文件夹 using System.IO; string name = "aa"; string path = Server.MapPath("") + "\\" + name; if (Directory.Exists(path)) { Response.Write("<script>alert('文件夹已存在了!');history.go(

C?#? ?读?写?S?Q?L?数?据?库?I?m?a?g?e?字?段

数据库的Image字段保存的是字节,所以写入数据库Image字段和从数据库Image字段读取的内容都应该为字节. 1.数据库Image字段读写文件      写文件:写文件的过程为将文件以流文件形式打开并将内容读取到一个byte数组,然后将此byte数组写入数据库的Image字段. 源码:     FileInfo finfo=new FileInfo("文件名");   //绝对路径 if(finfo.Exists) {         SqlConnection conn=new 

Python 文件(读\写)操作

文件(读\写)操作 open()函数,用来打开文件,创建file对象.open(name[,mode[,buffering]])name:要打开的文件mode:是打开文件的模式(读.写.追加)buffering:是否要寄存,默认为0或者False(不寄存),1或True表示寄存(意味着使用内存来代替硬盘,让程序更快,只有使用flush或者close才会更新硬盘上的数据),如果大于1表示寄存区的缓冲大小(单位:字节),如果是负值,表示寄存区为系统默认大小. open函数中模式参数的常用量:r 读模

Pandas 基础(4) - 读/写 Excel 和 CSV 文件

这一节将分别介绍读/写 Excel 和 CSV 文件的各种方式: - 读入 CSV 文件 首先是准备一个 csv 文件, 这里我用的是 stock_data.csv, 文件我已上传, 大家可以直接下载下来使用. 正如前面讲过的, csv 文件可以放在 jupyter notebook 同目录下, 这样直接写文件名就可以了, 但是如果没有放在同目录下, 就需要写绝对路径, 否则读取不到. import pandas as pd df = pd.read_csv('/Users/rachel/Sit

用于读/写配置的工具,下面列出了各种配置(从最高优先级到最低优先级)

代码写法: 1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.Enumeration; 6 import java.util.HashMap; 7 import java.util.Properties; 8 9 import org.slf4j.Logger; 10 impo

java读/写文件

读取文件参考:https://blog.csdn.net/weixin_42129373/article/details/82154471 写入文件参考:https://blog.csdn.net/BanketBoy/article/details/86504704 https://www.cnblogs.com/chenpi/p/5498731.html 1 package text; 2 3 import java.io.BufferedReader; 4 import java.io.Bu