<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/wireless/15139

            翻譯自:http://www.b0n0n.com/2016/04/20/ms-jailbreak/

            0x00 簡介


            這學期我得到了一個微軟智能手環作為項目研究目標。最初的項目目標并不是太難:只是去理解客戶端的通信方式。因此我決定尋求樂趣,我決定嘗試pwn掉它。在這里我想要感謝遠在OSIRIS實驗室的朋友給我提供的支持,我的伴侶也一直默默支持著我。當然,需要感謝的還有我的導師,mongo,他啟發了我,教會了我很多,對此我表示由衷地感謝。

            0x01 行為分析


            首先,我們分析一下這種智能手環的一些基本行為,例如它如何升級固件,上傳用戶狀態等。幸運的是,這個客戶端只是一個windows二進制文件,因此我們可以很容易的構建好逆向環境。這個Windows客戶端文件可以在這里下載。由于客戶端是用C#編寫的,我們可以使用一些例如ILSpy,JustDecompile,dnSpy以及dotPeek之類的工具很容易的對它進行調試和反編譯。

            在對客戶端進行逆向后,我發現客戶端會從云端下載FirmwareUpdate.bin文件并將其存放在這個目錄:

            #!bash
            c:/Users/IEUser/AppData/Local/Microsoft/CargoDevice/u_9e35ffc6-2859-4332-b89c-9110db164d9c/d_ffff1300ffffffff1830454e06000e30/FirmwareUpdate
            

            現在我知道了固件會從哪里進行更新,下一步要做的就是獲取用于更新的固件。因為我的設備已經是最新固件了,無法正常獲取更新固件,所以我需要找到另外一種方法來獲取固件。或許我可以試著欺騙服務器?

            p1

            我使用Burp修改了請求信息中的版本號,之后它成功的欺騙了服務器,開始下載FirmwareUpdate.bin文件。得到這個文件后我就可以繼續做一些有趣的事情。首先,我們需要分析更新固件FirmwareUpdate.bin。

            #!bash
            [email protected] ~/MS_band $ binwalk FirmwareUpdate.bin
            
            DECIMAL HEXADECIMAL DESCRIPTION
            --------------------------------------------------------------------------------
            29668 0x73E4 LZMA compressed data, properties: 0xA2, dictionary size: 2097152 bytes, uncompressed size: 1966105 bytes
            30069 0x7575 CRC32 polynomial table, little endian
            244521 0x3BB29 SHA256 hash constants, little endian
            853728 0xD06E0 LZMA compressed data, properties: 0xA2, dictionary size: 2097152 bytes, uncompressed size: 1966105 bytes
            939669 0xE5695 CRC32 polynomial table, little endian
            

            根據binwalk顯示的信息,我在網上沒有找到類似格式的有用信息。因此我決定對FirmwareUpdate.bin進行逆向然后猜測二進制文件中不同的部分。我注意到 FirmwareUpdate.bin的大小是0x16D67E比特,這個值存儲在文件頭的0x13偏移位置:

            00000000 5F C3 01 09 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00 7E D6 16 00 C3 23 1E 43 00 C0 65 01 00 00 00 00 01 00 01 C0 65 01 01 00 00 _..............!...~....#.C..e.........e....
            0000002C B0 0E 00 02 C0 65 B1 0F 00 68 03 00 00 42 00 CD B4 0F 00 02 73 01 00 2B 00 CF 27 11 00 30 10 00 00 2C 00 FF 37 11 00 30 0C 00 00 2D .....e...h...B......s..+..'..0...,..7..0...-
            00000058 00 2F 44 11 00 30 04 00 00 2E 00 5F 48 11 00 30 10 00 00 2F 00 8F 58 11 00 30 04 00 00 30 00 BF 5C 11 00 30 08 00 00 31 00 EF 64 11 ./D..0....._H..0.../..X..0...0..\..0...1..d.
            00000084 00 30 04 00 00 32 00 1F 69 11 00 30 24 00 00 33 00 4F 8D 11 00 30 04 00 00 34 00 7F 91 11 00 30 04 00 00 6C 00 AF 95 11 00 30 04 00 .0...2..i..0$..3.O...0...4.....0...l.....0..
            000000B0 00 2A 00 DF 99 11 00 6A 06 00 00 29 00 49 A0 11 00 00 03 00 00 46 00 49 A3 11 00 40 0A 00 00 36 00 89 AD 11 00 80 28 00 00 3F 00 09 .*.....j...).I.......F.I...@...6......(..?..
            000000DC D6 11 00 40 EF 00 00 41 00 49 C5 12 00 97 B6 00 00 28 00 E0 7B 13 00 D8 15 00 00 49 00 B8 91 13 00 4E 2C 00 00 4A 00 06 BE 13 00 40 ...@...A.I.......(..{......I.....N,..J.....@
            00000108 2C 00 00 4E 00 46 EA 13 00 2C 30 00 00 4C 00 72 1A 14 00 10 2F 00 00 4F 00 82 49 14 00 E2 2D 00 00 50 00 64 77 14 00 E6 2D 00 00 4B ,..N.F...,0..L.r..../..O..I...-..P.dw...-..K
            00000134 00 4A A5 14 00 06 2F 00 00 4D 00 50 D4 14 00 BA 2C 00 00 24 00 0A 01 15 00 0D 66 00 00 25 00 17 67 15 00 FB 95 00 00 6D 00 12 FD 15 .J..../..M.P....,..$......f..%..g......m....
            00000160 00 6C D9 00 00 9F 84 42 00 03 00 0A 00 E8 0C 00 00 00 30 00 00 00 00 01 00 15 05 FF 1F 64 07 C4 91 00 02 FF 1F FF FF FF FF FF FF FF .l.....B..........0..........d..............
            0000018C FF 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............................................
            000001B8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............................................
            

            因為binwalk顯示的信息中有CRC32多項式表,我決定尋找4比特的CRC校驗值,它應該是在頭信息中用于完整性檢查。在文件頭中,你可以在0x17偏移處看到4個字節的“隨機”數據:0x431E23C3。將這四個字節替換成'\0'后計算其他數據的CRC值,我們得到了完全相同的結果:

            #!bash
            Found at offset dec=23 hex=00000017
            CRC=431E23C3
            

            看起來這個二進制文件使用了CRC校驗值檢查了FirmwareUpdate.bin的文件完整性。下一步我將嘗試將修改過的固件推送到手環。我修改了存儲在FirmwareUpdate.bin中的版本號作為測試,看看這個手環是否會接受任意修改過的FirmwareUpdate.bin固件。如果手環接受了修改的固件,版本號作為測試值可以很容易的檢驗效果。

            0001EC6C 00 4D 69 63 72 6F 73 6F 66 74 20 43 6F 72 70 6F 72 61 74 69 6F 6E 00 00 00 31 30 2E 33 2E 33 33 30 34 2E 30 00 25 75 00 00 30 37 32 .Microsoft Corporation...10.3.3304.0.%u..072
            0001EC98 37 00 00 00 00 20 4C 45 00 9F 38 02 00 80 C3 C9 01 0B 2A 02 00 39 39 02 00 FF F7 E8 FE 06 20 28 70 60 68 C5 F8 05 00 01 E0 09 20 28 7.... LE..8.......*..99....... (p`h....... (
            

            不幸的是,我發現手環在進行更新時會檢查固件有沒有被篡改或者損壞。我需要繞過這個問題,于是我使用了Dnspy設置斷點,并且在客戶端發送信息給手環之前對其進行修改。

            #!csharp
             private bool PushFirmwareUpdateToDeviceInternal(FirmwareUpdateInfo updateInfo, CancellationToken cancellationToken, KdkFWUpdateProgress progressTracker)
             {
                 bool result = false;
                 this.CheckIfUpdateValidForDevice(updateInfo.FirmwareVersion);
                 Logger.Log(LogLevel.Info, "Verified that the firmware update is valid for the device", new object[0]);
                 cancellationToken.ThrowIfCancellationRequested();
                 string text = Path.Combine("FirmwareUpdate", "FirmwareUpdate.bin");
                 if (this.storageProvider.FileExists(text))
                 {
                     int.Parse(updateInfo.SizeInBytes);
                     this.UploadDeviceFirmware(text, progressTracker);
                 }
                 string value = this.FirmwareVersions.ApplicationVersion.ToString();
                 if (updateInfo.FirmwareVersion.Equals(value))
                 {
                     result = true;
                     Logger.Log(LogLevel.Info, "Verified that the firmware update is successfully installed on the device", new object[0]);
                 }
                 return result;
             }
            

            上面的C#函數用于將固件更新發送到手環

            然而在完成這個過程后,我沒有在手環的屏幕上看到固件安裝的畫面,這意味著它失敗了。似乎他們還有其他的機制用于檢驗固件完整性。這意味著我不得不繼續對更新固件進行逆向,根據binwalk顯示的信息,似乎有一部分代碼被識別為LZMA數據。現在的問題是我不知道文件的加載地址。在閱讀了一些關于嵌入式ARM設備的逆向資料后,我幸運地找到了一個表,其中包含了正確的加載地址0x05c8bf。

            #!bash
            000d2230 00 bf c8 05 00 11 c9 05 00 4f c9 05 00 8d c9 05 |.........O......|
            000d2240 00 93 c9 05 00 99 c9 05 00 f1 c9 05 00 51 ca 05 |.............Q..|
            000d2250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
            000d2260 00 01 00 00 00 14 00 00 00 00 00 00 00 02 00 00 |................|
            000d2270 00 04 00 00 00 00 00 00 00 03 00 00 00 06 00 00 |................|
            

            最終,我使用IDA處理這個二進制文件。通過搜索CRC位置(偏移量) 0x17,我發現了關鍵的CRC校驗函數,并且通過交叉引用我發現了IntegrityCheck函數,以及其他一些檢查函數。整個完整性檢驗程序如下:

            1.檢查主CRC

            p2

            2.檢查塊CRC

            p3

            3.檢查更新固件版本號是否高于當前版本

            p4

            因此我要做的就是將版本號修改為比我當前手環高的數值,然后重新計算塊CRC校驗值,以及主CRC校驗值。

            為了方便,我針對這種固件的二進制格式寫了一個解析器:

            #!bash
            Offset: 0x00000000 Magic number: 0xC35F
            Offset: 0x00000002 Unkown byte: 0x1
            Offset: 0x00000003 Unkown flag: 0x00000009 (looks like GPIO port output speed)
            Offset: 0x00000007 Zero padding
            Offset: 0x0000000F Total number of sections: 0x00000021
            Offset: 0x00000013 Firmware size: 0x0016D67E
            Offset: 0x00000017 CRC of whole firmware: 0x431E23C3
            Section table:
            Offset 0x0000001B section type 0xC000:
             Section offset 0x00000165, size 0x00010000 [ends at 0x00010165]
             Offset: 0x00000004 Version number: 0x000A0003.0x00000CE8 (shown as 10.3.3304)
             Offset: 0x00000010 Section size: 0x00010000
             Offset: 0x00000018 Section CRC: 0x91C40764
            Offset 0x00000025 section type 0xC001:
             Section offset 0x00010165, size 0x000EB000 [ends at 0x000FB165]
             Offset: 0x00000004 Version number: 0x000A0003.0x00000CE8 (shown as 10.3.3304)
             Offset: 0x00000010 Section size: 0x000EB000
             Offset: 0x00000018 Section CRC: 0xE46EFF7D
            ...
            

            接下來,我寫了一個補丁用于修改版本號,以及搜索修改我想要修改的字符串。

            #!python
            def Patch(filename):
                f = open(filename, 'r+')
                Patched = f.read()
            
                Patched = VersionNumPatch(Patched, "10.6.3304")
            
                text1 = TextPad("No new texts, check back in a few.")    #patch the empty text string
                text2 = TextPad("pwned by ------------- mongo&b0n0n")
                Patched = SearchPatch(Patched, text1, text2)
            
                Patched = CalSectCrc(Patched) # recalculate the section CRCs
                Patched = CalMainCrc(Patched) # recalculate the main CRC
            
                with open('FirmwareUpdate.Patch', 'w+') as f:
                f.write(Patched)
            
            Patch("FirmwareUpdate.bin")
            

            你可以在我的github上獲取所有代碼。

            在對固件進行完修改后,我使用了上面一樣的方法將其更新到設備中。

            p5

            設備接收到文件后,它會檢查文件的完整性,如果文件通過所有檢查,你會看到這樣的安裝畫面:

            p6

            安裝完成后手環會重啟,然后你可以檢查版本號以及其他修改過的地方:

            p7

            p8

            你可以修改將其中的任意代碼和數據修改為你想要的。

            我還沒有購買微軟手環二代,所以我不知道這種方法是否適用于二代的手環。當然們如果你有興趣可以自己進行嘗試。

            以上,如果您在文章中發現有任何錯誤,歡迎指正。

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

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

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

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

                      亚洲欧美在线