tft每日頭條

 > 科技

 > 固件的本質是軟件嗎

固件的本質是軟件嗎

科技 更新时间:2024-07-03 17:11:44

當你手上有一個固件?或許是從芯片上提取出來的亦或是從網上下載的更新文件。接下來你會怎麼做呢?

獲取到固件,然後提取出其中的有效信息,這可不是一個簡單輕而易舉的過程。有時,你不得不面對一些專有的文件格式(幾乎沒有任何參考文檔),奇怪的原始數據 quirks,甚至是加密的數據。

固件的本質是軟件嗎(固件分析--工具)1

接下來,就讓我們來了解了解從固件中獲取有效信息的一些策略。

1、結合使用場景

充分了解當前正在處理的文件的使用場景(環境),對後續的分析是很有幫助的。你需要搞清楚支持該固件運行的芯片型号,芯片架構,大端模式還是小端模式,固件上運行的系統是 RTOS 還是 Linux ?或者是純裸機?等等問題。

Context will help 。。。

2、Binary還是ASCII

So,文件裡面到底是 ASCII 字符串還是二進制數據呢?用 head,cat,hexdump這些命令亦或是你最喜歡的 GUI 文本編輯器去查看這些文件的類型。

如果你的目标設備是運行在裸機上的,那麼你可能會看到這些固件文件分散分布在衆多的十六進制文本中(也經常前綴有區分碼或者偏移地址/絕對地址,同時有可能在每一行後綴有校驗和)。在你對這些文件進行進一步分析前,首先需要将他們整理成二進制文件格式。接下來,我們來學習了解一些常見的二進制文件格式。

>>>>2.1 Motorola S-Record

通常,該文件格式也稱為 SREC。所有 S-record 文件,每行都是大寫字母S開頭。關于該二進制格式的詳細信息,參考[鍊接]。

固件的本質是軟件嗎(固件分析--工具)2

>>>>2.2 Intel HEX

類似 SREC , [ Intel HEX ] 每行都是以一個冒号(:)開頭。

固件的本質是軟件嗎(固件分析--工具)3

>>>>2.3 TI-TXT

TI-TXT 是德州儀器(Texas Instruments)公司開發的格式,常用于 MSP430 系列單片機。該格式以符号@作為地址前綴,而數據是以十六進制存儲的,整個文件的看起來如下:

固件的本質是軟件嗎(固件分析--工具)4

所有 Motorola S-record,Intel HEX 和 TI-TXT 文件都可以用[ bincopy python library ]轉換成二進制文件。

>>>>2.4 Raw NAND dumps

咋一看,數據是以一種奇怪的方式存儲在 NAND 芯片上的。可是,當你想在對芯片上的數據進行預處理時,你會稱贊該設計的智慧和實用。

固件的本質是軟件嗎(固件分析--工具)5

從上圖可以看到,Out-of-band(OOB)“空閑”區塊被插入到每頁數據的末端,或者是每塊數據塊的末端。這些空白的存儲區塊被主控用于跟蹤壞塊,擦除計數等等。所以,當你整塊芯片地 dump 原始數據的時候,這些“空白的”區塊也會 dump 下來。

這意味着你需要将所有這些“空閑”區塊剔除掉才能從芯片的 dump 中獲得連續的真實文件。這樣,你就可以開始用下述的策略對這些二進制文件進行深入地分析了。

3、你提取到了二進制文件?這并不值得十分興奮

一旦你得到了二進制格式的固件,你就可以嘗試從中分析出一些有趣的信息。

再次提醒,多結合固件的使用場景對進一步分析是十分有益的。如果你了解到該固件是用在某個具體型号的 MCU 上,那麼你可能會查找對應的 datasheet 然後直接将固件載入 IDA 進行分析。如果你知道該固件是用在裸機芯片上的,但是你沒有該芯片的 datasheet,那麼你可能會做一些字節級别的分析工作。如果該固件是用在一個更加複雜的系統,例如像 Linux 這樣的操作系統,那麼你很可能需要将文件提取出來。

無論如何,下面的這些工具還是很好用的。

>>>>3.1 strings

strings是提取文件初始底層數據的強有力工具。它返回的是一列由null字符結尾的可打印字符串。strings命令遠比大多數人了解到的強悍。一條基本的命令strings file.bin将返回 ASCII/ISO 4 字符串。稍微複雜一點的是:

strings -n16 file.bin

默認的字符串最小長度為 4 。-n選項用于申明返回的字符串的具體長度。上面例子将輸出長度不短于 16 的字符串到 stdout 。

strings -el file.bin

strings的 -e選項明确了字符編碼。-el指定字符編碼為小端模式,16 位寬。如果二進制文件是大端編碼的,那麼用 -eb 。16-bit 位寬編碼常見于嵌入式視窗系統的固件中。

strings -tx file.bin

-t選項用于返回文件中字符串的偏移。-tx則返回十六進制格式,-to則返回八進制(octal),-td則返回十進制(decimal)。這将非常有用當你在 十六進制編輯器中跨越引用時,或者你隻是簡單地像知道字符串在文件中的位置。

配合 -n 和 -t 選項,strings 命令的輸出效果類似于下圖:

$ strings -n16 -tx file.bin de1d73 vl1T-W4m% ]e7 ^") 14b3b12 K,E>$r!!qxc` a~S 15715a8 hX3Y@<-Gb$r G9[j 19717f0 hg9Dfs[31 .|~#y*4 3a223b5 v?_-=jO ?0n>#@[D 417fec4 s]pD(6X#_tD&-NN- 47667a1 dAsMJjD#= x'LG4<b7 4d55401 =GKw]I6VCDuTGvsv 511ad94 HelloFirmwareFans 53ef9cc %z.rkn'-z:gVUUl1-i 548b9e0 oelinux123 5d1c7cf P~7^SLD0njEo:ALa

字符串的偏移,是以十六進制格式顯示在每行的行首。

>>>>3.2 hexdump

用 hexdump對二進制文件進行分析,該命令将會向 stdout 輸出該文件中每一字節的十六進制形式。所以,該命令其實就是一個 hex(十六進制) dump 工具。

據我所知(了解),大多數人常用 -C 選項,該選項的結果是:以單字節方式返回文件數據,同時,添加一行顯示可打印字符(若為不可打印字符,則代之以 stop 字符)。因此,借助 hexdump可以很方便地獲取二進制文件中的 字符串以及對該文件的總體輪廓。

hexdump還通過 * 來指代重複行。但是,假如你希望清楚地看到每一行輸出的内容,那麼可以通過 -v 選項來取消這一項功能。

-n選項用來限制返回的字節數目。在下述例子中,hexdump 的-C 選項返回 file.bin 文件 0x200 字節的數據。

固件的本質是軟件嗎(固件分析--工具)6

>>>>3.3 file

用 file 命令檢測提取出的固件(包括 binwalk 、 dd 提取出的任何文件)往往能收到不錯的效果。file 是通過檢測文件頭部(即所給定文件的前面幾個字節)的 magic bytes 工作的。

無法界定的文件類型會被标記為“data(數據)”。任何可區别的文件都會被标記為 file認定的文件格式,同時, file 也會給出相關元數據。下面的示例是 file 對一幅 JPEG 圖片的解析:

固件的本質是軟件嗎(固件分析--工具)7

提取出來的固件有時候是包含大量各種類型文件的不規則文件塊。亦或是加密的以完全随機的字節序列開始,這可能使得它的 magic bytes 與合法文件格式相符或不符。在這種情況下,我們得到的結果将會是個錯誤的方向。

固件的本質是軟件嗎(固件分析--工具)8

PDP-11 UNIX/RT ldp 是什麼文件格式?我真的不清楚,不過可以肯定的是,這不是固件。這個結果反映的隻是該文件的前幾個字節與 PDP-11 UNIX/RT ldp 文件相符。

在文件夾目錄下運行 file * 是一個快速而高效的做法。舉例來說,在 binwalk 輸出目錄下運行該命令可以快速看到我們将要處理的文件類型。例如, binwalk 可能找到(并成功提取出)了一個 JFFS2 文件系統,以及其他一些東西。運行該命令, binwalk 輸出目錄的内容可能如下:

$ file * 2042C4: data 800000.jffs2: Linux jffs2 filesystem data little endian jffs2-root: directory

>>>>3.4 binwalk

binwalk 是一款可靠且很受歡迎的針對運行有操作系統的設備的固件分析工具。關于這方面,網上的讨論不計其數。不過,更為重要的是,并不要僅僅認為 binwalk 隻是徹頭徹腦的一個固件分析工具而已;這隻不過是它極其有用而又簡單的一方面功能。

從一個更高層次來說,在默認情況下 binwalk 循環疊代地搜索整個二進制文件,檢索 magic bytes。如果找到,就把它以表格的形式通過 stdout 打印出來。

binwalk 可以分塊的形式提取出被分析的二進制文件數據,這樣的話,就可以獨立單個地研究這些數據塊了。 - e 選項聲明将數據提取出來,而非輸出到 stdout 。提取出來的文件存放于 _filename.extracted ( 或_filename-[int].extracted ,如果前者已存在)。

由于 binwalk的本質特征,你很有可能會進入錯誤的方向。分析的文件大小越大,越有可能出錯。這是因為,在偶然情況下,一個普通的文件也可能會有 binwalk 能解析的 magic bytes 。在這種情況下,就意味着 binwalk 報告的結果是無效的。

所以,當你在用 binwalk 分析文件時,你應該大概清楚它可能的結果。舉例來說,如果你分析的設備運行的是嵌入式 Linux 系統,那麼它的 ROM 文件系統不外乎 squashfs,cramfs 或 jffs2 這些。zImage 或 uImage 也是有可能的。另外,也可能是 bootloader 鏡像。

下面是運行 binwalk 分析一個大的加密固件的例子。因為是加密文件,這種簡單的方式本來是不可能分析出有價值的信息來的,但 binwalk 卻返回了一些可能的結果。

固件的本質是軟件嗎(固件分析--工具)9

很顯然,這是錯誤的。返回這個結果,純粹是加密文件的某些字節序列與這些文件類型的 magic bytes 碰巧相符而已。另外,這些“文件”的偏移地址随意分布,使得他們看起來更不像是合法的文件類型。

binwalk 正常的、有意義的輸出結果大概是這樣的:

固件的本質是軟件嗎(固件分析--工具)10

從結果可以看到,該文件包含一個 uImage(大小、名稱與 entry point 基本一緻,) 和 JFFS2 文件系統。因為内核通常是經過 gzip 壓縮的,所以緊接着内核頭之後的 gzip magic bytes 也說得通。内核和文件系統兩者都是啟動嵌入式 linux 系統必須的。更加巧妙的是,這兩者的偏移地址( 0x200000 和 0x800000 )都十分整齊。盡管在實際情況中,這基本不可能,但是,在這裡也隻是為了強調效果。

>>>>3.5 fdisk

有時,碰到的設備是相當高端的産品,而且它的固件文件很大 -- 往往是整個的驅動鏡像。這通常是以為該設備具有豐富的資源,處于向桌面平台發展的過程中。試試 fdisk -l 或 fdisk -lu ( -u 選項指定以 segment(段) 标記分區大小,而不是默認的 “cylinders(柱面)”)。

這是一個不含有效磁盤鏡像的文件的 fdisk 輸出:

$ fdisk -l file.bin Disk file.bin: 104.3 MiB, 109407232 bytes, 213686 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes

而包含有效文件系統的輸出則與下面相似:

$ fdisk -l file.bin Disk file.bin: 2.6 GiB, 2751447040 bytes, 5373920 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xcd42b400 Device Boot Start End Sectors Size Id Type file.binp1 3892371390 4109164418 216793029 103.4G 72 unknown file.binp2 3287936629 3304577640 16641012 8G 6 FAT16

從這裡可以看到,一個 FAT16 鏡像位于 3287936629到 3304577640 之間。鏡像大小是 8 GB。

利用這些數據,我們可以用 dd (稍後會詳細講解)從固件把該文件系統提取出來。一旦将文件系統提取出來了,就可以用合适 mount 命令将它恰當地挂載到系統上。挂載文件系統是另一門額外的高深學問 ,另寫一整篇文章來讨論它也不為過。不過,根據 fdisk 判定的文件系統類型,結合網絡,搜索到合适的挂載命令/工具,成功挂載文件系統也不是很難的事情。

另外,特别說明一下。有些情況下,在一個非原生系統上你需要加載内核模塊(QNX 系統尤其要注意)。

如果得到的文件包含多種文件系統,想要把這些文件一次性提取出來,可以用下面一行命令:

fdisk -lu file.bin | egrep -i 'file.bin[0-9]' | sed 's/ */ /g' | while read line; do dd if=file.bin of=$(echo $line| cut -d' ' -f1) skip=$(echo $line | cut -d' ' -f2) count=$(echo $line | cut -d' ' -f4); done

>>>>3.6 dd

說到 dd 命令,很多人可能害怕它。的确,使用不當的話确實有可能把磁盤廢掉。不過,這也僅僅是當你把 of 設置成錯誤的路徑了(譯者注:dd 一般的用法是提取某處的文件,輸出到另外一個位置。of 是指 output file,輸出路徑,如果把 of =/boot 就會将提取的文件輸出到 /boot 下,從而覆蓋系統原來的啟動文件,導緻無法正常啟動)。使用中絕對要小心。

即便如此, dd 依然是一個極其簡單高效的字節級複制工具。尤其是在支持“dollar bracket bracket”語法的 Shell 中。這在将十六進制轉化成十進制以及在處理不同文件塊大小等基本算術運算中十分有用。

dd 的幾個必須知道的關鍵參數有:

if = [ FILE ]

dd 的輸入文件從這裡讀取。

of = [ FILE ]

dd 的文件輸出位置。

bs = [ NUMBER ]

塊大小。dd 所有的數值參數都将以該大小的倍數計算。默認的塊大小為 512 。如果你不介意運行的緩慢,煩人的數學運算的話,設置成 bs=1 也是可以。

skip = [ NUMBER ]

讀取輸入文件前跳過的塊。

count = [ NUMBER ]

從輸入文件拷貝到輸出的總的塊數目。

所以,當我們想從 firmware.bin 中提取 0x200 到 0x400 這一塊時:

固件的本質是軟件嗎(固件分析--工具)11

記住, dd 是對按塊對文件操作的。因此,在計算具體的塊大小,塊數目時,需要特别精确。如果你想确保安全,可以設置塊大小 bs = 1 。

4、GUI hex 文本編輯器

當事情更進一步時,為了更具可視化,你可能需要一款 GUI hex 文本編輯器來幫助固件分析。到目前為止,我還沒有找到一款完全符合我需求的編輯器。我理想中的 hex 文本編輯器應該是這樣的:能夠可視化二進制文件,辨别出常見文件中的有效字節,可視化信息熵,包括字節碼。支持文本标記和高亮,列出字符串等等。不過,不管怎樣,适合自己的就是最好的。

日複一日,我傾向于用 HxD 做基本的單調性工作,wxHexEditor 來做文本标記(note-taking)和高亮顯示任務。例如:

固件的本質是軟件嗎(固件分析--工具)12

除了這兩款外,還有衆多的 hex 文本編輯器,所以選擇那一款隻是個人喜好問題。不妨多試試,體驗一下它們的差别。

(上篇 完)

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved