我擋住了 Geohot 三十分鐘

那個 macOS app 也已經下架好幾年了,現在可以來聊聊當時的趣事。

十年前,我還在一家國產線上音樂串流服務打工。那年 Geohot 來台灣參加駭客年會,年會結束後,公司同事也爭取讓 Geohot 來公司演講。

全公司前後端工程師聚集在公司最大的那一間會議室,座位不夠,會議室角落也都坐滿了人,等待大神蒞臨。活動從早上十一點四十五分開始,預計進行四十五分鐘,十二點半之後,會安排與主辦活動的那幾位同事共進午餐。

他在前十分鐘內,首先做了一個謙遜的自我介紹,並且謙稱資安啊、入侵啊、破解啊…也沒什麼,絕大多數時刻,入侵者用的,往往也是些固定的手法,做資安其實也就是幾個大原則,像是能在線上管控的服務,就不要讓其他人可以在本機上使用,而想要防止入侵,就是自己也要有入侵者的思維,才會知道其他人可能會怎樣入侵,就這些。 — 他最近常收到邀請,像是昨天去了另外一家 T 社,今天來我們公司,他都不知道該講些什麼。

我跟旁邊的同事交頭接耳,說,今天他來我們這邊講 T 社的事情,大概過柳天,他也會在其他地方,講我們的事情吧。

既然能講的有限,那不如實戰演練,接下來的時間,讓大家看看我們的服務可能有哪些漏洞。他把 MacBook 接上了投影機,瀏覽公司首頁,首頁上最醒目的內容,就是「立刻下載 App」的按鈕,除了手機版本外,還有 Windows、macOS 兩套桌面版本。

他又重複了一次,像這種線上串流服務,如果只做線上版本,會遠遠比桌面版本安全,為什麼不只做線上版本就好呢?我們回覆,沒辦法,商業上,就是得要有離線聽歌的需求。雖然日後桌面上的方案,也逐漸往純網頁技術、以及網頁中的 DRM 方案發展,但已經是五六年後的事了。

喔,得離線啊。你們真的得知道這樣有多危險耶。

投影畫面中,就看到 Geohot 下載了一套 macOS 版本的 App,畢竟他現在用的是 macBook,有位同事幫忙設定帳號,其他同事則是先發出一陣騷動,視線全都投向了我這邊 — 畢竟 macOS 版本,還有其他蘋果平台上的版本,是由我負責的。

我聳聳肩。

Geohot 一邊操作一邊講解:一般想要破解桌面軟體,會先想辦法讓 debugger 可以 attach 到指定的 process 上,接下來對看起來有意思的地方,設定中斷點,在中斷的時候再去看一下 call stack 以及暫存器裡頭的變數,那麼這套軟體就算是被你看光了。第一次可以成功打開 app,播放一首歌之後,他退出程式,再從終端機呼叫 gdb,打下 run。

接著,程式馬上退出。

喔,你們有擋 debugger。

會議室裡頭充斥著長吁一口氣的聲音。

在 macOS 應用程式中,可以用 ptrace 命令,控制是否允許 debugger 可以 attach 上來,所以,只要在 release 版本中,在程式進入點,加上一行 ptrace(PT_DENY_ATTACH, 0, 0, 0) ,就可以阻止 debugger,算是十年前 macOS 軟體的基本與主要防護,當時還沒有 Hardened Runtime 等機制。此時此刻,我在想的是 — Geohot 會不會繞過 ptrace。

當時蘋果其實在 ptrace 留了一個後門。蘋果自己所有的應用程式,看起來用 ptrace 阻擋 debugger,但當時還是有些第三方開發者,有著需要對蘋果自己的應用程式 debug 的需求 — 當時蘋果還允許第三方開發者幫一些應用程式寫 plugin,像是 iTunes 的 visualizer (iTunes 直到 2015 才慢慢變成 Apple Music,在桌面軟體在一段時間內,也還是叫做 iTunes) ,這些 plugin 都還沒有變成後來跟主程式隔絕開來的 extension 架構。據說蘋果就對一些第三方開發者私下開放了一個後門,而應該私下流傳的後門,後來不知道怎麼傳的,反正在 macOS 開發社群中,變成幾乎是路人皆知。

這個後門是,進入 debugger 之後,先不要直接 run,而是先針對 ptrace 命令設定中斷點(gdb 命令是 break ptrace),才輸入 run。接著,程式就會在我們所設定的那一行 ptrace 停下來,接著,我們可以在 debugger 中輸入一行 return,再輸入 continue,就會繞過 ptrace,繼續執行程式。

要擋住這個後門,就是額外判斷程式是否收到 SIGTRAP,如果收到了,就強制退出,不讓其他有心人繼續執行程式。我那時候還加上了一段文字,在退出程式的時候,對方會看到「我們公司持續徵才中,您可以寫信到以下電子郵件信箱…」在前公司服務期間,還真的收到有人因此來信應徵,不過也就只有那麼一封信而已。來信中說有意應徵前東家的職位,不過他的專長是在後端,我就把這封信轉給了 gslin,但他在面試過程中似乎不順利,後來也不了了之。

回到 Geohot 這邊。他看起來打算選擇 debugger 以外的手段,先用 nm 把整個程式裡頭有哪些 symbols 倒出來,快速掃描了一遍。啊,有意思,你們有用 CommonCrypto。那麼,只要對 CommonCrypto 進行攔截,那也就可以拿到你們用什麼 key 加解密了。

CommonCrypto 是當時蘋果平台上主要的內建加解密函式庫,蘋果後來用 CryptoKit 取代。就看到 Geohot 一邊演講,一邊打開 vim,在大家面前,飛快地按照 CommonCrypto 的介面寫了一段 C 程式,內容是把 CommonCrypto 裡頭的加解密函式的實作換成把 key 列印出來,編譯成動態函式庫,過程如行雲流水。接著,就是把這個函式庫注入到我平時在維護的那套應用程式中。

會議室中所有人屏息以待。來吧,我們現在來看看,在開始播放歌曲之後,我們會拿到什麼?

終端機上出現的結果似乎讓 Geohot 也有些意外。終端機上的確顯示出了加解密的 key,不過呢,只要是在播放歌曲期間,每秒鐘大概都印出了幾百把不同的 key,所以在他的終端機上,就是大量的文字飛掠而過。門外突然傳出人聲喧嘩,原來是中午用餐時間到了,非工程師的其他同事要離開座位吃飯。今天的活動也該到尾聲,大家去吃飯吧!

在這每秒鐘出現的幾百把 key 當中,到底哪一把、或是哪幾把是用來加解密歌曲內容的,甚至當中到底有沒有用在歌曲內容上,歌曲加解密用的是不是 CommonCrypto,我就不方便寫出來了。總之,在一片要去吃飯的吆喝聲中,我糊裡糊塗地擋住了 Geohot 三十分鐘。

我常在想,如果當時再給他五分鐘,可能又會是完全不同的故事了。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.