App終点駅でできること|mitmproxyとApple Configuratorで下架前の状態を永久保存
Appが下架されてもmitmproxyとApple Configuratorを活用し、永続的に下架前の状態を保持。開発者や利用者のニーズに応え、貴重なApp資産を守る具体的手法を解説。
本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。
記事一覧
App 製品が終点に達したとき、何ができるか追憶する方法は?
mitmproxy + Apple Configurator を使って、App を下架前の状態に永久に保つ方法
はじめに
呪術廻戦
勤務時間が長く、多くの製品に関わってきた中で、かつて参加した製品が終着点(ストアからの削除)を迎えることも増えてきました。ゼロから製品を開発することは、新しい命を育むようなもので、チーム全員で3〜4ヶ月かけて子供を産み出しました。後半は別の保育者(エンジニア)に引き継がれましたが、最近その製品がライフサイクルの終わりを迎えると聞くと、やはり少し寂しい気持ちになります。
人生も同じで、明日太陽が先に昇るのか、それとも予期せぬ出来事が先に起こるのかは誰にも分かりません。唯一できることは、今を大切にし、目の前のことをしっかり行うことです。
追憶
歩んだ道には必ず痕跡が残ります。私たちは製品が終着点に達する前に何かを残し、皆が思い出せるように、そして少なくとも存在した証を残したいと考えています。以下の方法はすべてAppがまだオンラインであることが前提であり、すでに下架されている場合は本当に思い出だけが残ることになります。
非技術的な方法 — 録画
iPhone内蔵の画面録画機能 を直接使う以外に、QuickTime Playerを使ってiPhoneをMacに接続し、パソコンで録画して動画をエクスポートすることもできます。
- MacでQuickTime Playerアプリを開く
- 左上のツールバーで「ファイル」->「新規ムービー録画」を選択
- 録画画面を閉じた後、🔴の隣の「v」をクリックし、画面とスピーカーで接続したスマートフォンを選択してください
- この時、録画画面にスマホの画面が表示されます
「🔴」をクリックして録画を開始し、録画したい操作をスマホで行います。
録画中は現在の動画サイズが表示されます。録画を終了するには、もう一度「🔴」を押してください。
QuickTime Player のツールバーで簡単に動画をトリミングでき、最後に「Command」+「s」を押して動画を指定した場所に保存すれば、録画の記念が完了します。
動画での記録は、将来の思い出を画像よりもつなげやすくなります。深く録画すればするほど詳細に記録でき、必要に応じて画面を画像として直接スクリーンショットすることもでき、とても便利です。
技術的な方法
App の技術的バックアップは二つの方向に分けられます;「骨」App 自体は骨組みであり、「肉」は API Response Data で構成され、App のコンテンツデータの核心です。
骨はAppがApp Storeから削除されると同時に消えます。
肉はAPIサーバーの停止とともに消えてしまいます。
ですので、バックアップは「骨」と「肉」の2つの技術的な方法に分けています。
宣言
本記事は技術研究の共有を目的としており、いかなる技術を用いた違法または権利侵害行為を推奨するものではありません。
[骨] .ipa アプリインストールファイルのバックアップ
Appがストアから削除された後も、ダウンロード済みのAppはユーザーが手動で削除しない限り、その端末に残り続けます。また、機種変更時にデータ移行を行うと、一緒に移行されます。
しかし、もし誤ってそのAppを削除したり、機種変更で移行しなかった場合、本当に永遠にさよならすることになります;その際に手動でAppStoreの .ipa ファイルをバックアップしていれば、再び命をつなぐことができます。
ずっと前にリバースエンジニアリングの記事で触れましたが、今回は単純に .ipa ファイルをバックアップするだけで、クラッキングは不要です。すべて Apple 公式のツールを使って行います。
1. Apple Configurator 2 をインストールする
まずは Mac App Store から「 Apple Configurator 2 」をダウンロードしてインストールしてください。
2. iPhoneをMacに接続し、「このコンピュータを信頼」をタップする
接続に成功すると、iPhoneのホーム画面が表示されます。
3. バックアップしたい .ipa ファイルのアプリがスマホにインストールされていることを確認する
Apple Configurator 2 で画面を固定して、キャッシュされた .ipa ファイルを取得する必要があるため、まずは対象の App がiPhoneにインストールされていることを確認してください。
4. Mac 上の Apple Configurator 2 に戻る
上に表示されている iPhone のホーム画面をダブルタップして情報ページに入ります。
「App」タブに切り替え → 右上の「+追加」 → 「App」
App Storeアカウントにログインすると、これまでに購入したAppの一覧を取得できます。
バックアップしたい対象のAppを検索し、選択して「追加」をクリックします。
この時、待機ウィンドウが表示され、「XXX」にAppを追加中、「XXX」をダウンロード中です。
5. .ipa ファイルの抽出
ダウンロードが完了すると、既にインストールされているアプリを置き換えるかどうかを確認するウィンドウが表示されます。
この時点では何も操作しないでください。この時点では何も操作しないでください。この時点では何も操作しないでください。
Finder を開きます:
左上のツールバーで「移動」->「フォルダへ移動」を選択してください。
以下のパスを貼り付けてください:
1
~/Library/Group Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/MobileApps
ダウンロードしてインストール準備中の対象アプリの .ipa ファイルを見つけることができます:
それをコピーするだけで App の .ipa ファイルのバックアップが完了します。
ファイルのコピーが完了したら、Apple Configurator 2 に戻り、「停止」をクリックして操作を終了します。
[骨] .ipa アプリインストールファイルの復元
同様に、復元したいAppのiPhoneをMacに接続し、Apple Configurator 2を開いて、App追加画面に入ります。
復元する場合は、左下の「私のMacから選択…」を選んでください。
バックアップする App の .ipa ファイルを選択し、「追加」を押します。
送信とインストールが完了するまで待ち、スマホに戻ってアプリを再度開けば、復活成功です!
[肉] 最後の API レスポンスデータのバックアップ
ここでは以前のApp End-to-End Testing Local Snapshot API Mock Server の記事(詳細な原理はそちらを参照)で使用した方法と当時作成したオープンソースプロジェクトを活用します:
以前に API リクエスト&レスポンスの録画を使って E2E テストを行った技術と同様に、これを利用してアプリの下架や停止前の最後の API リクエスト&レスポンスデータを記録することもできます。
1. mitmproxy のインストール
1
brew install mitmproxy
mitmproxy はオープンソースの中間者攻撃およびネットワークリクエストスニッフィングツールです。
もし Mitmproxy の中間者攻撃の仕組みに詳しくない場合は、以前の記事「APPはHTTPSで通信しているのに、データが盗まれた。」や Mitmproxy公式ドキュメント をご参照ください。
純粋なネットワークリクエストのスニッフィングに使う場合、mitmproxy のインターフェースに慣れていなければ、「Proxyman」を使うこともできます。使い方は以前の別の記事を参考にしてください。
2. mitmproxy の証明書設定を完了する
HTTPS暗号化通信に対しては、ルート証明書を差し替えて中間者攻撃を行う必要があるため、初回使用時にはまず端末側でルート証明書のダウンロードと有効化を完了させる必要があります。
もしご利用の App と API サーバーで SSL Pinning を実装している場合は、Pinning 証明書も mitmproxy に追加する必要があります。
まず、iPhoneとMacが同じネットワーク環境に接続されていることを確認してください。
WiFiがない場合、パソコンが有線ネットワークに接続されていても、MacのWiFi共有機能をオンにすることで、スマホをMacのネットワークに接続できます。
Terminalで mitmproxy または mitmweb(Web GUI版)を起動します。
1
mitmproxy
この画面が表示されている場合、mitmproxy サービスが起動しています。現在トラフィックがないため空です。この画面のまま Terminal を閉じないでください。
- Macのネットワーク設定でMacのIPアドレスを確認する
スマホのWiFi設定に戻り、「i」をタップして詳細設定に入り、一番下の「プロキシサーバーを設定」を見つけます:
サーバーにMacのIPアドレスを入力する
ポート番号に8080を入力する
保存する
携帯で Safari を開き、次を入力してください: http://mitm.it/
もし以下のような表示が出たら:
1
// これが見える場合、トラフィックはmitmproxyを通過していません。
これは、携帯電話のネットワークプロキシサーバーが正しく設定されていないか、Mac上で mitmproxy が起動していないことを意味します。
通常は以下のように表示されます:
この時点ではHTTPトラフィックのみスニッフィング可能で、HTTPSトラフィックはエラーになります。設定を続けます。
接続成功を示し、iOSセクションで「Get mimproxy-ca-cert.pem」をクリックします。
- 「許可」をクリックしてください
ダウンロードが完了したら、携帯の設定に入り、「ダウンロード済みのプロファイル」が表示されるので、そこをタップします。
- クリックして入り、右上の「インストール」を押し、携帯のパスワードを入力してインストールを完了します。
設定に戻り -> 「一般」->「情報」-> 一番下の「証明書信頼設定」-> 「mitmproxy」を有効にする。
- 「続行」を押して有効化。
これで中間者攻撃のすべての準備作業が完了しました。
現在、あなたのスマホのすべての通信がプロキシサーバーを経由してMacから送信されます。操作が終わったら必ずスマホのネットワーク設定に戻り、プロキシ設定をオフにしてください。 そうしないとスマホのWiFiが外部ネットワークに接続できなくなります。
Terminal の mitmproxy に戻り、スマホの App を操作すると、すべてのキャプチャされた API リクエストの記録が確認できます。
すべてのリクエストは詳細な Request & Response 内容を確認できます:
以上は mitmproxy の基本設定と実際の作業です。
3. APIの解析と構造の理解
次に、mitmproxy の mitmdump サービスと、私が以前開発した mitmproxy-rodo addons を組み合わせて、リクエストの録画と再生を行います。
私の実装原理 はリクエストのパラメータをハッシュ値に変換し、再生時に再度リクエストをハッシュ化して、ローカルに同じハッシュ値のバックアップレスポンスがあれば返します。同じハッシュ値のリクエストが複数ある場合は順番に保存&再生されます。
私たちはまず上記の方法で App の API をスニッフィング(または Proxyman を使用)し、どのフィールドが Hash Mapping に影響を与えるかを確認できます。それらを記録し、後で除外設定を行います。例えば、ある API は固定で ?ts パラメータを含みますが、これは返却内容に影響しません。しかし Hash 値の計算に影響し、ローカルのバックアップが見つからなくなるため、後の設定でこれを除外する必要があります。
4. mitmproxy-rodo の設定:
私が作成した録画・再生用のオープンソーススクリプトを使用する。
詳細なパラメータ設定は該当オープンソースプロジェクトの説明を参照してください。
1
2
git clone [email protected]:ZhgChgLi/mitmproxy-rodo.git
cd mitmproxy-rodo
上のステップ3で選んだパラメータを config.json 設定ファイルに入力します:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"ignored": {
"*": {
"*": {
"*": {
"iterable": false,
"enables": [
"query",
"formData"
],
"rules": {
"query": {
"parameters": [
"ts",
"connect_id",
"device_id",
"device_name",
]
},
"formData": {
"parameters": [
"aidck",
"device_id",
"ver_name",
]
}
}
}
}
}
}
}
以上のパラメータはハッシュ値の計算時に除外され、特定のエンドポイントパスに対して個別の除外ルールを設定することも可能です。
5. 録画を有効にし、ターミナルで以下を実行:
1
mitmdump -s rodo.py --set dumper_folder=zhgchgli --set config_file=config.json --set record=true "~d zhgchg.li"
結尾の
"~d zhgchg.li"は、*.zhgchg.li のトラフィックのみをキャプチャすることを意味します。dumper_folder: 出力先ディレクトリ名
6. スマートフォンで対象のアプリを操作し、録画したい操作フローを実行する
再起動や再インストールを行い、最もクリーンな状態で操作を開始することを推奨します。
録画と組み合わせることをお勧めします。手順の再現が覚えやすくなります。
操作しながら、出力ディレクトリに多くの取得した API レスポンスデータが表示されます。これらは Domain -> API パス -> HTTP メソッド -> ハッシュ値 -> Header-X / Content-X の順に保存されます(同じハッシュのリクエストが2回あった場合は、順番に保存されます)。
再録画は出力ディレクトリを直接削除して、再度キャプチャさせることができます。
返却されるデータに個人情報が含まれている場合は、取得内容を匿名化するように調整してください。
[肉] 取得した API レスポンスデータの再生
録画が完了したら、必ず一度再生してデータが正常かどうかをテストしてください。Hash Hit が非常に低い場合(再生時に対応するレスポンスがほとんど見つからない場合)、嗅探ステップを繰り返して、毎回実行時に Hash 値に影響を与える不確定な変数を特定し、それを除外してください。
再生の実行:
1
mitmdump -s rodo.py --set dumper_folder=zhgchgli --set config_file=config.json
dumper_folder: 出力先ディレクトリ名デフォルトではローカルにハッシュマッピングされていないレスポンスデータに対して直接404を返し、Appは空白になります。これにより、取得したデータが有効かどうかを確認できます。
録画時に通過したパスページは、再生時に再表示されます:OK!
録画時に通っていないパスのページは、再生時にネットワークエラーが表示されます:OK!
回想
これで、骨と最後の肉を復元することで、当時のAppが終着駅に向かう最後の時間を再現し、皆で力を合わせて作り上げた時間を懐かしむことができます。
この文章は、最初の仕事のチームと、ウェブバックエンド開発から独学でiOSアプリ開発に転職し、3〜4ヶ月という短期間でAndroid、デザイナー、PMマネージャー、バックエンドの同僚と共に一から独立して製品を無事に完成させたことを記念しています。製品はまもなくライフサイクルの終点を迎えますが、当時の苦楽や初めてリリースされて誰かが使ってくれた感動は永遠に忘れません。
「ありがとうございます」
ご協力のお願い
もし同じような後悔があるなら、本記事があなたの助けになれば幸いです。なぜなら mitmproxy-rodo は当初、POC(概念実証)として開発されたツールだからです。ぜひ貢献やバグ報告、PRによる修正を歓迎します。
ご質問やご意見がございましたら、こちらからご連絡ください 。
Post MediumからZMediumToMarkdownにより変換。
本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。


































