was successfully added to your cart.

逆向工程Mac EFI韌體與SCBO文件之謎

原文 MacRecversing Apple EFI firmware passwords and the SCBO myth
參考翻譯

當Mac電腦被開機Bios密碼鎖住時候。
如果不知道密碼要強制解開。共有下面處理方式
2008以前的Mac可使用清PRAM方式(command+option+p+r)
如果是2008後機器,官方說法是。如果要強制解開請準備發票到維修中心會幫你解開。

非正規體系則提共下面幾種方法

1.MacEFIPassword由於沒有密碼輸入限制,用可模擬usb鍵盤的teensy或是密碼破解硬體暴力破解。時效很長,成功率低。
2.MacEFI bioseeprom改寫。這方面OSSLab2015就開始使用這技術。
3.外面黑服務提供要進入mac密碼恢復模式提取33位位碼+機器序號給黑服務方。黑服務方會提供一個SCBO檔案
   將此SCBO檔案考入外接硬碟選擇其開機就可解開MacEFIpassword。

這方法其實同於一般PC解密碼機制可參考這網站

其實這流程是蘋果維修中心工程部處理方法。
我們要想要知道的是是Appleefi被攻破了?是技術上的漏洞還是流程上的漏洞?

find hash

照上面方法回傳給黑服務得到scbo文件時要照下面流程重設EFI密碼

1.格式化外接硬碟為GUID分區和MacOS擴展格式。將它命名為Firmware

2.將名為“SCBO”的二進制文件拖拽到桌面。

3.在終端執行下列命令:

4.拔出外接硬碟。

cp~/Desktop/SCBO/Volumes/Firmware/.SCBO

5.將此外接硬碟插到需要解開電腦上,同時按住Option鍵。

cp~/Desktop/SCBO/Volumes/Firmware/._SCBO

6.會看到鎖形符號,一會兒後,電腦應重新啟動,顯示啟動管理器表示已經解開EFI密碼。

SCBO樣本文件SCBO_original.zip
(SHA256(SCBO_original)=fad3ea1c8ffa710c243957cc834ac1427af0ea19503d9fc7839626f6cac4398b)

scbo hexdump

上面為解鎖全部內容。前四個字節為字符串’SCBO’,這是一個MagicNumber(0x4F424353)。在幾個字節之後,可以看到另一個字符串,前面是機器序號但序號後數據暫時都是未知數。這個檔案的總長度為324byte

 SCBO文件是如何生成

正歸來講,授權維修中心發送給蘋果支持部門就能得到SCBO文件,但你必須提供一些關鍵信息。要獲得這些信息,你必須在出現韌體密碼提示屏幕時,同時按下SHIFT+CONTROL+OPTION+COMMAND+S,從而得到一個字符串。這就是蘋果支持部門所要求提供的字符串,同時,它跟我們在SCBO文件裡面看到的字符串一模一樣。如前所述,在前面數字是機器序列號,而後面的十六位數字是每次設置、刪除或修改固件密碼時現場生成的一個數值。

 

能不能通過修改和重復利用同一個樣本SCBO文件來重置任意其他Mac的固件密碼呢?

答案是否定的。如果我們在測試Mac上建立一個固件密碼,必須生成所需要的字符串,然後對SCBO進行相應的修改。計算機將處理該文件並重新設置系統,但密碼不會重置。

這為我們提供了另一個信息:這個SCBO的內容會進行某種完整性檢驗。如果沒有這種檢驗的話,任何人都可以修改SCBO內容。

但是,如果這是真的,那些人叫賣的SCBO文件為何貌似完全有效呢?
OSSLab簡單分析這SCBO流出應該為流程上的漏洞而非技術上的漏洞。

因此,有必要更深入地挖掘和逆向EFI文件系統代碼。

下面參考中文翻譯邪惡16進位

首先,我們需要提取出所有EFI二進制代碼,這有兩種途徑,一是途徑從存有EFI內容的Flash芯片轉儲中提取,另一種是從EFI更新文件中發現的SCAP文件中提取(不知何故,fd格式也可用於某些Mac上面)。

MAC韌體庫,如果你需要早期的EFI更新,或想驗證自己的EFI閃存是否遭到修改的話,可以輕松從這裡下載所需的更新。利用UEFITool,你可以輕松地從轉儲和SCAP中提取內容(如果需要大量提取所有文件的話,最好使用UEFIExtract工具代替)。如果需要從NVRAM分區提取內容(該功能超級有用,感謝Nikolaj!)的話,則必須使用UEFITool的new_engine分支。

就本文來說,目標Mac是一個的MacBookPro8.2系統,並且所有文件都是從MBP81_0047_2CB_LOCKED。scap這個固件更新文件中提取的。您可以使用其他的固件文件:GUID仍然不變,但地址和某些內容可能會有所不同。

有效載荷提取來之後,我們終於可以著手尋找合適的逆向突破口了。開始的時候,最好的線索自然是SCBO文件的魔法值了,因為它必然會在代碼中的某個地方進行相應的檢查。對付這種類型的任務,我最喜歡的工具是bgrep。有了它,我們可以在文件中查找特定的字節序列,這個功能對於定位二進制數據來說極其有用。我們想要查找的字節是5343424F,即“SCBO”的魔法值。如果你想查找字符串,請不要忘了,在EFI二進制文件中的字符串,大部分都是Unicode(寬度為兩個字節)。

只有一個符合要求,即一個DXE階段的二進制文件,其GUID為9EBA2D25-BBE3-4AC2-A2C6-C87F44A1278C請注意,在(U)EFI的世界裡是沒有文件名這一說的,所有的東西都是通過一個128位的GUID來引用的。

scbo dxe binary

下面我們把這個二進制代碼加載到反彙編器中,嘗試了解其中到底發生了什麼。我們可以發現,檢查該魔術字節的代碼如下所示:

scbo bytes

這意味著,我們在這個問題上找到了一個好的切入點,下面要進一步了解這個函數的要去向何方,以及它是如何被調用的。

誰將使用SCBO文件

為了提高逆向效率,我們需要盡量收集盡可能多的相關信息。下面介紹如何利用該SCBO文件來重設固件密碼:

1.格式化閃存驅動器GUID分區方案和MacOS擴展格式。將它命名為Firmware(注:並非真正需要固件!)。

2.將名為“SCBO”的二進製文件拖拽到桌面。

3.打開終端。

4.在終端執行下列命令:

cp~/Desktop/SCBO/Volumes/Firmware/.SCBO

5.在終端執行以下命令:

cp~/Desktop/SCBO/Volumes/Firmware/._SCBO

6.彈出閃存驅動器。

7.關閉電腦。

8.把閃存驅動器插入到計算機。

9.啟動電腦,同時按住Option鍵。

10.你應該看到鎖形符號,一會兒後,電腦應重新啟動,顯示啟動管理器。

這給了我們一條重要的線索,我們應該去尋找具有文件系統訪問權限的代碼,然後去讀取這兩個文件之一。如果我們看看當前反彙編的二進製字符串,就會明白,我們已經在正確的軌道上了。

scbo strings

複製到閃存驅動器的。SCBO文件名就是在這些字符串中引用的,但IDA卻無法找到任何一個引用它的字符串(IDA的bug?很有可能!)。

逆向(U)EFI的二進製文件是很煩人的事情,因為每個外部函數是函數指針,所以反彙編輸出不是很簡明易懂,因此需要一些輔助工具來改善這一點。為此,我們可以藉助於Snare創建的ida-efiutils,它實際上是一組腳本,可以通過重命名函數指針、偏移量和結構來改善反彙編輸出。由於它提供的功能仍然無法滿足我的需求,同時我也不是Python愛好者,所以我橫下心來鼓搗出了自己的IDAC插件,並將其命名為EFISwissKnife。

該插件可以完成更多的任務,如給已知的函數提供原型和文檔註釋,生成統計數據,以及從已安裝和使用的協議中提取信息並保存到數據庫中。有了它,我們可以方便地找出哪些二進製文件正在安裝和使用哪些協議,無需在二進製文件中搜索字符串,再也不用浪費時間查明某協議是由哪個模塊實現的了。

下圖為我們展示了無任何插件幫助下IDA對start()函數的反彙編輸出結果。

start function no comments

同時,我們還可以看看運行EFISwissKnife後的結果。

start function with comments

從上面可以看到,它識別了兩種被調用到的(U)EFI引導服務:SetWatchdogTimer和LocateProtocol,同時,也對LocateProtocol使用的GUID給出了相應的註釋。

它的統計功能,還給出了我們就能夠在此二進製文件找到的Guid的相關信息,以及用到(U)EFI運行時和啟動服務的GUID的有關信息。它們對於迅速掌握該二進制代碼當前活動非常有用。

efi swiss knife stats

在改進版反彙編輸出的幫助下,我們繼續嘗試去理解與SCBO文件有關的事情。

由於逆向工程的藝術成分較多,科學成分較少,因此我會首先告訴你發生了什麼,然後進一步介紹它是如何發生的。

首先,此EFI二進製文件安裝時,會有一個事件通知。USB閃存驅動器插入時,會觸發該通知,並調用一個回調函數。

這個回調函數的任務之一,是嘗試從閃存中讀取SCBO文件,並驗證它的格式是否正確(例如檢查幻數等)。如果SCBO的內容看起來沒有問題,然後將通過GUID5D62B28D-6ED2-40B4-A560-6CD79B93D366設置一個新的EFINVRAM變量”.SCBO_0000″。這個GUID還可以在固件密碼實用程序中找到。這個GUID並非只用於這個變量,還用於其他變量,例如FWAppCmd等。當利用固件密碼實用程序設置、更改或刪除一個新的密碼時,就會在NVRAM中觀察到這個變量。在“.SCBO_0000”變量設置成功後,系統將通過ResetSystem服務進行重啟。

事件通知代碼可以在start()函數中找到。負責創建該事件的代碼如下所示︰

install event

在這段代碼中,最有趣的當屬CreateEvent服務的第三個參數,即notifyfunction。當事件觸發時,就會執行這個回調函數。下面的代碼僅僅用於註冊該事件,這裡來說,是一個文件系統相關的事件。

register event

現在讓我們開始考察回調函數的代碼。第一個感興趣的細節是,它試圖通過GUID為75FAB4B4-6AC1-429A-A000-6B0B95E71CA1的代碼來定位一個新協議。這個議定是由GUID為818544B5-1B9D-4E7B-8F7D-835AAEAF3B5C的EFI二進制代碼安裝的。繼續往下看,我們終於找到了一段讓人感興趣的代碼,它用來處理讀取SCBO文件的內容相關事宜(我已經將原始的函數重新命名為read_scbo_file_contents)。

call read scbo

這個函數內部,我們找到了一些文件方面的操作。

open volume

上面的代碼負責打開USB閃存驅動器卷,以便能夠讀取其中的內容。就本例而言,在我們需要檢查EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID協議的佈局,從而了解協議的每一個函數指針都在幹什麼。通常情況下,我是通過定位字符串EDK2的源碼查找協議的,雖然EDK2規範要比蘋果的EFIfork更複雜(AMIBios源碼的洩露,為我們的搜索提供了另一個好去處,特別是EDK2以外的代碼,如電源管理代碼等)。下面的代碼給出了EFI_SIMPLE_FILE_SYSTEM_PROTOCOL的結構:

efi simple file system protocol

這個協議只有單個函數,即OpenVolume。我們感興趣的是閱讀它的說明內容部分,從而了解它成功執行後會發生什麼。

open root volume protocol

OpenVolume函數將打開卷(這裡是USB閃存驅動器)的根目錄,並且返回句柄EFI_FILE_PROTOCOL.為了了解其功能,我們還需要考察另一個協議。當我們逆向(U)EFI的時候,為了查找各種協議和函數有關的信息需要不斷在代碼中查找特定字符串。因為根本就沒有幫助文檔!

efi file protocol

我們可以觀察到,EFI_FILE_PROTOCOL已經提供了讀寫文件系統上的文件所需的基本功能。雖然逆向大量的協議非常煩人,但過了一段時間之後,我們就會因(U)EFI設計之高雅而流連忘返。

先前討論的反彙編代碼,會先試圖打開根卷,如果成功的話,就會使用返回的句柄嘗試從USB閃存驅動器卷打開“.SCBO”文件。如果打開了該文件,它就會使用EFI_FILE_PROTOCOL的GetInfo函數查看該文件的大小,然後分配相應內存,最終將其內容讀入分配的緩衝區中。

find scbo size

該文件分兩步讀取,先讀入前面的12個字節,這實際上是SCBO頭部的大小。如果頭部內容無誤的話,則繼續讀取其餘的內容。

read scbo header

從上面的代碼片斷我們可以看出,它讀取了前12個字節內容,並對頭部的結構進行了檢查。該SCBO文件支持多個數據單元,這意味著可能允許單個USB閃存驅動器重置多個MAC的密碼。這對於一個必須重置許多台Mac的系統管理員來說非常有用。這樣的話,所謂“通用”的重置SCBO文件好像也就能講得通了,它只是一個帶有多個數據單元的SCBO文件而已——這只是純粹的推測,因為這種文件尚未公開發現。這個函數的其他部分代碼,將會把文件的位置重設為起始位置,從頭開始將整個SCBO內容讀入一個預先分配的內存緩衝區中。

如果SCBO內容讀取成功,接下來就會調用來自另一個協議的函數,該協議將驗證該Mac的序列號和當前nonce是否與該SCBO文件中的內容相匹配。記住,每次修改固件密碼時,nonce都會改變。

verify scbo serial

如果序列號和nonce值通過了檢查,將在EFINVRAM中新建一個名為“.SCBO_0000”的變量,如果在SCBO文件中沒有更多數據單元要處理的話,系統就會重置。新變量保存了SCBO文件中除12字節的頭部之外的所有數據,也即總長度為312字節。

set new scbo variable

現在我們對SCBO功能的運行機制已經有了更深一步的了解。

如果該SCBO文件的內容與當前的Mac匹配的話,一個新的變量將被建立,並先於任何其他操作之前重新啟動計算機。這意味著將又一次讀取EFI二進製文並處理新的變量。當前二進制代碼只負責讀取SCBO文件並完成簡單的完整性驗證,但它不能清除固件密碼。此功能是留給二進制代碼818544b5-1b9d-4e7b-8f7d-835aaeaf3b5c的。

變量“.SCBO_0000”可以在下面的固件轉儲中找到。如果你看一下這個變量的大小,就會發現正好是312字節,這與我們的預期值完全一致。

scbo in firmware

與二進制代碼9EBA2D25-BBE3-4AC2-A2C6-C87F44A1278C相關的逆向過程到此結束。現在,我們已經知道它做了什麼,接下來,我們將研究真正有趣的二進制代碼。

0x03固件密碼功能是如何實現的

在逆向新的二進制之前,讓我們先來了解一下固件密碼功能是如何實現的。

兩年前,我逆向了固件密碼實用工具,並在該工作的基礎上建立了一個EFI密碼暴力破解工具。它幫我確定出該EFI變量包含的固件密碼信息是“CBF2CC32”。該密碼是利用SHA256以MAC(MessageAutenticationCode.MAC)來存放的,其中包含可變的回合數。暴力破解固件密碼方法不適應於長度超過四位數的密碼,因為回合數越高,就越不可能在可接受的時間內破解出來。下面的結構就是描述該變量的內容的:

trb structure

給定該結構後,暴力破解工具只需要通過IOKit檢索這些信息就可以開始破解過程了,直到密碼與當前哈希匹配為止。對於四位數密碼來說,這個過程只​​需要一兩分鐘的時間。

下面,讓我們快速瀏覽一下待逆向的新EFI二進製文件中的main()函數。

core dxe main

Main()函數非常簡單。首先,將表指針BootServices和RunTimeServices存放在本地變量中,然後調用一個函數,最後安裝協議,該協議是被我們最初逆向的EFI二進制代碼所調用的。

core dxe protocol

安裝的這個協議包含有七個函數指針。該函數是由第一個二進製文件調用的,偏移量是0x18.sub_10000828。這裡,我們要驗證哪些EFI二進製文件會調用這個協議。在EFISwissKnife數據庫的幫助下,這是個非常簡單的事情:

第一列存放使用此協議的EFI二進制代碼的GUID。涉及EFI固件密碼驗證的二進制代碼是2D61B52A-69EF-497D-8317-5574AEC89BE4。這個二進製文件還安裝另一個協議,這個協議是被其他一些二進制代碼所調用的,這些二進制代碼也許與用戶輸入和屏幕繪圖有關,但是尚未查明。

如果設法修改這個函數以使其總是返回零,將其重新封裝到固件轉儲中,刷新固件,這樣,任何固件密碼都能被接受。這意味著,我們的方向是正確的。

開啟新思路

現在,我要重構劇本,因為我在逆向這些東西之前,最初想要做的是利用Trammell的無限循環技巧處理75FAB4B4-6AC1-429A-A000-6B0B95E71CA1協議的各個函數,並找到我們感興趣的,給它們打補丁使其返回零,並找出哪些函數用於驗證密碼。

協議函數sub_10000704會檢索變量“CBF2CC32”,根據用戶輸入的密碼生成哈希值,並與與該變量中的信息進行比較。常量SHA1,SHA256和SHA512可以在818544B5-1B9D-4E7B-8F7D-835AAEAF3B5C二進制代碼中看到。

如果你有SPI刷寫工具,要想刪除Apple的EFI固件密碼的話,只需轉儲閃存內容,刪除“cbf2cc32”變量(實際上只需要翻轉其名稱中的一個比特即可),然後刷新修改後的固件即可。或者找到變量,直接擦除或修改它,這樣就無需刷寫所有內容。

實際上,還有另一種方法。變量“3E6D568B”具有特殊用途,因為如果刪除它,NVRAM就會被重置為缺省狀態,而該狀態下是沒有設置固件密碼的。

這樣,什麼論壇啊,價格讓人蛋疼的EFI密碼重置硬件啊,統統都免了:只需一個SP刷寫工具和SOIC夾,你就可以搞定一切。

這個75FAB4B4-6AC1-429A-A000-6B0B95E71CA1協議代碼中的其餘函數中,只有一個與SCBO有關,它被9EBA2D25-BBE3-4AC2-A2C6-C87F44A1278C二進制代碼所調用,這個二進制代碼的作用是驗證SCBO的序列號和nonce是否與當前的Mac相匹配(offset0x18,sub_10000828)。

這意味著變量“.SCBO_0000”還會被其他函數處理。其實就是在main()中調用的sub_10000314函數(圖18)。這個函數將對該變量相應的處理,並且如果“3E6D568B”變量出現前面提及的情況的時候,重置NVRAM。

位於函數sub_10000314前面的變量”3E6D568B”將被NVRAM所檢索,如果它不存在的話,代碼流將被重定向到地址0x100003CD處。

在上面的截圖中,始於地址0x100003CD的代碼刪除了幾個變量,其中包括”CBF2CC32″,並再次創建”3E6D568B”,以使得Mac不會陷入死循環。我將這個函數標註為”zero_EFI_variable”,它的作用是通過將參數DataSize設置為零來刪除變量。根據(U)EFI的文檔來看,”大小為零的變量將被刪除”。

跟踪變量SCBO的處理代碼

下面的問題是,如何跟踪處理變量SCBO的代碼?

對於(U)EFI的二進製文件來說,進行靜態分析可不是件輕鬆的事情:如果我們要修補代碼並查看運行結果的話,每次刷寫都需要5到8分鐘。此外,相應的調試器的成本也很貴(如用於(U)EFI的JTAG調試器),許多都在6K美元以上。

對於這個大型的函數和它調用的其他函數,許多部分我已經做過逆向分析了,雖然沒找到處理SCBO變量內容的代碼,但是,我並未打算逆向所有東西,同時也受夠了這種修改代碼然後刷寫的方式——實在是太慢了。

當時,我又萌生了一個新點子!利用UnicornEngine框架創建一個EFI模擬器和調試程序如何?我感覺,這還不是非常困難和耗時,因為EFI環境是自成一體的——例如沒有連接器和系統調用。我也知道,此二進製文件是多少有點獨立,僅使用了很少的Boot和RunTime服務,並且涉及的外部協議也很少。由於Boot和RunTime服務的總數量非常少,這就意味著,有沒有大量的代碼需要我們進行仿真。

鼓搗了沒幾天,EFIDXE仿真器就誕生了。我真是服了我自己:終於能夠在用戶態運行調試EFI二進制代碼了,逆向速度裡面有了前所未有的提升,這樣就能快速搞清楚前面那個難纏的代碼到底在搞什麼鬼了。

它具有gdbinit風格的用戶體驗,並且能夠模擬許多基本命令,例如設置斷點、函數的跟踪進入及跳出、內存轉儲、修改內存及寄存器等,雖然這些命令都很簡單,但是對於EFI調試來說卻極其有用。儘管該調試器較之於Unicorn/QEMUJIT的設計來說還有一些局限性(例如無法直接修改RIP或EFLAGS寄存器),但是對於基本任務來說絕對夠用了。我已經模擬了許多核心啟動和運行時服務,如獲取和設置變量及NVRAM區、分配/複製/設置內存、加載更多的鏡像,以及安裝/定位新的協議。雖然功能算不上完整,這是一個非常有用的工具,但是對於當前的以及將來的(U)EFI工程的關鍵性開發來說,非常有用。

經過一番折騰,在逆向這個函數之後,我終於搞懂了SCBO的功能。首先,SCBO的文件結構可以利用下列數據結構來描述:

我們最初搞不明白的那些二進制數據,不過是一個2048位的RSA簽名。除非有人找到了蘋果的私有密鑰,否則,根本無法創建SCBO密鑰生成器。那麼,網上的那些視頻,以及有人宣稱他們能夠從網站購買SCBO文件是怎麼回事呢?我敢打賭,這是由於某種未知的原因,某些傢伙能夠向蘋果的支持系統提交非法請求,然後將收到的SCBO文件出售,以獲取不菲的收入。這些人可能是在蘋果支持中心工作,甚至有可能是蘋果公司的內鬼。只有蘋果公司才能真正調查和跟踪這些文件的來源。另一種選擇是,通過漏洞,不過我還沒有找到。這些代碼和設計看起來毫無破綻,至今還沒有找到明顯的安全漏洞。

為了驗證這一假設,我弄來了一些以前用來驗證SCAP的固件更新的簽名的代碼,最後終於證明我得到的SCBO文件的確是一個具有有效蘋果簽名的SCBO文件,但是,卻無法通過修改它來用於其他機器,除非給某些固件代碼打補丁(這實際上沒用,因為如果你可以給固件代碼打補丁的話,還不如直接重置這些變量)。

處理SCBO內容的核心函數是sub_100021f0。它的首要任務之一是分配一個0x110(272)字節的緩衝區來保存蘋果公司的公共密鑰。

這個緩衝區具有下列所示的數據結構:

地址位於0x1000128c的函數,將負責從EFI的“文件系統”檢索蘋果的公開鑰匙。該固件包含五個不同的2048位的公鑰,可以從EFI文件B2CB10B1-714A-4E0C-9ED3-35688B2C99F0中找到。

每個原始文件的長度是276字節,這就是說前20個字節都只是頭部信息,對於我們來說毫無意義。我們只需要刪除這些頭部字節,就能獲得256個字節的公鑰。在TrammellHudson的Thunderstike演示文稿中,有一個重要的細節是密鑰字節是倒置的。如果想要在自己的工具中使用此公鑰的話,我們必須把這些字節顛倒過來。再次提醒,密鑰不是直接由函數提取的,而是像通常那樣,由一個協議來實現這種功能。該協議的GUID為ac5e4829-a8fd-440b-af33-9ffe013b12d8,並通過二進制代碼8b24e4d4-c84c-4ffc-81e5-d3eacc3f08dd進行安裝。逆向整個協議是毫無意義的;我了解到它會檢索蘋果的公鑰,這就夠了。

為避免模擬與文件系統相關的操作,我直接使用了Unicorn代碼鉤子,並註入了正確的公鑰。我們使用了圖33中的第三個公鑰來驗證SCBO的簽名,其SHA256為94218318fe5aaada2889bbd5f9789cf4afa15bd6eb7654ad66f1f199cf70f8ad(整個原始文件是通過UEFITool提取出來的)。

此外,還將分配另一個32字節的緩衝區來保存SHA256的哈希值。稍後,我們將看到此緩衝區的作用是,保存這個SCBO變量的前56個字節的校驗和。

下一步是在物理內存中,從地址0x0FFFFFF08處提取序列號。如果你引導一個Linux安裝並使用Chipsec來讀取物理內存的話,你就能夠讀取Mac的獨立編號(在較舊的macOS版本上,您也可以使用AppleHWAccess.kext或DirectHW.kext來讀取內存,但在新版的系統中已經不可用了)。

下一步是從變量”BC9772C5″中提取當前nonce。目的是建立跟SCBO中看到的一模一樣的序列號+nonce字符串。

我們可以利用調試器觀察在調用包含printf的函數前後的相應變化。

生成的這個字符串將用來替換SCBO緩衝器區中的序列號+nonce串。簽名驗證代碼將使用從Mac獲得的當前值,而非從SCBO文件中獲得的值。

這樣,我們可以計算SCBO前56字節內容,field1,field2,以及前述的SCBO_CONTENTS結構中的序列號+nonce的哈希值了。

我們可以利用調試器來觀察這些結果。如果我們從SCBO文件中提取的相應內容併計算哈希值,如果與我們之前的哈希值匹配的話,則意味著我們的思路是正確的。

最後一步是驗證RSA簽名,以保證序列號+nonce沒有被篡改。

由於蘋果的公鑰不止一個,所以我們將會看到一個循環結構,這意味著該簽名將針對固件“文件系統”中發現的所有蘋果密鑰進行驗證。如果返回一個有效的結果,那麼該密碼將被刪除,實際上就是從NVRAM中清除“cbf2cc32”。

如果參數DataSize(R9寄存器,地址0x100024F8)為零,則該變量就會從NVRAM中被刪除。此代碼再一次表明了,EFI密碼功能確實是通過NVRAM變量”CBF2CC32″實現的。

小結

好了,SCBO及其格式的神秘面紗已經被我們徹底揭開了。在這個過程中,我的EFIDXE仿真器和調試器功不可沒,極大提高了我的逆向過程的速度。我們看到,該SCBO的功能設計是健壯的,但是網上在售的貌似有效地SCBO文件對我來說仍然是一個迷。我敢打賭,這可能是由內鬼通過蘋果技術支持中心獲得了蘋果系統的訪問權限,但再次聲明,這只有蘋果公司才能查明原因。

如果你忘掉自己的固件密碼,現在可以自己重置它了,只要SPIFlash芯片不是較新的BGA類型(新的Mac電腦當前使用的就是這種類型的芯片,不過通過一種隱秘的調試端口,照樣可以達到同樣的目的!)。你只需要一個裝置來轉儲閃存芯片,刪除變量,然後刷寫上修改後的版本,或直接刪除變量(我總是喜歡完全轉儲然後重新刷寫閃存的方式)。

當然,這些信息可能被小偷偷用來銷售被盜的Mac電腦,但實際上網上已經到處都能獲得相關東西了,不過,本文並沒有透露任何以前未曾揭露的秘密。

我不僅希望你喜歡這篇文章,更希望能通過它激起對(U)EFI逆向技術的興趣。當然,由於缺乏相應的調試器,該技術並沒有用戶態或內核逆向技術那樣輕鬆,不過,只要稍微多做一些努力,這些困難仍然是可以解決的。目前,出於某些原因,我還不打算公開自己的EFI仿真程序的代碼。

Thx Chang

Author Thx Chang

More posts by Thx Chang

Leave a Reply