セキュリティやIT技術に関する情報を発信していくアカウントです。【お知らせ】2021年5月10日~リニューアルオープン!今後はこちらで新しい記事を公開します。エンジニアの方向けにセキュリティやIT技術に関する情報を発信するブログです。(編集:株式会社ラック・デジタルペンテスト部)当ウェブサイトをご利用の際には、こちらの「サイトのご利用条件」をご確認ください。魚脳デジタルペンテストサービス部の魚脳です。今回はiOS内部ストレージの中、たまにどっかに隠れているbplistファイルの構造やそれを引っ張り出す方法のまとめとなります。利用されるオブジェクトシリアライゼーションのためのファイル形式であります。iOSの開発経験がある方なら、きっと馴染みがあると思います。bplistというはその文字通りバイナリ化(b)したplistを指します。xml形式のplistと比較してそのまま読めず、〇〇.plistのようなファイル(Info.plistなど)になったり、他のファイルに「隠れる」など少し厄介な存在です。bplistをターゲットに理由としては主に2つあります1つ目はbplistはplistの延長線上にあり、重要情報が保存される可能性が十二分あるため、フォレンジックやアプリ診断中に突然遭遇する事もケースによってあります。2つ目は現状複数種類のファイルに含まれることを確認したため、それを一貫にして抽出できるツールがあったら良いと思いました。上記理由は建前で、本音を言うと何回か遭遇した結果、興味が湧いたのでまとめることにしました。一貫してbplistを抽出するために、「ここからここまではbplist」というのをきっちり把握する必要があると考え、とりあえずはbplistのフォーマット1を調べました。<string>tokyo</string></dict></plist>上記のplistをplistutilを使って変換したbplist大まかな構造(セグメント)は以下のようになります。numberはbplist00固定objects(オレンジ色)実際のデータ部。6Eに対して、先頭の5Bはマーカーであり、11(0xB)文字のASCII文字列(0x5)を指します。マーカーに次ぐ11byteはそれぞれDescriptionのASCII値となります。文字列以外に数字やブール型など型が存在しますが、このセグメントは特にbplistファイルの特定に貢献しないため、今回は割愛します。table(黄色)このセグメントにはobject各々のオフセットが保存されます。6Eのオフセットは0Fになります。オフセットのバイト数はデータ量に応じて変わります(1byteは0xFFのオフセットまでしか表せないため)。「5B」から始まるオブジェクトのオフセットは0Fになりますこのセグメントも特にbplistファイルの特定に貢献しないため、割愛します。trailer(赤色)このセグメントは以下の情報を含めます、長さは32byte固定paddingbyte1-5パディングsort_versionbyte6ソート関連offset_table_offset_sizebyte7オフセットのバイト数を決めます。object_ref_sizebyte8objectが辞書型などデータが更に複雑になる場合必要なオフセットのバイト数、今回特に出番がないため、詳細を割愛します。num_objectsbyte9-16objectの個数。table内最初になるのはどれかを決めます、通常は0になります。tableのオフセット。使えそうな情報は全部trailerに詰まっているという印象でした。上記の構造からheaderとtrailer以外のセグメントの長さは可変であるため、まずそれを解決しないといけません。trailerに含まれる情報がそれを教えてくれました。offset_table_startは間接的にheader+objectsで長さを示します。offset_tableの長さはoffset_table_offset_size*num_objectで得られます。32例のbplistのtrailerをパースしてみるとoffset_table_startは0x91offset_table_offset_sizeは0x1num_objectは0x12公式によって長さは0x91+0x1*0x12+0x20=0xC3になり、実際の数値と一致します。長さはtrailerから計算できるため、末尾の位置からbplistの長さ分を引けば、ファイル先頭の位置に戻れるはずです。numberと一致すればOKです。parser(fdata,idx)テストと問題点テストとして、よくbplistを含むCache.dbを対象にbplistファイルを抽出してみます。|CFURLStringType\|今回紹介した方法を利用して558個のbplistファイルをCache.dbから抽出できましたが、その数はCache.db内に存在するbplistのマジックナンバーの個数に下回ります。理由としてはおそらくデータの欠損だと思います。この抽出方法はbplistのtrailer(セグメント)に依存するため、もしtrailerに欠損があるとうまく抽出できません。今回は「平文の状態で保存されたbplist」をターゲットにした抽出方法を紹介しましたが、暗号化やエンコードなどかかった場合は先にそれらを解決する必要があります。まとめ今回はbplistの構造を勉強して、最終的にそれを抽出する方法を考えました。実用シーンが限られますが、なにかの参考になれたら幸いです。読者になる関連記事2024-09-17Windowsカーネルから見るオブジェクトハンドルデジタルペンテスト部の北原です。2024の参加レポート・writeup(Web&Misc編)こんにちは、デジタルペンテスト部(DP部)のst98です。初めまして、DP部の今井です。fixups入門どうも、でぃーぴーぶの魚脳です。writeupシステム環境変数のPathに設定するフォルダの権限にご注意を。読者になるこのブログについてはてなブログをはじめよう!lac_devblogさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。