有幸參加今年11月份的上海Syscan360安全會議,會議期間有一個亮點就是360的獨角獸團隊設計了一款電子badge(胸牌)供參加人員進行破解嘗試,相似於美國Defcon上面的那種解密puzzle的比賽,在參會現場的人均可以參加這種破解,總共9道題,規則是現場會給每道題謎面,在這塊胸牌上面輸入正確的謎底才能進入下一題,解題須要開腦洞,有好些人蔘與破解,並且有好些人都解出來了,今天筆者從這塊胸牌的硬件和軟件層面去揭密這個胸牌的一些有意思的功能和如何在不須要知道謎面的狀況下,快速解密答案,算是硬件破解方面拋磚引玉。git
我這邊看到有兩塊板,一塊黑色一塊紅色,其中黑色以下web
硬件配置以下:算法
MCU:德州儀器TI CC1310 型號(CC1310F64RGZ)VQFN (48) 7.00 mm × 7.00 mm編程
ARM Cortex-M3處理器,時鐘速度高達48Mhz安全
64KB片上可編程flash,20KB靜態內存SRAM,30個GPIO口服務器
RF Core支持收發1Ghz如下的無線信號數據結構
外置存儲器: Winbond 25Q32bvsig工具
32Mbits存儲空間佈局
一個LCD液晶屏學習
四個led燈,若干電阻和電容,6個按鍵和開關,全部的這些構成一個小型的嵌入式系統
使用方法:
6個按鍵,分別負責切換不一樣的可打印的ASCII碼,刪除,進入和返回等功能
只有全部的關卡經過後才能出現控制閃燈和產生紅外信號去關閉遙控電視的功能,這是後話,後面細講。
要想了解裏面的原理和功能,必須得拿到裏面的代碼邏輯。經過查閱MCU CC1310芯片的數據手冊,咱們發現它支持jtag仿真調試,咱們只須要外掛支持ARM的仿真器,就能夠進行整個內存空間的訪問和片上動態調試,這一點對於咱們逆向來說很是有幫助,CC1310芯片佈局以下。
DIO_16 26 Digital I/O GPIO, JTAG_TDO, high-drive capability
DIO_17 27 Digital I/O GPIO, JTAG_TDI, high-drive capability
咱們知道要進行jtag調試須要至少4根信號線分別是TMS,TCK,TDI,TDO,(RST可選)最後是GND(接地), 具體JTAG的定義和各個信號線的定義你們能夠網上搜索,我就不贅述了,找到這幾個信號線接到相應的仿真器上就能夠進行調試了。
從該MCU的電子手冊咱們得知這四個信號線的Pin腳位置以下。
TMS——24
TCK——25
TDO——26
TDI——27
而後咱們能夠經過萬電錶量出這幾個引腳引出來的位置,恰好這板子已經把這幾個信號腳引出來了,也省去咱們很多麻煩。
好了,焊好線後,須要咱們的仿真器出場了,筆者使用的ft2232h mini module,固然你們也能夠選用別的仿真器,像jlink之類的,簡單說一下這個mini module,它是一個多硬件協議(MPSSE)集一身的小模塊,好比SPI/JTAG/I2C等,共用GPIO口,很是方便,接下來就是連線了,鏈接圖以下。
右邊是mini module CN-2接口Pin腳,左邊是CC1310的引腳,GND隨便找一個板子接地的地方接上就行了。
下面就是ft2232h mini module
好了,接下來就是激動人心的時刻了。
硬件鏈接準備就緒後,咱們開始驅動仿真器來進行片上調試。
調試工具準備以下:
OpenOCD (開源的硬件調試軟件)
Arm-none-eabi-gdb (arm版的gdb)
在使用openocd以前須要準備好cc1310的調試配置文件cc1310.cfg,在這裏能夠找到。
一切準備穩當,接下來就能夠開始見證奇蹟的時刻了。
運行telnet localhost 4444進行命令行來控制操做cpu或者內存空間,在這裏咱們可把cpu halt暫停下來,cpu重置,設置斷點等操做。
在這裏咱們執行halt命令,cpu就斷下來了,效果以下
這個時侯個人gdb就能夠遠程attach上去進行動態調試與內存空間訪問了。
運行arm-none-eabi-gdb,gdb裏面執行target remote localhost:3333
進行遠程調試鏈接,能夠內存空間訪問與動態調試。
好了,咱們能夠內存空間訪問了,先把固件,flash,和內存數據dump出來,靜態分析一下吧。
以下是cc13xx芯片的內存空間地址映射表,它可讓咱們知道dump哪些有用的數據
0地址開始到0x10000是咱們CC1310F64型號的flash的地址空間
BootROM是從0x10000000到0x10020000
SRAM地址從0x20000000到0x20005000
好了,咱們就dump這三塊位置。
在gdb裏面運行以下命令
dump binary memory cc1310_flash.bin 0 0x10000 dump binary memory cc1310_brom.bin 0x10000000 0x10020000 dump binary memory cc1310_sram.bin 0x20000000 0x20005000
好了,合併這三個文件用IDA進行反彙編,不一樣的段進行地址重定位,能夠作到地址精確引用,以下。
好了,接下來就是逆向篇了,如何找到答案和分析其代碼邏輯等等。
咱們經過IDA裏面的一些字符串得到一些線索。
而後咱們很快找到每一道題的答案了
解釋一下這裏面的一些邏輯。
這裏面每一道題的提示和答案,還有用戶自定義ID存儲在flash 0xe000開始的區域裏面,總共長度0xe2個字節,運行時會把這塊區域數據讀到SRAM裏面,在SRAM裏面進行操做,而後把SRAM結果寫回到0xe000這塊區域裏,以保證下次設備重啓數據和進度不會丟失,其結構以下。
0xe000 ---0xe010 存儲用戶設置的ID
0xe014 --- 0xe015 存儲用戶過了多少關了(直接改爲9就通關了:),修改SRAM裏面相應的存儲的數據,而後經過ID設置來觸發寫回到0xe014,這樣就生效了)
以下是不一樣關卡的提示和答案
比較每個關卡的用戶輸入答案,並進行更新
0x20001060存儲着flash地址0xe000裏面的數據
偏移0x14就是用戶當前所在關卡數,若是答案比較相等,這個關卡數加1並寫回到flash裏面,並在屏幕上顯示『right!』。
總共9道題的答案分別是
UR1NMYW0RLD!
42
ORDREDUTEMPLE
FQJPVDPOK
VYTX
LOYAL
GNILCS
FIBONACHI
WORLD
通關最後的結果以下
若是你只想知道答案,看到這裏就能夠了,接下來會講講裏面的一些其它功能。
當全部的關卡都經過後,會多出來兩項列表,分別是
Led Light
TVB Gone
進入Led Light前置的兩個led燈能夠顯示3種顏色,這裏是經過設置12號GPIO和19號GPIO口,對應在芯片上的引腳是18和29.
這裏咱們重點關注這個TVB Gone功能,這個一個能夠經過紅外信號遠程關閉不少不一樣品牌的電視的小應用,具體介紹參考:https://en.wikipedia.org/wiki...
咱們知道咱們家裏面使用的電視的遙控器,通常都是發射的紅外信號,來控制電視的開關,調臺等操做,這個TVB Gone的功能就是經過發射不一樣品牌和不一樣頻率的控制信息來達到關閉遙控電視的目的。
紅外控制信號經過必定頻率的PWM(脈衝寬度調製)調製方式輸出給led燈,led燈產生的紅外信號影響遙控電視。
研究發現這個板子裏面存儲了80組紅外控制信號源數據,經過特定的數據結構來存儲,例如以下。
以下是存儲每一組數據的地方指針列表
咱們挑選其中一組來看
解釋一下每一個字段的含義
0x9600 表示這種數據的發射頻率38400Hz
0x1a 表示有多少對數據須要發送出去
0x02 表示每發送一對信號裏面承載着2個bit數據
0x9e38 表示存儲時間對的指針地址
0x97b4 表示要發送的數據的指針地址
地址0x97b4在存儲的數據以下
{0xe2, 0x20, 0x80,0x78,0x88,0x20,x10}
上面有講這些數據須要發送26次,每次是2個bit,總共就是52個bit
上面是7個字節,總共是56個bit,還有4個bit怎麼辦,後面再說。
這個時候咱們須要說說存儲時間對的指針了
地址0x9e38存儲的時間對
{60,60,
60,2700,
120,60,
240,60}
這個時間對分別是time on和time off
解釋這兩個概念時先計算一下PWM調製的週期時間
1/38400=26μs(微秒)
該MCU的系統時鐘是46Mhz,這裏使用了一個16位的通用定時器GPT TimerB
咱們經過代碼得知該PWM調製的佔空比(duty cycle)是33.3%,什麼是佔空比,就是在一個PWM週期裏面高電平佔總電平的比例,以下圖
這個PWM的週期是26μs,高電平是8.84μs,因此佔空比就是8.84/26=33.3%,也就是1/3,咱們從代碼裏面也能看到。
這個PWM輸出使用的是4號GPIO口,地址0x40022090是設置各個GPIO口置bit1的地方,這裏賦值0x10恰好是置4號GPIO口bit1,也就是高電平,地址0x4001002c設置定時器時間,也就是這個高電平持續多長時間,後面0x400220a0是設置各個GPIO口清除bit1,也就是置bit0,這個是0x10,表示置4號GPIO口bit0,也就是進入低電平,設置定時器長度在地址0x4001002c,時長是高電平的2倍,這就是一個週期time on的狀態,經過計算咱們可以得出一個週期高電平的時長。
系統時鐘週期1/46000000
(46000000/38400/3.0)*( 1/46000000)=8.67μs
好了,繼續回來上面的時間對Time on和time off
{60,60,
60,2700,
120,60,
240,60}
把每一個數字乘以10,時間單位是微秒,這個10怎麼來的,代碼裏面看到的,不知道緣由(搞硬件的同窗幫忙解釋下)
{600,600,
600,27000,
1200,600,
2400,600}
每對數字前的數字表示Time on,就是在這個數字的時間內,PWM信號週期性出現,後面的數字Time Off表示低電平沒有PWM週期性變化。
這兩個組合在一塊兒的PWM信號就是表示數字信號裏面的2個bit位,上面有提到
{600,600, 表明bit 位『0 0』
600,27000, 表明bit 位『0 1』
1200,600, 表明bit 位『1 0』
2400,600} 表明bit 位『1 1』
因此這個紅外信號就是經過PWM的這種方法調製發射出去的,繼續上面的例子,咱們要發送的數據以下。
{0xe2, 0x20,0x80,0x78,0x88,0x20,x10}
發送數據的順序是MSB,就是從左到右開始發,好比0xe2的比特數據是
「 11100010 」
先發11,10,00,10對應的發送時間序列對就是
2400,600
1200,600
600, 600
1200,600
咱們能夠經過邏輯分析儀來看這些信號發送的狀況
第一組發送的比特11
Time on 2400微秒(也就是2.4毫秒),咱們觀察到按照週期性變化的PWM信號長度就是2.4毫秒,低電平的時長就是600微秒左右
*第二組發送的比特10
time on時長1200微秒,time off時長600微秒
第三組發送的比特00
time on時長600,time off時長600
第四組發送的比特10
time on時長1200微秒,time off 600微秒
好了,上面咱們有提到要發送的數據是7個字節,56bit,可是隻發送了26對也就是52bit,還有4bit怎麼辦,咱們看最後一個字節0x10對應的比特位是00010000
由於最後4位都是bit0,因此直接低電平補位了(猜想)。
最後在14秒左右遍歷了80組紅外信號來嘗試關閉遠端的搖控電視
咱們彷佛忘記了那個4MB的winbond的外置flash了,它的功能以下:
存儲一些文字介紹信息
存儲LCD文字顯示映射碼
存儲啓動的圖片
存儲了一個變量
若是dump外置flash?
先祭出個人神器FT2232h Min Module,用熱風槍把外置flash吹下來,而後夾住,連線以下圖,SPI接口一一對應好就能夠了。
經過軟件flashrom來讀取flash裏面的內容
運行
flashrom –p ft2232_spi:type=2232H,port=A –r flash_cc.bin
LCD顯示是經過硬件I2C協議寫入數據,ASCII碼和UNICODE顯示邏輯以下
漢字經過UTF8解碼而後GBK編碼後存儲
因此想在顯示屏上面顯示中文漢字,只須要把漢字UTF8解碼而後GBK編碼後放到相應的位置就能夠了,例如
>>> '謝君'.decode('utf8').encode('gbk') '\xd0\xbb\xbe\xfd'
這四個字節寫入地址0x20001060處,而後寫回內置flash就出來以下效果了。
該板子帶一個無線收發功能,中心頻率是433.92Mhz,速率50Kbps,2-GFSK方式調製,該無線功能一直處於監聽狀態,當收到服務端發過來的相應命令的數據包時,會作相應的解析,而且發相應的包響應。
這個無線功能有以下一些功能,我就挑選了幾個:
廣播請求客戶端提交大家的用戶id信息
廣播請求客戶端提交大家的經過關卡數的信息
服務端器發送無線數據格式以下:
0x00 0xaa無線通訊前導碼(preamble)
0x01 數據包payload長度
0x02 請求命令
0x03-0x04 header 0x5555或者0x2b2
0x05 序列號(seq)
0x06 地址
0x07 子命令
end 兩個字節的數據包校驗和
客戶端發送數據格式以下:
0x00 0xaa前導碼
0x01 數據包長
0x02 請求命令
0x03-0x04頭部header 0x02 0xb2
0x05 對應服務端發過來的地址
0x06 子命令
0x7—須要提交的一些數據
end兩個字節的校驗和
校驗和算法:
把字段數據包長度後面的數據,不包括校驗和字段,每一個字節數據相加結果再和校驗和做比較。
我節選了幾個數據交互對,因爲咱們如今不可能收到服務器發的數據,因此只能根據逆向代碼來判斷髮送的內容是什麼樣的:
recv是來自服務器發的,send是咱們的板子響應發出去的。
Seq是序列號,add是地址,各佔一個字節
請求提交你過了多少關:
recv 0xaa 0x06 0x02 0x55 0x55 seq add 0x01 chk1 chk2
send 0xaa 0x08 0x03 seq 0x02 0xb2 add 0x01 0xff 0x09 chk1 chk2
請求提交板子的用戶id,名字長度是16個字節
recv 0xaa 0x06 0x02 0x55 0x55 seq add 0x03 chk1 chk2
send 0x0a 0x16 0x03 seq 0x02 0xb2 add 0x03 username chk1 chk2
其它
recv 0xaa 0x06 0x04 0x02 0xb2 seq add 0x01 chk1 chk2
send 0xaa 0x05 0x05 seq 0x02 0xb2 add chk1 chk2
固然還有改進的空間,好比在解題算法代碼上面,不要用明文存儲答案,通過一些算法混淆處理,能夠提升代碼分析的門檻。
硬件上面的一些反調試對抗,能夠考慮一些芯片硬件特性的支持,好比今年defcon上面使用的intel在quark d2000 x86芯片,裏面有一個jtag的disable的OTP比特位,燒錄設置後jtag硬件調試就不能用了。
相信他們在設計這塊板子的時候也是付出了不少精力,逆向也是一個學習的過程,感謝。