これは、第 3 世代から第 5 世代の iPod Nano に影響を与える wInd3x bootrom エクスプロイトの記事です。 . このエクスプロイトを利用するための活発に作成されたツールは、github.com/freemyipod/wInd3x にあります。
バックグラウンド
2020 年の 12 か月です。廃棄物インスタンスが近づいています。 私は YouTube で Dankpods というタイトルの愚かなオーストラリア人男性に見えます。
「ねえ、iPodってなんかいいよね! 私は彼らにドゥームをぶつけたい」、私は自分自身に言いました.
私は現時点で、これらのぼろぼろの iPod の多くが「解放された」http://q3k.org/「ハッキングされた」ことに気づきました。 」 (これは、吸収ツールをそれらに押し付ける可能性があることを示唆しています)、それらの山は静かではありませんでした。 当時、iPod Nano 4G よりも現代的な機器でコードを実行するという選択肢はありませんでした。
たまたま見つけたミニチュアの意外な一品。 容認できません。 これらのデバイスの安全性は、古い iPhone と同じように完全に壊れているに違いないと思いました (精査: checkm8 vuln)。
つまり、不規則な iPhone エクスプロイトを iPod に適切に移植することはできますか? 彼らは、なんらかの形のプロト XNU か何かを愛するべきではないでしょうか? 今はそうでもないのに、ハッキング可能な大規模なものは常にあるはずです、正直?
iPod Tech Stack
成功しましたが、まだ完全ではありません。 復習しましょう:
Working machine: 実行中の iOS/XNU の代わりとして、iPod はカスタムの組み込み RTOS を展開しますが、これには効果的に文書化されたものさえありません。題名。 あるいは、RTXC マイクロカーネル全体に完全に基づいており、Apple が製品ライフサイクルの中ですぐに買収した組織である「Pixo」によって提供される UI スタックを使用しているわけではありません。 事実の要素は、ここではセキュリティ指向の OS ではなく、バグが大量にある可能性が高いということです。 忌まわしい現代は、通常、評価も既知のバグも何もないということです。
ブーツチェーン
: すべてが暗号化され、署名されています (これについては後で説明します)。 オンダイの BootROM (初期の iPhone や iPod touch で使用されていた BootROM に相当) は、NOR/NAND の第 2 段階のブートローダーに適切にチェーンされます。またはディスクモードまたは診断。 興味深いことに、第 2 段階のブートローダー (および診断ツールが大好きなペイロードのペア) は、完全に EFI ファームウェア ボリューム/ドライバーに基づいています。 ただし、それはすべての主題です。ハードウェア: 初期のデバイスは昔ながらの PortalPlayer SoC です。 私が真剣に取り組んでいるデバイス (Nano 3G+) は、Samsung S5L87xx SoC を採用しています。これは、S5L89xx の初期の iPhone SoC の末期です。 S5L8720 は、iPod Nano 4G および iPod Touch 2G のすべてが時代遅れですが、確かな BootROM を備えています。 これらの SoC のデータシートは公開されていません。
ブート セキュリティ チェーン
楽器の同じ古いブート循環は次のとおりです:
.--------. | | BootROM | '--------' | | | V .------------------------- を検証します。 | | 第 2 段階のブートローダー | | | (ナンド/ノア) | '-------------------------' | | | |'-------.------------- を選択して検証します。 VVV.--------. -----------。 .--------. | | OS | OS | | | ディスク モード | | | 診断 | | | (ナンド) | | | (ナンド) | | | (ナンド) | '--------' '-------------' '--------'BootROM は、NAND/NOR の特定のセクターから 2 番目のステージをロードするための設計図を使用して十分なハードウェア起動を実行します (機器の世代を考慮)。次に、第 2 段階のブートローダが、LCD/DMA/DRAM/VIC などの多様な周辺機器を起動し、Apple ロゴを表示し、特定の人がファームウェアのロードを希望できるようにします (ほとんどの主要なファームウェア、ディスク モード、または診断)キープレスで防御します。 ファームウェアは NAND からロードされますが、今回は大量の Flash Translation Layer を経由します。
ロードされるすべてのステージ (および BootROM 自体) は
Image1、これも初期の iPhone デバイスでは古風なものに変わりました。 この構造体には次のセキュリティ プロパティがあります:
ヘッダー内の他のすべてのアリーナは、同じキーを使用して本文が復号化されるかどうかを決定します。 これは、実際に見られるすべてのファームウェア ペイロードに適しています
- ヘッダー内の他のすべてのアリーナは、本体が X509 PKI マシンを使用して署名されているかどうかを判断し、フィンガープリントは初期のブート段階でハードコーディングされています。 これは、実際に見られるすべてのファームウェア ペイロードに適しており、Nano 3G よりも新しいデバイスで価値があります。<0x1c)>
問題は、常にあなたがする必要があります多様化したミニチュアを検索します器具に修復物を描かなければなりません:
.---- ------。 | | BootROM | '--------' | | | V .------------ を検証します。 | | なんてこった | | | (USB DFU) | '---------' | | | V を検証します。 | | リカバリ ディスク モード | | | (USB DFU) | '--------------------'精査することもあるかもしれませんが、復元を行うときに、同様にセカンダリ ブートローダー ステージとファームウェアに分割しますが、次のステージをローカル ストレージからロードする代わりに、それをオーバーロードします。 USB、DFU プロトコルを使用。 第 2 段階のブートローダーは、理由は不明ですが「WTF」と名付けられます (奇妙な第 2 段階のブートローダーとの最も大きな違いは、USB DFU 経由で次の段階をロードするようにデフォルト設定されていることです)。
さて、あなたはすでにここで苦境に立たされているでしょう。 ブートロムを含むブートローダの初期段階で、大量の USB スタックと DFU プロトコルの実装を実行しています。 多くのプログラムのセキュリティは、可能な限り最高の特権範囲で実行される見掛け倒しの USB 実装に陥っています。 そこにピンを入れます。
先行技術
間違いなく、これらのデバイスを解放しようとしたのは私が初めてではありませんでした。
最初に、uClinux (現在は Linux nommu) のポートである iPodLinux に変更され、PortalPlayer ベースの完全に不規則な iPod に移行しました。 私たちのこれらは、iPod ファームウェアについて活発にファイル形式を評価する方向への道を切り開いてきました。 それにもかかわらず、iPod が完全に Samsung ベースのチップに移行したとき (iPod Nano 2 と iPod 'Traditional' の開始に伴い)、発生した問題はやや行き詰まりました。
その後、Linux4Nano、現在は Freemyipod に変わり、S5L ベースで完全にコード実行を取得しようとする私たちの集団です。デバイス。 現代の iPhone ハッキング シーンのロゴと協力して、彼らは 'Pwnage 2.0'、しかし X509 解析スタック内の他のすべての bootrom コンピュータ ウイルス。 次に、iPod Nano 2 と iPod traditional の Rockbox への移植を可能にするのに十分な数のデバイスをリバース エンジニアリングしました。 Pwnage 2.0 コンピューター ウイルスは、iPod Nano 4G と同じくらい多くの設計図を作成し、Apple によってパッチを取得しました。 Notes アプリケーション内の他のすべてのコンピュータ ウイルスも、今度はファームウェアの段階で、iPod Nano 4G と同じくらい多くのコード実行を可能にしました。
そして今、私。 要約すると、次のエントリを取得しました:
- Nano 2G (Samsung S5L8701)、Nano 3G / iPod Traditional (Samsung S5L8702) でのコード実行、Nano 4G (Samsung S5L8720) は、Pwnage 2.0 コンピュータ ウイルスの結果です。
- 上記のデバイスからの BootROM ダンプ
- 上記のデバイスの復号化されたファームウェア が残したリバース エンジニアリングのメモ
Nano 5G からすべてが通常の完全密封に変更されました。 ファームウェアのダンプもコードの実行もありません。 本当にリバースエンジニアリングするものは何もありません。 適切な行動の方向性は、 Nano 4G 内の最近の脆弱性を導き出し、それを後のデバイスに移植すること [0] であると確信しています。 。
だからきっとNano 4G BootROM
BootROMのリバースエンジニアリング
簡単なフェーズは開始に変わりました。適切なバイナリ ダンプを使用し、アドレス 0x2000_0000 にロードし、最初のバイトで逆アセンブルを開始します。
何が起こっているのかを理解することは、非常に洗練されたミニチュアに変わりました。 BootROM は非常に貧弱で、通常は人間が読み取れる文字列をステアリングとして使用することはできません。 ありがたいことに、私は以前の世代のハッカーからリバース エンジニアリングされたレジスタ/メモリ ハウス ノートをいくつか持っていたので、初期のメモリ ポークは PLL とクロック ツリーの設定が大好きな問題であることが現時点で判明する可能性があります。 クロック ゲートを有効/無効にするコードに変更された多様な「アンカー」について、構築された AES ペリフェラルを使用したタイム デスク AES 復号化、通常、MMIO レジスタ ポークは、文書化の問題を開始するために事実上のアリーナに変更されました。
すぐに、BootROM の主要なパフォーマンスの多くを回復しました。 当然のことながら、BootROM バイナリが適切なものに変更されたため、以下のエンブレム/構造体の名前の合計は私の吸収です。これは、長い間確立されたすべてのシンボルが取り除かれたバイナリです。
void boot(void) { undefined4 スピノ; char *cnCA; DFUBoot dfuBoot; Squawk *instruct=g_State; g_State->vtable=&StateVTable; /CHIPINFO の不明なフェーズ、ビット . */ CHIPINFO chipinfo=read_volatile_4(CHIPID_INFO); uint chipinfo_unk=(uint)((int)chipinfo <> 0x1e; 命令->chipinfo_unk=chipinfo_unk; if (chipinfo_unk==1) { cnCA="/CN=Apple Stable Boot Certification Authority"; } else { /That is in prod certs. */ cnCA="/CN=Apple iPod Certification Authority"; } instruct ->cnS5L8720SecureBoot="/CN=S5L8720 Stable Boot"; instruct->cnCertificationAuthority=cnCA; gstatus_set(0,0); int disconnected=boot_otg_try_connect_dfu(); if (disconnected !=0) goto dfu; gpio_configure_input(3,5, 0); gpio_configure_input(3,6,0); gpio_configure_input(3,7,0); int gpio5=gpio_read(3,5); int gpio6=gpio_read(3,6); int gpio7=gpio_read(3,7) ; switch(gpio7 | gpio5 <<2 | gpio6 <<1) { ケース 0: ケース 2: スピノ=0; ブレーク; ケース 1: ケース 3: スピノ=1; ブレーク; ケース 4: ケース 5: ケース 6: boot_nand(); デフォルト: goto dfu; } boot_spi(スピノ); dfu: gpio_configure_unk(0xc ,3,1); gpio_set_bit(0xc,3,1); (*g_State->vtable->DFUBootDFUBoot)(&dfuBoot); /setup dfuBoot... */ (*g_State->vtable->DFUBootSetup)(&dfuBoot); (*g_State->vtable->DFUBootSetupUSB)(); (*g_State->vtable->DFUBootRun)();
戻る; }BootROM がどのように決定するかを精査するのもよいでしょう。 NAND、NOR(SPI)、または USB 経由で起動するための GPIO ストラップ (および、いくつかの PMIC またはクリックホイールからの確実な GPIO 通信)。
すべてのブート メソドロジ ハンドラの内部では、読み込まれた IMG1 の整合性を確認するための呼び出しがいくつかあります。 例として、boot_nand では:
undefined4 boot_nand(void) { clkgen_enable_gate(5); clkgen_enable_gate(9); nand_power_up_maybe(); nand_reset(0); nand_read_maybe(0,0,(int)&hdr); bool bVar1=(*g_State->vtable->verify_img_header)(&hdr,AES_KEY_TYPE_GLOBAL); if (((bVar1 !=不正) && (hdr.field2_0x7==ASYMMETRIC || hdr.field2_0x7==ASYMMETRIC_ENCRYPTED)) && (hdr.bodySize <0x24c01)) { uint私は=0; uint カウント=hdr.bodySize / 0x600; if (hdr.bodySize % 0x600 !=0) { カウント=カウント + 1; } if (count !=0) { make { nand_read_maybe(0,i + 1,(int)(&g_IMG_Payload + i 0x180)); 私=私 + 1; } 一方 (i <カウント); } int iVar2=(*g_State->vtable->verify_decrypt_image)(&hdr,&g_IMG_Payload,2);if (iVar2 !=0) { オフセット=g_State->img_header_jump_offset; gstatus_set(3,0); prepare_and_jump((int)&g_IMG_Payload + オフセット); } } 0 を返します。 }
NANDのネットページも調べてみるのもいいかも(?) 学び、ヘッダーが AES(SHA(header), fused_key)==header.signal を通過することを保証する verify_img_header の名前が続きます。 その後、IMG1 の本体の余分な NAND ページの束をロードし、ロードされたイメージ全体に対して、ダメージ内で verify_decrypt_image という名前を付けます。 フリップでは、今回は X509 を使用して、本体の署名チェックを実行します。 ロードされたペイロードには、その末尾に追加された驚くべき証明書チェーンが含まれていると予想されます。
上記の X509 コードパスがビルドです 「Pwnage 2.0」が生きています。 あるいは、非常に洗練された ASN.1/DER パーサーの非常に厄介な脆弱性ではありません。 リンクされた Wiki の記事をのぞき見して、余計な印刷物を見つけてください。 言うまでもなく、X509 の構文解析コード全体を調べて追加のバグを探しましたが、緩和を真に導き出すことはできませんでした。 ただし、証明書チェーンのロジックの約 1 つは非常に毛むくじゃらです。
BootROM 内には大量の余分なコードがあり、これはコードベースの種類がどのように愛を検索できるかの非常に適切なインスタンスに変更されました。常に何十時間も注いで使用する必要があります。 この静かさは理想的ではありませんが、本当にバグを探すには十分です。
コンピュータウィルス: USB wIndex==magic
がんばりましょう。 私が見つけ出したコンピュータウイルスは何ですか? USB スタック内の方向性の特に些細な脆弱性。 コードベースを大々的に回覧するようになったとき、それは本当に些細なことに変わったので、それを見逃していました。
シノプシス USB OTG 周辺機器へのコールバック、「ops」構造、および魔法のレジスタ ポークの樹木が生い茂ったアリーナの奥深くで、我々は発見します取得した SETUP パケットを解析する関数:
無効な USB::HandlePendingSetup(void) { usb_device_request *req; USBHandler *fptr; uint インデックス; バイト bmRequestType; USBState 命令; if (g_State->ep0state !=SETUP) { return; } req=(usb_device_request g_State->ep0_dma; 指示=g_State->usbState; /INIT または CONFIGURED */ if (instruct <3) { LAB_20004e18: EP0Stall(); PrepareRecvBuf(); 戻る; } [...]
重要な部分は、g_state->ep0_dma がエンドポイント 0 で取得した USB パケットを格納するように構成されたメモリ バッファ。つまり、これらは攻撃者によって瞬時に管理されます。 コードは、ここにある USB SETUP パケットを想定し、そこから bmRequestType アリーナを抽出し、その上でディスパッチします:
bmRequestType=req->bmRequestType; if ((bmRequestType & 0x60)==0) { /Variety==ポピュラー */ EP0OutSetupStandard(req); PrepareRecvBuf(); 戻る; } if ((bmRequestType & 0x60)==0x20) { /Variety==クラス */ [...] } else if ((bmRequestType & 0x60)==0x40) { /Variety==プロバイダー */ [...] }そうでなければ { LAB_20004e18 に移動します。 }
ちょっと変わったもの。 それがポピュラーであるかどうかを確認してクエリを送信し、そうであれば、名前で EP0OutSetupStandard にアドレス指定します。 それがクラスまたはプロバイダーである場合は、クエリをフォームに配置し、それにも対処します。 それ以外の場合は、失速して失敗します。 そのクラス ハンドラーを拡大してみましょう:
index=(uint) req->wIndex[0]; if (instruct usbHandlers[index].handlerClass; goto Joined_r0x20004d9c; } の場合((bmRequestType & 3)==1) { if (index==0) { fptr=(USBHandler g_State->usbHandlers[0].handlerClass; goto Joined_r0x20004d9c; } } [...]あそこは長い道のりだ. コンピュータウイルスはそこにある. あなたはそれを精査できますか?
Nano 4G と... Nano 5G で! これは最近のツールであり、これよりも早くコード実行が行われたケースはありません! ただし、最初に、Nano 4G でこれについて途方もないことを試してみましょう。そのための BootROM ダンプがあります。 正直なところ. If (bmRequestType & 0x3)==0、特定の人が管理する「インデックス」(SETUP パケットの wIndex アリーナの減少バイトから読み込まれる) は、境界テストなしの g_State->usbHandlers へのインデックスとして古風です。 次に、そのインデックスの結果が関数として実行されます (ここでは確認されていません) おっと、同様のバグのあるコードパスが Provider ハンドラー内に存在します。
実際、bmRequestType 領域を 0x20 にして、巧妙に細工された USB SETUP パケットを DFU モードで BootROM に送信すると、 (2次試験合格 s 上記) および wIndex 領域を 0xff00 にすると、BootROM が破壊されます
Nano 4Gの活用
このレベルでは、Squawk の構造とその usbHandlers メンバーについて、ミニチュア エクストラについて理解を深めたいと思います。
typedef struct { uint stuff[0x15] ; USBInterfaceHandlers usbHandlers[0x15]; // その後、多様化した問題... } Squawk; typedef struct { USBInterfaceDescriptor *interfaceDescriptor; void *onSetConfiguration; ボイド*アンク; void *onSynchFrame; void *handlerClass; ボイド *handlerVendor; } USBInterfaceHandlers;
効果的に、私たちがおそらく作ることができるのは、ジャンプ先のコード ポインタとして、Squawk の usbHandlers の後のフィールド。 ミニチュア ビット演算を行うと、これらは 0..255 の N のオフセット 0x64 + (0x1c n) および 0x68 + (0x1c n) です。
主なポイントは割愛しますが、たまたま次のように変更されました。 3 にクラスを送信してクエリを送信するには、コード ポインターとして Squawk 構造内のオフセット 184 で uint をアドレス指定して作成します。 Squawk のそのオフセットには、私が ep0_txbuf_offs と呼んでいるカウンターがあります。
BootROM DFU は、現在、計測器にプロットするイメージを簡単に受信することはできませんが、現在その中にあるものを送信することもできます。バッファ。 実際のところ、その実装は長い道のりですが、最初に N バイトの画像にクエリを送信し、次にホストの側面から学習を開始すると、ep0_txbuf_offs は N-0x40 を吸収します (つまり、残りのレコードデータの量から最初のパケットの次元を差し引いたもの)。
アリーナにはいくつかの寸法制限がありますが、機器からのファームウェア送信をスケジュールし、bmRequest=0x20 と wIndex を送信することにより、=3、0x000 から 0x600 までの任意のアドレスで作成する機器を取得できます。 ARM デバイスを認識している間に、これらの下位アドレスが CPU の割り込みベクトルを吸収する必要があることもわかるでしょう。 全体として、ほとんどのデバイスが最新の実行媒体 (この場合は BootROM) をこれらの下位アドレスに複製する可能性があり、それがここでも当てはまる理由です。
では、BootROM から 0x000 から 0x600 までのアドレスを作成することもできます。 成功すると、アドレス 0x3b0 の下に次のものが見つかりました:
200003b0 30 ff 2f e1 blx r0この素敵なミニチュアスキームは、効果的に進行するトランポリンですARM CPU の最初のレジスタである r0 にあるアドレスから実行します。 このレジスタは、関数に渡された最初の引数を保持するために、奇妙な ARM ABI 内では古風になります。 そして偶然にも、USB::HandlePendingSetup では、悪質な fptr が実際には引数 ep0_dma を持つものとして知られています。
やったー楽しい! 0x3b0+0x40 の学習をスケジュールし、wInd3x コンピュータ ウイルスを実行することで、ARM コードとして USB SETUP パケットの実行を開始します!
これは、エクスプロイト チェーンの私のお気に入りのフェーズを紹介する時が来たことを示唆しています: 多言語 ARM シェルコードと USB パケット:
0x20 0xfe 0xff 0xea 0x03 0x00 0x00 0x00USB SETUP パケットとして解析すると、bmRequsetType は 0x20、bRequest は 0xfe、wValue はこれは、上記の wInd3x コンピューター ウイルスをトリガーすることを示唆しています。
0x2202e300 (ビルド ep0_dma ライブ) から実行されている ARM コードとして解析すると、次のようになります:
$ rasm2 -a arm -b 32 -o 0x2202e300 -D "20feffea03000000" 0x2202e300 4 20feffea b 0x2202db88 0x2202e304 4 03000000 andeq r0, r0, r3
、0x2202db88 は DFU バッファーへの 136 バイトです。これは、かなり多くの「無制限」の次元であり、管理が非常に困難です。 安定したコード実行を負担します!
これにより、楽器に「シェル」コードの送信を開始できます。 私が書いた最も初期の問題では、「send-memory-region-over-USB」というアイデアの証明に変更されました。 今後の記事では、さらに合理的なペイロードに焦点を当てる予定ですが、ここでは、ここにいる理由に焦点を当てましょう:
Nano 5G の活用
We'今は極寒地帯にいます。 Nano 5G BootROM は破裂のために wInd3x に弱いことを実験的に確認しましたが、Nano 4G のように問題なくエクスプロイトを作成するための BootROM ダンプはまったくありません。 同じペイロードを試してもうまくいきません (予想どおり、BootROM の再コンパイルにより、オフセットがすべて多様化する可能性があります)。
まず、ep0_dma quiet を制御して 0x000..0x600 メモリに飛び込むエクスプロイトの第 1 段階を調査したいと思いました。苦労した。 私は、単純な「オラクル」を見て、バックアップ手順を実行する立場に変わりました。 それにもかかわらず、4 にリージョン化すると、無効な命令ハンドラである 0x004 にジャンプします。これは、Nano 4G BootROM が大きなループとして実装されていることがわかっています。 それは大変だったので、処刑のその段階を見守る手助けができるかもしれないと思いました。
ここで、私の目的は、最初の 0x600 バイト内のどこかで動作する 'blx r0' スキームを検索することに変わりました。 だから私はそれを強引に取り、メモを取りました:
# 374:スタック # 378: リターン # 37c: 再起動 <- クィア # 380: リターン # 384: スタック # 388: リターン # 38c: リターン # 390: スタック # 394: リターン # 398: リターン # 39c: スタック # 3a0: スタック # 3b0 : スタック # 3b4: スタック # 3b8-3fc: return
1 つのアドレスが飛び出しました確実な動作: 0x37c. 他のすべては、楽器をクラッシュさせた (そして infloop で立ち往生するように促した) か、終わりがなかった (mov ノートブック コンピューター lr で終わるコード ブロックにヒットする可能性が高い)。 これで、USB/ARM ポリグロット ペイロードを処理できるようになりました。 驚いたことに、それは 箱から出して苦労しました:DFUバッファに「loop:b loop」または「bl #0x0」命令を入力したかどうかを考慮して、多様な動作を獲得しました。
さて、たぶん exec
-pre>%% item_read_more_button%%
Fantastic! I was involved in the freemyipod project back when the 4G was still a current product. In fact, the freemyipod.org wiki ran from a server I kept downstairs in my parent's home. My favorite memory was when we all built robots to brute force a return address (https://freemyipod.org/wiki/Nanotron_3000). Glad to see the project is still alive!