在這篇文章中,我描述了為什么我的廉價的磁條閱讀器不能讀取所有的磁條,只有信用卡和借記卡。這并不能幫助我了解酒店鑰匙卡上的數據,而這正是我真正想要知道的。我沒有特意地去購買更好的閱讀器,而是選擇了打開廉價的磁條閱讀器,略作探索,找到了一種從酒店鑰匙卡讀取原始數據的方法。這些數據意味著什么,仍然是個謎,因此在某個時候我可能會發布文章的第二部分。
我在2017年以11.85英鎊購買了以下閱讀器:
來自eBay的廉價閱讀器
它通過USB連接,被檢測為鍵盤。如果你通過閱讀器刷信用卡/借記卡,那么文本編輯器就會像得到輸入指令一樣顯示來自磁條的相應數據。如果你當時沒有打開文本編輯器,你將看不到磁條上的任何信息。
它在Windows和Linux下都能正常工作,但僅適用于信用卡/借記卡。當我刷酒店鑰匙卡時,我什么數據都沒有得到。
我本可以采取一些不同的(毫無疑問更好的)方法來實現這個項目,找一個更好的磁條閱讀器就是其中一種選擇。通過谷歌搜索來更好地了解酒店磁條無疑是最有成效的方法,但可能會降低一些我們解決問題的能力。當我被卡住時,我總是可以通過谷歌搜索來解決。
我投資了一臺MSR605X讀寫器。我之前沒有使用過它,但它能夠做原始讀取。我可能會在以后的文章中對它進行介紹。
我認為廉價的閱讀器中的磁讀頭幾乎肯定能夠從酒店鑰匙卡或任何其他帶有磁條的卡中讀取數據。但實際上,它們只能讀取支付卡數據。如果我可以在閱讀器內的正確位置探測電子信號,我應該能夠看到磁條上的1和0代碼信息。
閱讀器內的磁讀頭
我只有一個模糊的計劃,當然不會是阻力最小的道路,但最終會有成效……
我有兩種工具可以使用(這是一個基于家庭的項目,而不是基于辦公室的項目):
l? 廉價的手持式示波器(Sainsmart DS202)
l? Saleae Logic邏輯分析儀
我很快意識到,我可以把探頭連接到讀頭上,上面有7個連接點。
讀頭背面的連接點
我想,如果將讀頭直接連接到我的示波器上,我就可以在刷卡時看到模擬信號。最終,我希望用這個信號做一些事情來獲取我想要的數據。
將讀頭直接連接到示波器上
我嘗試將這7個探測點以不同的組合連接到我的示波器,但根本沒有發現任何信號。也許是信號太弱了,或者(回想起來)我做的探測工作還不到位。
至此,我只能在去谷歌搜索更多關于芯片的信息了。它有一個2倍運算放大器和一個1倍模擬比較器:
l? 2xLM2902DG(運算放大器)
l? 1xLM2901DG(模擬比較器)
2倍運算放大器
模擬比較器(左),STM32微控制器(右)
這些芯片負責放大來自讀頭的信號。因此,如果連接到每個輸出,我可能會看到一個信號,我可以用它來確定磁條上的數據。為此,我通過使用數據表來識別每個芯片的輸出引腳。
2倍運算放大器的輸出峰值為0.5-0.6v,使用我的示波器可以輕松查看,但我無法將其提供給我的邏輯分析儀。我需要大約3v的峰值。信號看起來也很沒有規律,不是我希望的方波。
模擬比較器的輸出正是我所追求的。一個不錯的3或4v的峰值方波,僅在我刷卡時出現。這時,比較器有4個輸出,其中一個從未發出信號,對于可以讀取3軌磁條的讀頭來說,這似乎是合理的。是時候將它提供給邏輯分析儀,并開始計算由0或1構成的信號的內容了……
到目前為止,進展非常快。這正在形成一個有趣的項目。
這是Saleae Logic軟件中比較器的輸出:
通過邏輯分析儀查看比較器輸出
請注意,我們只看到1個方波,而不是3個。這是因為這個特定的鑰匙卡在3個軌道中的只有1個有數據。
所以,我們只有一個信號要分析,但我們還沒有計算出信號的內容。
1992年的Phrack37給了我們幫助:
關于1和0如何在磁條上編碼的ASCII解釋
本質上0和1在編碼時都是相同的長度。只是1改變了狀態,而0沒有改變狀態。注意,0可以是高的或低的。
我沒有僅通過觀察來解碼1和0,而是編寫了一個Python腳本,它解析了邏輯分析儀中導出的數據并轉儲了1和0。以下是導出為CSV時“Logic”(Saleae軟件)使用的格式:
從Saleae的Logic軟件導出CSV格式
由于數據的波特率不是常量,因此編寫Python代碼很難。它取決于鑰匙卡劃過讀頭的速度。在編寫代碼時,我因為一些錯誤而走了彎路,但最終找到了一個有效的解決方案。
這是一個散點圖,所顯示的方波脈沖的持續時間并沒有預期的兩個值。相反,可以看到各種范圍的值。它仍然可以從1(短脈沖,藍色/紫色點)到0(長脈沖,綠點),見下圖(上)。每個連續脈沖與最后一個脈沖的比率是從1到o的,見下圖:
圖表顯示脈沖持續時間(delta)需要多少值,而不是預期的兩個值
正如在phrack論文中提到的,信用卡使用2個軌道,其中一個字符由5位(4位+ 1個奇偶校驗)組成,另一個字符由7位(6位+ 1個奇偶校驗)組成。
我花了很多時間來編寫信用卡解碼器。部分原因是因為我需要確定我正確讀取了1和o,另一部分原因是因為我認為我需要代碼來查看酒店鑰匙卡中是否使用了相同的字符類型。
對此進行編碼的挑戰之一是需要知道數據的開始位置和前導碼何時結束。似乎“Sentinel?”命令可用于標記數據的開始/結束。這些是特殊字符(位模式),讀者可以在條帶的開頭和結尾查找…然后它才會有意義。這就是閱讀器只能用于信用卡的原因:固件正在尋找信用卡使用的標記。它無法解碼酒店鑰匙卡,因為數據的開始或結束位置并不明顯或數據沒有構成一個什么進程。此外,可能缺乏有效的縱向冗余校驗(LRC)。
我在酒店鑰匙卡的磁條上運行了我的信用卡代碼,看看是否有所有5位或所有7位的奇數奇偶校驗。不幸的是,沒有。這可能是廉價的磁條閱讀器失敗的另一個原因。
然后我對1和0進行了一些頻率分析。由于很多5位和7位的值都有自己的特點,我在信用卡磁條上看到了它們各自對應的內容。7位磁條上有20個空格。因此,使用頻率分析,我應該能夠猜測到正在使用7位字符。
通過將一些酒店鑰匙卡數據分成8位模式,我們注意到1和0的相同字符串發生的次數比預期的要多得多。所以我的猜測是,酒店鑰匙卡使用了8位字符。
下面是我的Python腳本的一些輸出樣本:
l? 原始位
l? 字符串(帶十六進制轉儲),如果使用5位、6位、7位或8位字符,則是正確的。雖然“正確性”取決于奇偶校驗、位順序以及位值映射到的字符集。這里有很多錯誤和改進的空間
l? 檢查字符內的奇數/偶數奇偶校驗
l? 尋找常見字符的頻率分析,用于改變字符長度
|
上面的數據來自于實際的酒店鑰匙卡(盡管酒店后來改用了RFID鎖)。
我還開始研究XORing、旋轉字符(rot13格式)、位序和偏移的整個位流(以防止我在把字符組合放到錯誤的位置)。不過,到目前為止這些都還沒有成功。
這就是我所得到的。如果我能解碼鑰匙上的任何數據,我一定會再次發布。我希望能看到我的房間號和結賬日期。但同樣,一個不以明文形式出現的加密字符串也不會讓我驚訝——這是我在某些卡片上所看到過的。
以廉價和耗時的方式來做事也可以很有趣——這也是練習編寫代碼、了解matplotlib以及邏輯分析儀的好機會。
如果你想了解更多有關磁條的信息(在它們變得完全過時之前),請查看:
Samy Kamkar的magspoof工具(視頻鏈接)–如果你需要你的計算機通過磁頭來傳輸惡意數據,可能會很有用。
DEF CON 24-Weston Hecker –黑掉酒店鑰匙和銷售點系統
我很受這些項目的啟發。