Apple TV 3 登入 iCloud 成功:從憑證錯誤到照片串流檢查的排查紀錄
Apple TV 3 登入 iCloud 成功:從憑證錯誤到照片串流檢查的排查紀錄
前言:iTunes 可以登入,為什麼 iCloud 不行?
我最近在整理一套舊款 Apple 裝置,希望把 Apple TV 第三代重新接回自己的蘋果生態圈。這台機器的 iTunes 已能登入,電腦媒體也能播放,偏偏 iCloud 一直失敗。帳號密碼已確認,舊裝置卻常常連雙重認證通知都沒有觸發,看起來很像帳號出了問題。
這次我和 Codex 透過 SSH、原生介面觀測與受限的程序內修補,一層一層排查,最後讓 Apple TV 的原生 iCloud 登入成立。本文記錄的是這一台裝置的實作過程,不是所有舊版 iOS 都可直接套用的通用安裝教學。
先說結果:iCloud 選單已出現「登出」,系統帳號儲存區中存在主要 Apple 帳號,照片介面也讀到共享相簿項目。本文的成功範圍是「原生 iCloud 登入成功」;相簿內照片播放、移除測試元件後的狀態,以及整機重新開機後的持續登入,尚未完成驗證。
一、這次使用的環境
Apple TV 的版本名稱容易混淆。這次直接讀取 SystemVersion.plist,ProductVersion 是 8.4.4、MarketingVersion 是 8.4.3、ProductBuildVersion 是 12H1006,因此三個欄位一起記錄。本文不把它寫成現代 Apple TV 的 tvOS 版本,也不只靠外觀判斷是哪一代。
越獄前段使用 Blackb0x,完成後除了看到工具的 Done 提示,還實際確認 root SSH、套件狀態與原生程序存取。這些是後續診斷得以進行的環境條件;單純在未越獄的設定畫面輸入密碼,無法完成本文的程序內修補。
二、我們遇到的其實不只一個問題
一開始,原生介面顯示「帳號或密碼不正確。請再試一次。」。後來越過前面的障礙,又變成「此 Apple ID 帳號未設定 iCloud。」。如果只看畫面,兩者都很容易被理解成帳號有問題。
但登入流程包含網路連線、憑證信任、輔助資料取得、Apple 認證、裝置端條件判斷與帳號保存。任何一層失敗,都可能被舊介面包成很籠統的錯誤。我們因此停止盲目重送密碼,改成追蹤每一階段實際走到哪裡。
先前也懷疑過驗證碼、網頁登入與區域 IP。把 Mac 放在同一個網路中作為輔助端,有助縮小環境差異;但最終證據沒有證實「Apple 鎖區域 IP」是根因。不能因為同網路方案最後成功,就把原因歸給 IP。
三、測試思路:每一層只回答一個問題
- 先確認 SSH 主機身分、型號與實際系統 build。
- 檢查原生選單與元件是否載入,不以套件安裝成功代替生效。
- 對輔助服務做不帶帳密的連線與 TLS 測試。
- 只記錄認證階段與結果,不傾印敏感回應。
- 伺服器階段完成後,追查裝置端的拒絕條件。
- 條件明確後才做受限修補,再從原生 UI 與帳號保存驗證結果。
我們刻意不保存完整認證回應、token、anisette 值或帳號物件。診斷只保留階段名稱、必要錯誤碼與布林值,文章也移除了帳號、網路位址、裝置序號、相簿名稱及私人內容。
GSAPort 是這次使用的社群認證相容性元件。實際套件是 Beta 2.0-1+debug;套件能安裝,不代表已對 Apple TV 生效。Apple TV 的介面程序是 AppleTV,不能直接假設 iPhone 的 SpringBoard 流程也存在。我們把載入範圍限縮在 AppleTV 與 accountsd,確認元件與觀測點真的存在後,才進行登入測試。
四、第一道障礙:舊系統不信任輔助網站的憑證鏈
第一輪觀測顯示,登入請求已被 GSAPort 接住,卻在取得 anisette 輔助資料時遇到 NSURLErrorDomain -1202。獨立原生連線測試還看到底層 SSL -9813。這時流程根本還沒有走到後面的 GSA 認證,沒有跳驗證通知並不能用來證明密碼錯誤。
我們核對了裝置時間、伺服器憑證有效期與信任鏈。使用官方 ISRG Root X1/X2 作為單次測試的信任錨後,原生信任評估可以通過;把測試主機名改錯,仍然會失敗。這個反向測試很重要:它證明正常主機名驗證仍在運作,而不是把所有憑證都接受。
取得同意後,安裝只含官方 ISRG Root X1 的可移除描述檔。它沒有 VPN、代理或 MDM 設定,但會增加整台裝置對這張公開根憑證的信任,範圍不限單一網站。憑證來源是 Let’s Encrypt 官方,並回讀實際安裝的憑證內容比對。
安裝本身也遇到問題:獨立 root Cycript 程序缺少 ManagedConfiguration 所需 entitlement,被系統拒絕。我們沒有偽造 entitlement,而是改由既有 AppleTV 程序的系統 API 完成安裝。之後原生 HTTPS 測試不再出現 -1202。
另一個容易誤判的地方是,機上的舊 OpenSSL 命令列仍握手失敗。它和系統原生 Security/CFNetwork 不是同一條測試路徑,所以我們以實際登入會使用的原生網路堆疊為準。
五、第二道障礙:TLS 修好了,輔助服務卻回 HTTP 500
憑證修復後,錯誤從 TLS 失敗變成輔助服務 HTTP 500。這代表 HTTPS 已經能連上,但服務沒有提供可用資料,不能把「連線成功」當成「登入成功」。
我們再做一次不帶 Apple 帳密的 helper-only 測試,同樣收到 HTTP 500。這把問題縮小到該輔助請求或後端相容性;它不夠證明整個服務對所有人都故障,也不能用來判定 Apple 帳號有問題。
接著參考 AltStore 官方 AnisetteDataManager.swift 的做法,在同網路的 Mac mini 讀取 AOSKit 提供的 anisette headers。Anisette 可以理解為認證流程需要的一組裝置相關輔助資料,和使用者手動輸入的六位數驗證碼不同。
Mac 的暫時 helper 只綁定 loopback,透過 SSH 反向轉送讓 Apple TV 存取,並設有 15 分鐘期限。Apple TV 程序內的轉接只替換原先的 helper 請求;Apple 的 HTTPS 認證連線保持原路徑。這個 helper 不接收 Apple 帳密,產生的資料也不寫入檔案。
替換後,兩次 GSA exchange、authenticate 與 get_account_settings 都收到 HTTP 200。但原生介面仍拒絕登入,顯示「此 Apple ID 帳號未設定 iCloud。」。這正是我們繼續查裝置端判斷,而沒有提早宣布成功的原因。
六、第三道障礙:Apple TV 還在檢查已停用的照片串流
我們接著分析 AppleTV 原生登入完成處理函式 _authCompletionHandler:error:callbackType:。在沒有 NSError 的路徑中,它會先檢查 MediaStream 是否已開通,再檢查主要電子郵件是否已驗證。任一條件不成立,就走到 BRError 1401。
為避免只憑反組譯猜測,我們在裝置上建立同一錯誤碼,確認其本地化文字正是「此 Apple ID 帳號未設定 iCloud。」。同時核對執行檔雜湊、原始指令與系統 dataclass 常數,確認分析的檔案和實機相符。
失敗後讀取仍存活的認證帳號物件,得到下面三個布林值。這裡沒有輸出帳號身分,也没有傾印完整帳號資料。
mediaStream = false
sharedStreams = true
emailVerified = true
也就是說,這個帳號具備 SharedStreams 權限,郵件也已驗證,卻因 MediaStream 是 false 而被舊程式拒絕。Apple 官方公告指出,「我的照片串流」已於 2023 年 7 月 26 日停止服務,並且是與 iCloud 照片不同的服務。
官方公告提供了背景,真正把問題鎖定到這台 Apple TV 的證據,則是原生分支、錯誤文字、帳號布林值及後續受限修補結果。這不代表每一台舊裝置的 iCloud 失敗都由相同原因造成。
七、最後怎麼修:只調整一個過時的登入前提
取得受限修補測試同意後,我們製作了針對本機 build 的原生 C 動態函式庫。它使用 Substrate 的 MSHookMessageEx,在 AppleTV 程序記憶體中攔截 ACAccount 的 isProvisionedForDataclass:。
這項修補確實會在特定位置改變一個判斷結果,因此必須把範圍講清楚:它不全域開通 MediaStream,而是只在已核對的原生登入完成檢查位置,允許「SharedStreams 已開通且主要郵件已驗證」的帳號繼續走原生登入流程。
- 先呼叫原方法;原本已通過的查詢不變。
- 只處理 MediaStream,且必須來自這個 build 的指定登入檢查位置。
- 原生 SharedStreams 必須為 true,主要郵件也必須已驗證。
- 最多生效一次,且必須在安裝後五分鐘內命中。
- 條件不符、來源不符、逾時或已用過,都維持原結果。
本次 build 的目標呼叫返回位置是 0x9935c,執行時會依 image base 換算;不是把這個數字當成所有韌體通用的絕對位址。build 與完整檔案雜湊在部署前核對,載入後的安裝函式另核對原始指令、方法簽名及必要符號。沒有修改磁碟上的 AppleTV 執行檔。
Apple 的帳密與 GSA/iCloud 認證仍然需要通過。修補沒有製造成功的伺服器回應,也不會讓 Apple 已停止的照片串流服務復活。
這是一次有條件、限時、只生效一次的相容性實驗,不是做成開機常駐套件。重啟 AppleTV 程序可以移除該記憶體 hook;但「具備撤回方式」和「成功登入後已完成撤回驗收」是兩件事,本文沒有把後者寫成已完成。
八、修補過程也走了幾段彎路
這幾次失敗讓我們學到:沒有日誌,不一定代表沒有執行;有 ready 訊息,也不代表真的攔到目標。必須把「工具有載入」「目標有命中」「條件有通過」「帳號有保存」分開驗證。
最後一輪先完成密碼欄輸入,再啟用五分鐘測試窗口並提交。這次計數顯示 calls=1、queries=1、matches=1、used=1、expired=0,表示精確呼叫位置命中一次,且在期限內完成受限調整。畫面停在連線中約半分鐘後返回 iCloud 設定,沒有因等待稍久就中斷程序。
九、我們怎麼確認真的登入進去了?
這次沒有只看 HTTP 200,也沒有只看畫面不再報錯。我們交叉檢查原生選單、系統帳號儲存區與照片資料模型。
其中,系統帳號儲存區的檢查使用 ACAccountStore 的 aa_primaryAppleAccount,只記錄是否存在,再讀取 SharedStreams 與 emailVerified 的布林值。這比先前僅在登入暫存物件中看到帳號,更能證明原生登入流程已把帳號保存下來。
照片介面接著讀到兩個 ATVCupidSharedPhotoStream 項目,底層對應 MSASAlbum。這是一項後續功能線索,但仍不等於每個相簿的照片都能下載或播放;文章不公開私人相簿名稱與內容。
啟用照片介面時,系統還問是否把「我的照片串流」用作螢幕保護程式,我們選擇否。舊選單仍存在,不代表 Apple 的舊服務仍在運作。
十、成功之後,哪些事情仍要分開看?
- iCloud 登入:本次已成功,使用者也確認以此作為登入目標完成。
- 共享相簿:已取得項目;照片內容顯示與播放尚未驗證。
- 我的照片串流:Apple 已關閉服務,本次沒有恢復它。
- 持續性:尚未證實移除測試元件或整機重新開機後仍可正常使用。
- 其他裝置:iPad 3/iOS 8.4.1 等案例只是研究線索,本次成果不能直接外推。
成功當下的測試環境仍涉及 GSAPort、Mac 暫時 helper、SSH 轉送及程序內修補。helper 有期限、hook 只生效一次,但這不能替代正式清理及重啟後的驗收紀錄。本文停在這次已證實的原生登入成果,不把它包裝成免維護的永久解法。
如果其他人想重現,應先核對自己的型號、build、原始指令與套件來源,再依同樣的分層方式找出實際卡點。不能把本文的位址照貼到另一個韌體,也不應關閉 TLS 驗證、把所有服務旗標改成 true,或反覆提交密碼來碰運氣。
結語:錯誤訊息說的是結果,未必說出了原因
這次最有收穫的地方,是把一個看似「帳號密碼錯誤」的問題,拆成了憑證信任、輔助服務,以及原生過時條件這三層。每修掉一層,下一個真正的卡點才會出現。
最後,我們在這台已越獄的 Apple TV 3 上完成了原生 iCloud 登入,並用「登出」選單、系統主要帳號與共享相簿項目交叉確認。以這個範圍而言,這次實作是成功的。
至於照片串流,它確實已經停止。這次工作的價值,是讓舊裝置不再被過時的前提擋在登入門外,同時誠實保留哪些功能還沒有驗證。
參考資料
- Apple:My Photo Stream 停用公告
- Let’s Encrypt:官方憑證與信任鏈
- AltStore:AnisetteDataManager 原始碼
- GSAPort 原始碼
- GSAPort 另一來源分支
本文的裝置結果來自本次 SSH、原生 UI、診斷紀錄與修補計數;上述外部資料用於服務背景、憑證來源及實作參考。
留言
張貼留言
歡迎留下您的心靈足跡👍