RFID之M1卡資料分析

wyzsk發表於2020-08-19
作者: 321 · 2014/10/10 11:00

0x01契機


一直沒有機會也沒下定決心認真的去研究某個安全領域,很早之前就看到好多人研究RFID,一直很憧憬那片天空,趁著老大給機會,決定選這個方向作為個人業餘努力的方向。 差不多四天前入手了ACR122U,決定拿自己母校的餐廳飯卡練手。 ACR122U的使用很簡單,只要安裝上驅動,使用M1卡服務程式就可以很快破解,破解完成後檢視其生成的dump檔案,找到加密扇區的密碼,將密碼匯入到MCT (Mifare Classic Tool),剩下的就可以完全使用MCT完成了,個人很懷疑破解過程是否完全可以透過手機(支援NFC)APP完成。ACR122U的詳細使用過程可以參考:RFID安全之某學校水卡破解,本文主要介紹目前M1卡中的資料分析和M1卡安全防護方案。

0x02背景知識


瞭解M1卡的結構可以知道M1卡共16個扇區,編號從0到15,每個扇區配備了從0到3共4個段,每個段可以儲存16位元組的內容。

0x03資料分析


閱讀《RFID安全之某學校水卡破解》可以發現該學校的水卡中資料儲存比較簡單,按照作者的分析,4號扇區的1、2號資料段(編號從0開始)儲存了水卡餘額,將已知的餘額32.31,換算為分為3231,再轉為16進製為C9F,即00000C9F,而0C9F取反為FFFFF360,這時比較下4號扇區的值,很容易發現規律:前四個位元組不取反倒序(9F0C0000)儲存餘額,接下來四個位元組取反倒序(60F3FFFF)儲存餘額,再接下來四個位元組不取反倒序(9F0C0000)儲存餘額。

enter image description here

上面提到的“倒序”,可以結合計算機資料儲存方式來理解:如下圖所示,變數a儲存的資料對應的16進製為0A112233,變數b儲存的資料對應的16進製為0B445566。

enter image description here

這樣就很明顯了,5634120A,就是變數a所代表的資料的十六進位制0A123456的倒序。 作為入門教程,個人認為《RFID安全之某學校水卡破解》是非常不錯的。看完這個教程,並實踐結束後,我停下來思考這樣一個問題:M1卡的密碼破解是傻瓜式的,當然也有文章介紹破解原理,但是作為門外漢,目前我還不是特別關心,我只想找到那種破解成功,可以修改金額的快感!那麼在整個M1卡的破解過程中,我自己到底起了什麼作用?答案是卡片的資料分析。 《RFID安全之某學校水卡破解》中的資料分析並不難,只要知道水卡的餘額就可以定位卡片中餘額資料的儲存位置,細心的讀者肯定可以發現文中的截圖5號扇區也存在非0值塊,作者在《RFID安全之某學校水卡破解後記——不留後患》中作了進一步分析;《任意修改學校食堂飯卡餘額》這篇文章所描述的卡片和《RFID安全之某學校水卡破解》的分析非常相似;而另一篇《破解學校水卡---||||RFID Hack初探 》文中的資料就更簡單了,只有餘額和消費金額之和,連取反的校驗都沒做。 分析了幾篇圖文教程式入門文章,加上自己的實際破解過程,總結了一下資料分析的經驗。 首先,需要收集資訊,然後可以透過資料比對法定位餘額,如果卡片資料採取了校驗保護,可以採用試錯法進行排查定位,正如《RFID安全之某學校水卡破解後記——不留後患》中所用到的方法。

0x03.1比對法

比對法,就是將已知資料換算成十六進位制,尋找卡片中能與之對應的資料,從而確定卡片中對應的儲存位置所儲存的資料的意義,或者將卡片中變化的位元組轉成十進位制,判斷是否存在相應的資料資訊。 最常用的比對值當然是卡片餘額,還有當前的消費金額,或者是累計的消費金額,這兩個資料有出現在前文的引用文中。那麼除了這些,還應該考慮哪些資料呢?這裡我作一個簡單的羅列:消費次數、日期、時間、讀卡器編號、卡號(非UID)等 之所以認為上面的資料可以儲存在卡片中,是因為兩個位元組(16bit),不考慮符號位,可以表示的最大數值是65535,一個位元組(8bit)可以表示最大數值為255。一張卡按四年有效期來算的話,每天要刷44次才能再四年內超過這個數值;日期也可以用兩個位元組來表示,可以選擇整體表示,譬如12月31日,記為1231,對應到16進位制04CF,也可以一個位元組表示月一個位元組表示日,仍然是12月31日,可以記為0C1F(1F=31);時間(不考慮秒)的最大表示數字是23:59,也可以參考日期的表示方式,選擇不同的方案;讀卡器編號,一般情況下一個單位也不會同時具有65535臺讀卡裝置;卡號,這裡卡號一般可以用兩個位元組表示,如果單位人數較多(超過65535),也可以使用四個位元組表示,卡號的意義可以標識一個人,也可以標識單位內的一個部門等。

0x03.2試錯法

試錯法就是針對一些不明意義的位元組(可能是校驗位元組),透過修改已知意義的位元組來確定其關聯性,找出不明意義位元組的計算方法。 資料比對法,有時並不能分析出所有資料塊的資料,這時可以考慮試錯法來確定隱晦資料和哪些欄位有關聯,譬如下面的案例: 卡片只有0號扇區有資料:

43 9A ** ** ** ** 04 00 46 BA 14 12 51 10 03 10             第0段
0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
11 01 ** ** ** ** FF 07 80 69 FF FF FF FF FF FF             第3段

第0段為廠商寫死的UID,不可修改,經過多次資訊收集發現第1段的資料是不變的,變化的只有第二段,經過比對法,發現第1段的4A 3D是卡號,第2段的01 C2是本次消費金額,0E A6是餘額,027D是消費和充值次數,081D是日期,到此,第2段中還有前四個位元組以及最後兩個位元組的意義不明。 下面透過試錯來定義各個位元組的意義 嘗試直接修改K1餘額,讀卡會失敗,於是認為刷卡消費過程存在驗證,餘額和消費金額並不能構成驗證對,所以認為驗證資訊在意義不明的6個位元組內。 只修改消費金額也會導致讀卡失敗。 嘗試使用K2的值整體替換K1的第2段,結果讀卡依然失敗。 最後嘗試使用K2的值,整體替換K1的第1和第2段,等價於複製卡片,終於讀卡成功了。 透過以上幾步,可以確定消費讀卡器在進行扣錢之前,會先校驗卡片的正確性,校驗值和餘額、消費金額以及第1段中的資料都有關聯。為了進一步定位資訊,做出如下試錯計劃:

1、修改卡號,確認卡片是否可正確識別; 2、逐個修改第2段中已知意義的位元組,確認卡片是否可正確識別,排除與校驗無關的位元組 3、對第2段中不明意義的6個位元組逐個修改,確認卡片是否可正確識別,排除非校驗位元組 4、對第1段中的3個不明意義的位元組逐個修改,確認卡片是否可正確識別 本質是就是對所有資料位元組進行試錯,排除與校驗無關的位元組! 透過以上過程縮小與校驗相關的位元組,再結合比對法中找出的已知意義的位元組,從而確定不明意義位元組的意義和校驗演算法。 由於刷卡條件限制,以上案例尚未破解完成,試錯法也有待該案例進一步驗證。 破解過程需要大膽猜測,努力求證!

0x04卡片防護


破解和防護是一對冤家,既然M1卡這麼容易被破解,那有沒有合適的防護方法呢?上一小節中提到的校驗案例就算是一個很小的防護手段,但是依然存在很大被破解的風險。 為了降低水卡和飯卡被破解的風險,同時又不增加替換M1卡的成本,可以完全加密資料欄位,基於金鑰和演算法保密性,保證即使可以透過驗證攻擊獲取到M1卡中的資料,駭客也無法快速判斷各個資料欄位的意義,從而無法完成餘額修改! 譬如,參考上一小節的校驗案例,如果所有資料再與一個2位元組的金鑰進行異或處理,這時就無法簡單的透過比對法判斷出哪些位元組是餘額、哪些是消費金額,進一步降低了破解風險。當然針對金鑰可以設計一套動態金鑰方案,效果類似支付寶令(需要考慮如何處理長期不使用的卡片),而加密演算法可以選擇更加複雜的對稱加密演算法,只要保證不會對消費刷卡機造成過大延遲即可。

0x05複製攻擊


資料加密雖然可以增加駭客分析卡片資料的難度,降低駭客惡意修改餘額的風險,但是無法應對卡片複製攻擊! 複製攻擊可能造成的後果是盜刷他人飯卡或水卡,這一點是最容易理解的,當然前提是駭客可以接觸到別人的飯卡或水卡。 除了這一點,複製攻擊是否還存在其它危害? 在分析這之前,需要明確幾個前提,1)刷卡機中會記錄哪些資訊;2)我們假設刷卡機沒7天向中央資料庫伺服器提交一次資料,刷卡機向中央資料庫提交的是哪些資料。 如果刷卡機只記錄一張卡片的最後一次消費記錄,那麼其向資料庫提交的資料必然要包含餘額資訊。如果在刷卡機兩次向資料庫提交資料的時間間隔內,利用複製的卡片(複製較早的卡片資料)做最後一次消費,那麼真實卡片消費的資料就會被覆蓋掉。 當然個人猜測目前的刷卡機應該會記錄卡號(非UID)、消費累計金額、消費次數,同步資料庫時只需要基於卡號找到對應的記錄,然後將餘額減去消費累計金額、總消費次數疊加本次提交的消費次數。這種情況下,複製攻擊就只能盜刷他人的飯卡或水卡餘額了,但是即使是這樣,如果不影響被複制的卡,也算是一種修改餘額的方式,畢竟刷卡機不會基於資料庫資訊向卡片寫資料! 本來以為複製攻擊就這些影響了,晚上睡覺前忽然想到,既然可以複製別人的卡,為什麼不能複製自己的卡呢。T1時間充值m元,並記錄下卡內的資料資訊D1,消費一段時間後,T2時間卡內餘額n元(n<m),此時將資料資訊D1重新複製回卡內,卡片資訊重新回到T1時間的狀態,等價於T1-T2時間段內沒做任何消費!這種情況即使是使用UID作校驗也無法防護了,除非刷卡機是線上實時查詢資料庫的,後來發現這種攻擊方式12年就有人提出了,並稱之為重放/重置攻擊

0x06後記


剛接觸RFID,有描述不準確或錯誤的地方,請輕拍指正!

0x07捲土再來


基於0x05節的分析和實際驗證,透過複製攻擊(重放攻擊)已經實現0x03.2節示例中卡片的餘額修改,但是為了論證 0x03.2節試錯法的可行性,規劃瞭如下方案:

43 9A ** ** ** ** 04 00 46 BA 14 12 51 10 03 10             第0段
0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段
11 01 ** ** ** ** FF 07 80 69 FF FF FF FF FF FF             第3段

針對以上資訊,對第1、2段內容,逐位元組進行試錯,確認卡片是否可讀 驗證結果如下: 1、修改第1段第0位元組

0D 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

2、修改第1段第1位元組

0C 0E 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

3、修改第1段第2位元組

0C 0D 0D 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

4、修改第1段第3位元組

0C 0D 0C 12 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

5、修改第1段第4位元組

0C 0D 0C 11 01 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

6、修改第1段第5位元組

0C 0D 0C 11 00 01 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

7、修改第1段第6位元組

0C 0D 0C 11 00 00 4B 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

8、修改第1段第7位元組

0C 0D 0C 11 00 00 4A 3E 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

9、修改第1段第8位元組

0C 0D 0C 11 00 00 4A 3D 01 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

10、修改第1段第9位元組 0C 0D 0C 11 00 00 4A 3D 00 2E 00 00 00 01 00 47 第1段 37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60 第2段

11、修改第1段第10位元組 0C 0D 0C 11 00 00 4A 3D 00 2D 01 00 00 01 00 47 第1段 37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60 第2段

12、修改第1段第11位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 01 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

13、修改第1段第12位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 01 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

14、修改第1段第13位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 02 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

15、修改第1段第14位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 01 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

16、修改第1段第15位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 48             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

17、修改第2段第0位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
38 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

18、修改第2段第1位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0C BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

19、修改第2段第2位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BD E4 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

20、修改第2段第3位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E5 01 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

21、修改第2段第4位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 02 C2 00 00 0E A6 02 7D 08 1D 05 60             第2段

22、修改第2段第5位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C3 00 00 0E A6 02 7D 08 1D 05 60             第2段

23、修改第2段第6位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 01 00 0E A6 02 7D 08 1D 05 60             第2段

24、修改第2段第7位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 01 0E A6 02 7D 08 1D 05 60             第2段

25、修改第2段第8位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0F A6 02 7D 08 1D 05 60             第2段

26、修改第2段第9位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A7 02 7D 08 1D 05 60             第2段

27、修改第2段第10位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 03 7D 08 1D 05 60             第2段

28、修改第2段第11位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7E 08 1D 05 60             第2段

29、修改第2段第12位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 09 1D 05 60             第2段

30、修改第2段第13位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1E 05 60             第2段

31、修改第2段第14位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 06 60             第2段

32、修改第2段第15位元組

0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47             第1段
37 0B BC E4 01 C2 00 00 0E A6 02 7D 08 1D 05 61             第2段

本來期望可以得到一個很不錯的結果的,甚至連測試結果位置都預留了,天不遂人願,畏畏縮縮的在一個視窗連刷了32次,每次都是讀卡失敗,這下鬱悶了,本以為破解只能止步於此了。 又拖了一週,感覺自己都沒激情了,只是偶爾抽時間看看之前收集的資料,卻總結出了下面的結果:

13 05 71 22 04 E2 00 00 01 54 03 15 08 19 0D FC         0E0E
13 05 71 22 27 10 00 00 28 64 03 16 08 19 0D 37         0404
59 04 71 96 04 E2 00 00 23 82 03 17 09 01 0D EC         6767
13 05 86 B3 04 E2 00 00 1E A0 03 18 09 02 0D 66         E7E7
13 05 89 8E 01 90 00 00 1D 10 03 19 09 03 04 99         E7E7
13 05 92 5C 04 E2 00 00 18 2E 03 1A 09 04 0D 11         F5F5
59 04 78 53 03 52 00 00 14 DC 03 1B 09 05 09 F2         3535

注:這是另一張卡上收集的資料,兩個位元組兩個位元組進行異或運算再與始終不變的第1段逐兩位元組異或 開始時,始終沒能搞清楚這個異或結果,今天突然想到,每兩個位元組進行異或的結果出現的是兩個相同的位元組值,那麼逐個位元組異或豈不就是0,經此確認,試錯法終於可以再次登場了,結合之前的32次試錯,大膽猜測卡片的校驗過程:第1和第2段逐位元組異或為0。 現在明確了卡片關鍵的兩段資料逐位元組異或為0的校驗條件,再次進行如下試錯測試: 前提:當前卡片資料(消費讀卡器可識別)

43 9A 5D A7 23 88 04 00 46 BA 14 12 51 10 03 10     第0段
0C 0D 0C 11 00 00 4A 3D 00 2D 00 00 00 01 00 47     第1段
26 02 99 63 01 2C 00 00 0D 7A 02 7E 08 1F 03 EC     第2段
11 01 08 46 04 20 FF 07 80 69 FF FF FF FF FF FF     第3段

1、嘗試修改第一段中的資料

1.1 4A3D-->5324                                         結果:不可讀
1.2 4A3D-->4A3E 0047-->0044                         結果:可讀

2、修改第二段中的資料 2.1修改第二段中的最後兩個位元組:

03EC-->00EF     結果:可讀

2.2修改第二段中最前面的兩個位元組:

2602-->2400     結果:可讀

2.3修改第二段中第三四個位元組:

9963-->966C     結果:可讀

2.4整段替換第二段:

26 02 99 63 01 2C 00 00 0D 7A 02 7E 08 1F 03 EC3-->13 05 86 B3 04 E2 00 00 1E A0 03 18 09 02 0D 66

結果:可讀,金額變化一致;卻與之前的一次實驗結果衝突!

透過上面的試錯,基本可以明確針對第2段的校驗過程:逐位元組異或,判斷結果是否為0。為進一步驗證猜測,構造如下資料:

1E 02 66 83 02 3C 00 00 EF C4 03 FF 08 FF 03 E4

這條人為構造的資料,餘額為613.8元,消費金額為5.72元,消費日期為一個不存在的日期,如果該該資料能夠校驗透過,那麼破解基本就可以結束了。 1E 02 66 83 02 3C 00 00 EF C4 03 FF 09 1E 03 04,如果上一條不能成功,則嘗試該日期正確的資料。 經過驗證,隨意構造的兩條資料都成功修改了卡片餘額,如下圖:

enter image description here

到此,卡片的破解算是告一段落,雖然遺留了一下問題: 1、整體替換兩次實驗結果衝突? 2、第2段中的前四個位元組以及最後兩個位元組的資料是如何產生的? 第一個問題可能是自己粗心造成的;第二個問題並不影響卡片破解。

0x08小結


透過上面的例項分析,再次總結卡片破解過程中資料分析的兩大步驟: 1、資料比對 收集多組資料,結合消費金額、餘額、日期、消費次數等已知資訊確定資料段中各個位元組的含義 2、試錯分析 在直接修改餘額出錯的情況下,逐位元組或整體試錯,確定校驗相關位元組,並猜測校驗演算法,一般情況下,校驗演算法是可逆演算法,位元組運算一般主要考慮異或運算;然後透過試錯進行論證;最後自己構造資料實現卡片餘額修改,完成破解。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章