作者:Yimi Hu & Light @ PwnMonkeyLabs
原文鏈接:https://mp.weixin.qq.com/s/F5YHjG1t67Np53_kobG73Q

簡介

本篇為家庭版果加智能門鎖全面分析的最后一篇,在此前的兩篇中,我們分析討論了門鎖固件和配套的app。家庭版果加智能門鎖的app相對較容易分析,通過日志可以直接定位到java層代碼,并進一步追溯到native層代碼,在libBleCmd.so中,我們看到了所有BLE指令的生成代碼以及相關的加密和解密函數。在解密函數中,我們找到了參與解密算法的幾個常量,通過這幾個常量,我們在門鎖固件的大量代碼中,定位到了進行解密運算的幾個函數,詳細分析這幾個函數后,確定了BLE解密密鑰存儲的內存地址,接收到的BLE指令存放的內存地址等,并根據交叉引用的結果不斷增加我們對固件程序的理解,展開了固件代碼的分析討論。

在這篇文章我們順著這條主線繼續深入分析,隨著我們理解的內容不斷增多,我們會發現更多有有意義的函數。最后,我們會展示一個家庭版果加智能門鎖存在的嚴重問題,該問題已于2018年修復完畢,現在拿出來討論一下應該還未出“小玩鬧”的范疇。

固件分析

繼續我們上一篇的思路,回到上一篇結尾時遺留的sub_80000C8函數位置。此函數為整個固件中最復雜的函數,我們將其F5反匯編之后,整理一下代碼,可以看到該函數函數只有入口,沒有出口:

圖片

圖2-1 整理后的sub_80000C8函數

然后我們再搜索下sub_80000C8函數的交叉引用,如下圖所示:

圖片

圖2-2 sub_80000C8函數的交叉引用

繼續向上溯源,可以找到下圖所示位置:

圖片

圖2-3 loc_80000C0標簽的交叉引用

可以看到,sub_80000C8函數是系統復位中斷之后執行的第二個函數。一般情況下,復位中斷會執行兩個函數,第一個函數為init函數,即圖2-3的sub_800D704函數;而第二個函數為main函數,即圖2-3的loc_80000C0標簽處的代碼。此外,單片機的main函數一般都是死循環,不存在執行完畢后退出的情況,這與我們在圖2-3中看到的while死循環相對應。與我們常見的運行于操作系統之上的程序不同,比如說’ ls’、’pwd’等常見的程序,他們完成各自的功能之后,就會退出,而單片機上電之后,MCU就要開始運行給他編寫的程序,一直到單片機斷電為止。

確定main函數之后,我們把目光重新聚焦在上一篇分析的sub_800EB20函數,當時我們把這個函數的功能概括為預處理,即完成消息頭校驗、crc校驗、數據解密等工作的函數。那么在預處理之后,就應該是解析BLE數據、完成邏輯功能的代碼。相關代碼截圖如下:

圖片

圖2-4 BLE命令解析相關代碼

上圖中,我們可以根據代碼結構進行一些猜測:MEMORY[0x20000140]和MEMORY[0x20000169]應該是兩個標志位,其中一個標志位標識收到了BLE指令;v115是預處理函數的返回值,返回值為0代表預處理成功,這與上一篇的分析是一致的;綠框部分的代碼,即為真正解析BLE指令的代碼。

然后我們再來看看sub_800F9EC函數,即圖2-4綠框中的代碼。將代碼反匯編后,稍作整理,可以看到下圖所示的特征:

圖片

圖2-5 BLE指令解析代碼

再結合app的輸出日志,如下圖所示:

圖片

圖2-6 家庭版果加智能門鎖app部分日志

可以確定圖2-5 中,變量v3是保存了門鎖發給手機的BLE指令類型,如圖2-6中,0x2004類型代表開鎖命令的返回數據。

下面我們仔細閱讀一下圖2-5中case 0xE004部分的代碼,該分支是門鎖對于BLE開鎖指令的回復信息,將相關代碼截圖如下:

圖片

圖2-7 BLE開鎖指令回復分支

進一步分析圖中涉及到的函數,可以確定sub_80125C8函數的作用是日期轉時間戳,其返回值v57就是時間戳。變量v57將會與v59和v60進行了比較,當v57不在[v59, v60]區間內時,就會調用sub_800D40C(0x1B)函數。此處的比較,我們是能夠猜想到的:如果密碼過期了,是無法開啟門鎖的,但是sub_800D40C(0x1B)函數就不太確定其含義了。所以我們再來研究一下sub_800D40C(0x1B)函數。

查找sub_800D40C(0x1B)函數的交叉引用,可以發現其調用位置有很多,如下圖所示:

圖片

圖2-8 函數sub_800D40C(0x1B)的交叉引用

上圖中列出了大量調用sub_800D40C函數的位置。點開每個調用位置,可以發現每次調用該函數時都會傳遞一個常量作為參數。而且在main函數進入while循環之前,也會調用此函數,如下圖所示:

圖片

圖2-9 進入while循環之前調用sub_800D40C函數。

為確定sub_800D40C函數的真正含義,我們嘗試更改函數的參數,然后將更改之后的固件刷入門鎖。其更改方法并不復雜,直接進行16進制的固件文件編輯即可,如下圖所示:

圖片

圖2-10 sub_800D40C函數參數

上圖中,紅框部分為傳入參數的數值,截圖中分別是0x09和0x0A。在16進制編輯軟件中打開固件文件,找到該偏移位置:

圖片

圖2-11 十六進制編輯固件文件

將上圖中的高亮字節0x09改為其他字節,如0xB,接著保存固件即可。然后將修改之后的固件刷到智能門鎖設備中,刷入方法也比較簡單,只需要在Fiddler中做一個AutoResponder,用修改過的固件替換原本固件,就可以了,具體操作如下圖所示:

圖片

圖2-12 利用Fiddler替換原本固件

待智能門鎖完成固件更新之后,我們給門鎖重新上電,當門鎖運行至while循環之前的sub_800D40C(0xB)函數時,門鎖發出提示音:“請輸入新密碼”,而不是往常的“設置成功”提示音。再次修改固件,使智能門鎖調用sub_800D40C(0xC)函數,上電后門鎖發出提示音:“請再次輸入新密碼”。由此,我們可以判定sub_800D40C函數正是發出語音提示的函數,而該函數的參數代表了不同語音提示內容。通過反復修改并刷入固件,我們整理了一部分語音提示內容的編號,如下表所示:

圖片

表2-1 家庭版果加智能門鎖語音提示編號表

分析到此時,其實我們相當于在固件中找到了一個非常關鍵的函數:sub_800D40C函數。對于我們分析者來講,這函數相當于日志輸出的作用,在他的幫助之下,我們就能理解絕大部分代碼,這里不再占用篇幅討論更多內容了。

后門密碼分析

在表2-1中,我們可以看到有一個“進入測試模式”的語音輸出。順其自然的,我們想看看測試模式都干了點什么。通過sub_800D40C(0x3)函數,我們可以定位到原固件中進入測試模式的代碼,如下圖所示:

圖片

圖3-1 進入測試模式的相關代碼

上圖中,可以看到一個關鍵的判斷是v84的返回值。觀察圖中的函數參數,應該是和0x80126EE內存地址有點關系。我們跳轉到0x80126EE函數的位置,可以看到如下內容:

圖片

圖3-2 偏移為0x80126EE位置的內存內容

上圖中的內容,我們打了碼,不過還是可以看出來,這些內容是智能門鎖的鍵盤內容。如果不打碼,我們擔心影響太糟糕。

我們試著在門鎖關閉的狀態下輸入這一串字符,當輸入前兩位時,門鎖提示說“密碼錯誤”,此時不要停,繼續輸入,待全部輸入完畢之后,門鎖果然提示說“進入測試模式”。然后,我們隨便在門鎖鍵盤上按了2個數字加‘#’號鍵,門鎖竟然開啟了。就這樣,我們有了一個驚天發現:后門密碼。看起來這并不是故意留下的后門密碼,但確實實現了開門的效果。

圖片

圖3-3 通過測試模式開啟門鎖

小結

到這篇為止,我們完成了關于果加智能門鎖的分享內容,在這次分享中,我們著重介紹了IoT固件的分析方法,解析固件內容,反匯編固件程序,并分析這些看起來意義不明的代碼。在分析過程中,可以以其配套的手機app作為切入點,憑借此app與門鎖之間的通信內容,在門鎖固件程序中定位關鍵的代碼,逐步理解固件內容。最后,我們還演示了關于果加智能門鎖的一個小玩鬧。紙上得來終覺淺,絕知此事要躬行。建議感興趣的讀者還是親自嘗試分析一下。最后,希望大家能夠喜歡這個分享內容,如若有什么想討論的,可以隨時聯系我們。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1534/