校园卡内部数据结构研究

试周前,我在 CC98 上阅读了一个有关复制校园卡门禁功能的帖子,帖子里有一名学长推荐了学校中的一位技术型博主,在这位博主的博客中有两篇讲解校园卡的文章。今天刚刚结束考试周,在这仅有的半天空闲时间里(光电学院长达一个月的小学期,你值得拥有),我终于认真阅读了这位博主的文章,收获颇多。对于校园卡功能的实现,在大二下的春学期,我在物联网相关课程上进行了比较深入的学习,对 RFID(射频识别)有了较为清晰的认识。在实验中也对 RFID 卡进行了一波写入数据设置门禁的操作。其实现在也差不多忘干净了

校园卡内部构造

我们每天进出宿舍楼,去食堂吃饭,到超市买东西的时候都会用到校园卡,但很少会有人研究校园卡里面到底长什么样子。

将校园卡放置在强光下,可以看到内部的芯片和线圈。

zjuidcard-internal-circuit.jpg◎ 校园卡内部线路

(说句题外话,我用的这个校园卡还是当年随录取通知书一起寄过来的那一张,从来没丢过,也从来没补办过,校园卡表面的图案层已经刮花,伤痕累累。)

在机制上目前已知的东西

  • 每次刷卡都一定会连接服务器端确认数据(如是否冻结)。
  • 卡的密码有两份存储,卡上 [0x96 0x97 0x98] 和服务器端,正常仅读取卡中的密码,仅当补办卡时会对新卡写入服务器端密码。
  • 金额则有三份存储,卡中一份、服务器端 cache。
    • 卡中:在卡消费时被读取和改写,被加密,算法目前无法破解。
    • 服务器 cache:余额可以在网上被查到,此余额我叫它 cache 是因为它 等于最近一次消费后卡中的金额 。即不管卡中金额是多少,服务器 cache 的金额都会根据卡中的金额被赋值,注意是赋值而不是根据消费/充值额增减。
    • 服务器对账:每星期四 23:59:59(避免歧义),服务器会重新将上次对账时卡的余额累加上这星期卡的消费/充值,得出一个正确余额,并和服务器 cache 值对比,若两者相差过大(阈值在 15 元左右),则冻结卡。
    • 从已知的信息来看,不能用校园卡来刷钱。
  • 门禁、体育打卡机(固定和移动)都不读取卡内数据,而只根据卡 UID 来识别用户。
    • 只有 UID 的空卡不能用来付钱和充值。(猜想)若多次试图刷空卡付钱,可能会导致冻结。
    • 有一种不需要接触卡就能得知卡 UID 的简便方法,为避免滥用,此方法保密。
  • 每次在 POS 机上付钱时不仅会改变 4 个 [0x80 0x81 0x8C 0x8F] 余额记录字节,也会改变 [0x88 0x89 0x08A] 这三个字节。
    • 但是洗澡机上刷卡并不改变后者三个字节。
    • (猜想)可能是记录刷卡序号一类的东西,可能和对账有关。
  • 每个人的卡区块密码都不一样。
    • 除了扇区 15 的 KeyA 都为「synpub」的 ASCII 码。但是有人的卡里没有扇区 15。删除自己卡中的扇区 15,卡各种功能都正常。

校园卡数据结构表

感谢原博主对校园卡内部结构研究做出的努力。

由于校园卡样本数量有限,有一些字段(如记录学园、专业、是否是本科生之类的)无法弄清楚。

zjuidcard-data-structure.png◎ 校园卡数据结构表

加载评论
点击刷新