如何提取D-Link解密密钥
如何提取D-Link解密密鑰
當我們在分析固件鏡像時,遇到的最常見障礙之一便是加密。雖然已經有一些方法可用于解密固件鏡像,但今天我們仍將簡要介紹一下,如何提取D-Link部分路由器型號中的加密密鑰,特別是D-Link DIR-X1560。該設備與 D-Link DIR-X5460是同一代路由器的一部分,最近,針對該設備,德國流行技術雜志Chip和IoT Inspector聯合對其進行了Wi-Fi路由器相關的安全檢查。
一、D-Link路由器固件加密
D-Link傾向于用自定義的固件更新文件格式,來加密他們的固件鏡像。許多DIR系列的D-Link路由器,使用帶有SHRS頭的固件更新文件格式:
00000000 53 48 52 53 01 13 91 5D 01 13 91 60 67 C6 69 73 SHRS‘]‘`g?is這種固件格式及加密方案已經被公開記錄。一位名叫0xricksanchez 的研究者,發布了一篇非常棒的writeup,記錄了如何發現SHRS固件鏡像(包含DIR-3060,我們已經發布了一篇相關advisory)中密鑰的過程。他們從imgdecrypt二進制文件中提取出了加密密鑰和初始向量IV,此二進制文件可以通過類似系列型號中的URAT shell獲得。
然后,最近我們遇到了DIR-X系列的路由器,它們的固件頭有一點不同。
00000000 65 6e 63 72 70 74 65 64 5f 69 6d 67 02 0a 00 14 |encrpted_img....|頭部就是一個encrpted_img字符串,然后緊跟其后的是鏡像大小字段(32位大端模式)。
SHRS固件鏡像的key不適用于這些encrpted_img 鏡像,因此我們需要找到另一種方法,將解密密鑰從這種加密格式的設備中提取出來。
二、密鑰在哪里?
顯然,我們無法從加密的固件鏡像中提取加密密鑰,因為它是加密的。所以,我們需要找到另一種方法來獲取密鑰key。
如果我們能夠在設備上以某種方式執行代碼,那么就很簡單了。如有足夠的本地權限,我們可以在設備運行時,訪問設備上的所有內容。這是解密后的固件鏡像。
如果設備制造商最近才引入固件加密,則可以追蹤尚未加密的老版本固件鏡像(很可能是引入加密之前的固件版本),并檢查是否可以從中提取出密鑰key。
直接讀取設備的flash內存,是我們可以采用的另一種技術。在flash中固件不太可能被加密。拆開其中一個設備,卸掉flash內存芯片,轉儲內存后再讀取文件系統。但是這樣破壞性太太了,設備很昂貴,一旦損壞將大大浪費。
在這里,我們不會深入探討這些問題,因為其他人已經做過了。關于這個問題Zero Day Initiative有一篇詳細的文章,當你在解決固件加密時,可以考慮這個方法。
三、Shell中的操作
在我們的例子中,通過UART調試接口可以輕松得到DIR-X1560設備的shell。獲取到交互式shell后,就可以輕松dump出整個文件系統。使用內置的busybox tar和nc命令可以很容易地做到這一點。首先在設備上設置監聽器:
nc –nvlp [PORT] > filesystem.tar.gz然后在設備上運行以下指令,只寫明想要傳出的根目錄即可。
tar -cvz /bin/ /data/ /etc/ /etc_ro/ /lib/ /libexec/ /mnt/ /opt/ /sbin/ /usr/ /var/ /webs/ | nc [IP ADDRESS] [PORT]最終,將得到tar.gz壓縮文件,包含文件系統中任何你想要的部分,然后通過網絡傳輸出來。
四、發現在何處解密
不同于“SHRS”固件鏡像,沒有明顯的imgdecrypt二進制文件可供關注。因此我們可以跟蹤固件上傳過程,看是否可以定位到在哪里解密。
幸運的是,固件頭部的字符串,可以作為獨特的關鍵字,幫助我們在文件系統中找到相關程序。
$ grep -r encrpted_img Binary file bin/fota matches Binary file bin/httpd matches Binary file bin/prog.cgi matches在此我們找到了兩個二進制程序 prog.cgi 和fota,二者可能以某種方式來處理加密過的固件鏡像。
在progl.cgi中,根據字符串encrypted_img,我們可以很容易的追蹤到固件上傳的地方。
通過跟隨固件被加密部分的指針變量,發現函數FUN00033144被調用,此指針是其第一個參數。
在這個函數內部,出現一個極有可能是固件解密的函數: gj_decode()
五、深入庫文件
gj_decode()函數被定義在libcmd_util.so文件中,此函數代碼不多,但關鍵的是,其內部調用了兩個加密相關的函數: aes_set_key 和aes_cbc_decrypt。這兩個函數也被定義在上述庫文件中,但我們沒必要深究這二者。因為它們的函數名已經給予了很多信息:像是CBC模式下的AES加密。
我們可以看到,aes_set_key()的第二個參數可能是AES密鑰,而 aes_cbc_decrypt 的第二個參數可能是初始向量IV。
這里的反編譯代碼有點亂,但不要太在意細節,直接看代碼邏輯。有兩個do-while循環,將數據從全局變量復制到本地緩沖區,這些循環在全局地址的字節上迭代,直到到達某個特定的結束地址。
key_loc 和key_loc + 4是指向本地緩沖區的指針變量,第一個循環中,00031ba3地址處的數據拷貝到key_loc+4直到00031bc3地址,而第二個循環,00031bc5地址處的數據拷貝到key_loc直到00031bd5地址(還注意到:這兩個本地指針分別是aes_cbc_decrypt()和aes_set_key()的第二個參數)
的確如此,在地址00031ba3處,可見有一個字節數組。
同樣在00031bc5地址處,也可見類似的形式。
因此,我們可以假設AES密鑰位于 00031ba3,而初始向量IV位于 00031bc5。
今天我們在這不會公布真實的密鑰,但是那些關注且跟隨者應該有能力將密鑰提取出來,如他們而言,這是留給有興趣讀者的練習。
六、節省時間和腦力
通過使用CyberChef,我們可以快速、輕松地驗證假設。大多數情況下,當我想要快速解決密碼學相關問題時,我都會打開這個工具。它由英國GCHQ編寫,如果對公務員寫的東西持懷疑態度,大可不必,它只是用純JavaScript編寫,可以在你想要的任何瀏覽器中運行。
復制加密固件鏡像中的第一個0x1000左右字節的數據,作為16進制的ASCII粘貼到CyberChef輸入中,再結合我們提取的密鑰和IV,通過CyberChef的“AES Decrypt”操作,就可以得到一個理想的結果。
在這里我們可以看到UBI數據塊的頭部數據,說明我們正在完全的解密整個固件更新包。
一旦我們知道密鑰和IV是有效的,那么很容易就可以編寫一個完整的解密腳本。在這種情況下,在我們得到一個完整且正確的鏡像之前,還有幾個小的問題需要克服,比如數據對齊,但這些都很容易解決。
七、結論
在許多情況下,嵌入式設備中的固件被加密并不是一個很難解決的問題。一旦可以獲取到物理設備,解密過程就可以大大簡化。值得記住的是,嵌入式設備的固件加密主要在固件更新包中實現,而很少在存儲級別實現,這一點與移動電話和筆記本電腦的最新實現相反,這二者常見的加密方法是全磁盤(至少是磁盤的重要部分)加密。
這種設置在未來可能會改變,至少是部分改變。例如,Android從4.4開始就支持 全磁盤加密 ,從7.0開始支持基于文件的加密。自Android 10以來,就需要基于文件的加密。然而應該注意的是,術語“完整磁盤”加密在Android中具有誤導性,即加密的只是data/userdata分區。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的如何提取D-Link解密密钥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应急响应-Yara规则木马检测
- 下一篇: 【安全漏洞】CVE-2021-32682