内容简介:金诚卡这个东西说熟悉的人很熟悉,说不熟悉的人压根就没见过,国内有很多高校都用这款水卡。 这款水卡有两个版本,下图是旧版本的金诚卡(非全加密),另一个版本长的比这个丑(全加密)。虽然全加密和非全加密感觉安全性改善了很多,但是由于其加密密钥,加密方法并没有变化所以还是可以通过旧卡分析出来算法。当然完全可以通过 mfcuk 得到完整的密钥,实现通用修改毕竟算法并没有改变。
*本文内容仅用于技术讨论,严禁用于任何违法用途。
一、引言
金诚卡这个东西说熟悉的人很熟悉,说不熟悉的人压根就没见过,国内有很多高校都用这款水卡。 这款水卡有两个版本,下图是旧版本的金诚卡(非全加密),另一个版本长的比这个丑(全加密)。虽然全加密和非全加密感觉安全性改善了很多,但是由于其加密密钥,加密方法并没有变化所以还是可以通过旧卡分析出来算法。当然完全可以通过 mfcuk 得到完整的密钥,实现通用修改毕竟算法并没有改变。
二、卡内数据结构一览
首先我们看一下旧卡的(非全加密卡),通过几张卡对比就能发现是一卡一密。
旧卡是12扇区有数据,新卡的话也是12扇区有数据,但是在别的扇区也增加了一些个人信息的数据(估计是如果有人破解了好抓人)。可以看到只有12扇区的KEYA不是默认密钥,其余均为默认密钥。于是我们学校好多人就动起了歪心思。毕竟acr122u这种设备已经泛滥,也不管三七二十一就克隆写入到白卡开始卖(也不分析下卡的数据),然后一个个全被抓(该!)。而新卡为全加密,数据的扇区和块均保持不变。但是密钥的算法还是保持不变的。
Ps.上面这个数据是我在网上收集的,还修改了涉及到学校代码的信息。
三、金钱区块算法分析
12扇区0块为金钱值,通过最没有技术含量的对比法分析哪个位置是金钱的。所以可以得到第5、6、7组 是明显变化的。所以判断这三个和金钱有关。
01 15 02 00 21 86 B1 F1 FFFFFFFFFFFFFFFF |
---|
01 15 02 00 21 85 B2 F1 FFFFFFFFFFFFFFFF |
01 15 02 00 21 84 B3 F1 FFFFFFFFFFFFFFFF |
但是之前还有01 15 02 这三个代码,考研报名的时候就经常见到这个代码(本文代码是假的)。这摆明了就是学校的代码嘛。合着水卡的信息还包含学校代码。
21 86从十六进制转换成10进制,竟然和卡里的钱数*100后一样,所以5 6组就是金钱的位置。那么第七组就是校检位了,防止篡改数据。想想Ic卡最常见的校检方法,结果还是2位。于是我推测是每一组每一组进行异或运算。果真01^15^02^00^21^86的结果是B1。原来学校代码的作用是这个啊,防止跨校买水么。于是此阶段水卡的金钱扇区就解密了。
四、一卡一密解密
这部分不敢太详细说,怕教坏别人。但是通过金钱区块的分析得到生成校检位的是异或运算。那么KEYA是不是也是通过异或得到的?还有为什么KEY结尾四位都是固定的?前面8位变化?uid也是8位?是不是KEYA是根据UID计算出来的+固定值?异或好像是可逆运算啊!这段就说到这里了。
五、大头来了,自制硬件设备
有了KEYA计算规则,还有校检生成方法。可以完美的对任何一张水卡进行充值了(包括新卡,因为除了全加密了其余并没有改变)。
硬件设备包括:
0.96的OLED一个 (i2c) esp8266nodemcu v1.0 的开发版一个 Rc522模块一个 (spi)
其实本来想用arduino的,但是手头有个不用的esp8266就干脆用上了,把它看作arduino就行了。接线按照下图接入spi和i2c就行了,没啥难的。(主要是我画的电路图太丑了 拿不出手)下图是esp8266的引脚定义,如果你也用esp8266那么可以参照这个。
我自己接完之后长这样。背面我就不拍照了,太丑了,焊工渣死。
代码如下,请注意看注释:
#include <Adafruit_GFX.h> #include <Adafruit_ssd1306syp.h> #include <SPI.h> #include <MFRC522.h> #include <Adafruit_ssd1306syp.h> #define SDA_PIN 4 //定义oled的data #define SCL_PIN 5 //定义oled的clock #define RST_PIN 10 // 定义rc522的rst #define SS_PIN 15 //定义rc522的ss (其余的就参照spi和i2c对应的引脚就行了 rc522的RQ悬空 不用接) MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建MFRC522实例 Adafruit_ssd1306syp display(SDA_PIN, SCL_PIN); //创建oled显示实例 MFRC522::MIFARE_Key keyA; /** Initialize. */ void setup() { delay(1000); display.initialize(); Serial.begin(9600); while (!Serial); SPI.begin(); mfrc522.PCD_Init(); pinMode(D0, OUTPUT); //这个是设置板载的LED为输出端口 digitalWrite(D0, HIGH); //这个LED高电平亮低电平灭 所以拉高。 display.setTextSize(3); //欢迎界面 display.setTextColor(WHITE); display.println("WELCOM"); display.update(); delay(3000); } /** Main loop. */ void loop() { display.clear();//清空显示 //寻找新卡 if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } //选择一个卡 if ( ! mfrc522.PICC_ReadCardSerial()) { return; } //读取uid并byte2string String UID = ""; for (byte i = 0; i < mfrc522.uid.size; i++) { UID.concat(String(mfrc522.uid.uidByte[i], HEX)); } UID.toUpperCase(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0, 0); display.println(UID); //计算key 这块结合着前面看,已经很清晰的知道怎么计算KEYA了 keyA.keyByte[0] = mfrc522.uid.uidByte[0] ^ 0x**; keyA.keyByte[1] = mfrc522.uid.uidByte[1] ^ 0x**; keyA.keyByte[2] = mfrc522.uid.uidByte[2] ^ 0x**; keyA.keyByte[3] = mfrc522.uid.uidByte[3] ^ 0x**; keyA.keyByte[4] = 0x**; keyA.keyByte[5] = 0x**; String KEY = ""; for (byte i = 0; i < 6; i++) { KEY.concat(String( keyA.keyByte[i], HEX)); } KEY.toUpperCase(); //display.print("KEY:"); // display.println(KEY); //display.update(); byte sector = 12; //扇区 byte blockAddr = 48; //扇区开始块 金额地址 MFRC522::StatusCode status; //状态码 byte buffer[18]; byte size = sizeof(buffer); // 在trailerBlock块中 使用身份验证密钥A Serial.println(F("Authenticating using key A...")); status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockAddr, &keyA, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { //如果状态!=成功 display.println("failed"); display.println(mfrc522.GetStatusCodeName(status)); //输出状态 return; } //输出指定扇区当前内容 status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size); if (status != MFRC522::STATUS_OK) { //如果读取错误输出错误信息 display.println("failed"); display.println(mfrc522.GetStatusCodeName(status)); //输出状态 } int IntMoney = buffer[5] | buffer[4] << 8; //byte2int display.print("old:"); display.println(IntMoney / 100.0); IntMoney = IntMoney + 1000; buffer[4] = IntMoney >> 8; buffer[5] = IntMoney; int IntMoney1 = buffer[5] | buffer[4] << 8; //int2byte buffer[6] = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5]; //计算校检位 status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, buffer, 16); if (status != MFRC522::STATUS_OK) { //如果写入失败返回错误状态码 display.println("failed"); display.println(mfrc522.GetStatusCodeName(status)); //输出状态 } //再读一遍 显示读取后的钱 status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size); if (status != MFRC522::STATUS_OK) { //如果读取错误输出错误信息 display.println("failed"); display.println(mfrc522.GetStatusCodeName(status)); //输出状态 } IntMoney = buffer[5] | buffer[4] << 8; // display.print("new:"); display.println(IntMoney / 100.0); mfrc522.PICC_HaltA(); // Stop encryption on PCD mfrc522.PCD_StopCrypto1(); display.update(); digitalWrite(D0, LOW); delay(500); digitalWrite(D0, HIGH); }
这是烧录后的效果,测试效果是刷一次增加10元,下一步准备把wifi利用上,毕竟不能浪费了wifi功能。最后,请大家不要利用本文干坏事哟!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【蓝牙安全】蓝牙安全测试环境搭建(硬件设备篇)
- Fuchsia 设备出现,谷歌正对其进行蓝牙测试
- web测试-ios设备模拟器(iOS Simulator)
- 爆料:苹果正在测试带有Face ID的触摸屏Mac设备
- 通俗易懂--决策树算法、随机森林算法讲解(算法+案例)
- 限流算法之漏桶算法、令牌桶算法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。