web-dev-qa-db-ja.com

iPhone / Androidアプリを強化して、リバースエンジニアリングするのが難しい方法は?

これらは私が考えている次の目的です:

  1. バイナリはいくつかの秘密のトークンを保持するため、アプリをクラックしにくくします。
  2. それでもクラックされる可能性がある場合、アプリが誰かまたは自分自身にクラックされたことを通知し(チェックサムや証明書、またはアプリに対してそれを実行しているOSをチェックするなど)、何らかのアクションを実行できる方法はありますか?プログラムがメモリ内にあるときにも、アプリのバイナリが感染したり、不正なコードが挿入されたりする可能性があるため、提案されたメソッドはこれらの両方のケースに対処できるはずです。

私はこれらのプラットフォームを使用しています:

  • iPhone [OS:iOS、言語:Objective-C]
  • Android [OS:Android、言語:Java]

これは視聴者にとって重要なアプリであるため、コストと開発時間を考慮に入れないでください。両方のプラットフォームで質問に答えられるとすばらしいと思います。あなたの時間と注意をすでにありがとう。

編集1これらのProtectionClasses は文書化されていませんか? Apple docsの下にドキュメントが表示されません。これらが役立つかどうかは誰でも知っていますか?

編集2:Mac OS Xのコードサインには-o killバイナリに署名するためのオプション。バイナリが証明書のチェックサムと一致しない場合は常に、OSがそれを強制終了します。 詳細はこちら [Ctrl-F 'オプションフラグ']。 iOSにはこのようなものはありますか?

編集3:これらのアイデアを組み合わせて使用​​することを考えています。誰かがここに来た場合に備えて、これが役立つかもしれません。 一方向関数忘却転送

10
kumar

基本的に、目標「1」は機能しません。リバースエンジニアリングはうまく機能しません。 Androidバージョン、Javaは本当に簡単に逆コンパイルできるため、Androidでは特定のバイトコード形式が使用されるため、Java実装は Dalvik であり、「真の」Javaではありませんが、原則は残っています。)しかし、iPhoneバージョンでもそれほど難しくはありません(Objective-CはARMコード。分解して理解するのが最も難しいことではありません)。

目標「2」も機能しません。まず、リバースエンジニアリングとデータ抽出はパッシブのみであるため、アプリケーションは変更されません。したがって、そのようなリバースエンジニアリングが行われたことをアプリケーションが検出するためにできることは何もありません。また、一部のアプリケーションコードを変更して内部テストをバイパスすることも簡単です。これは、1980年代初頭以降、ゲームのコピー防止機能を回避するために採用されたクラッキングテクニックの1番です。

期待できる最善の方法は、ユーザーを2つのカテゴリに分割することです。つまり、電話をジェイルブレイクしたユーザーとジェイルブレイクしなかったユーザーです。ジェイルブレイクされていないiPhoneでは、Appleによって正式に承認されたアプリのみをインストールして実行できるため、これにより、「秘密トークン」を使用する変更された非公式アプリをしかし、ジェイルブレイクは、人々が未承認のアプリをインストールするために行うことであり、比較的簡単なようです。

また、シークレットトークンを頻繁に更新し、アプリの新しいバージョンを常に公開することで、攻撃者の生活を困難にすることもできます。これがゲームコンソールベンダーが行っていることであり、ユーザーは新しいゲームで遊んだり、新しい映画を視聴したり、ゲーマーネットワークに接続したりできるように、ユーザーがダウンロードしなければならない新しい「ファームウェアバージョン」を常に備えています。これもユーザーを困らせるので、それを行うのは必ずしも安くはありません。

「シークレットトークン」をユーザー固有にすることで、より簡単になります。このようにして、トークンの値が過度に抽出された場合でも、サーバーでそれをブラックリストに登録できます(アプリでどこかのサーバーに接続するためのトークン)。

デプロイされたアプリケーションでデータを秘密に保つこと、またはそれに失敗すると、前述のデータの不正使用を確実に検出することは、世界中のすべてのゲーム編集者および映画発行者の聖杯であることに注意してください。最後に聞いたところによると、ソニーやワーナーのような大きなプレーヤーはまだそれを見つけていません、そしてそれは試みの不足のためではありません。

8
Tom Leek

IPhone/Androidアプリを強化してリバースエンジニアリングするのが難しい方法は?

ソフトウェアのリバースエンジニアリングを防ぐことは難しい問題です。

弱いハードウェアアシスタンス(PC、iPhone、またはAndroid電話)を使用して、一般的なコンピューティングプラットフォームでアプリケーションソフトウェアのリバースエンジニアリングを長期間(数か月)防ぐことは、非常に難しい問題です。

一般に、アプリケーション全体を保護する代わりに、アプリケーションが使用する重要なデータの保護を試み、アプリケーション全体の保護をあきらめることが一般的な代替策です。

[1]バイナリが秘密のトークンを保持するため、アプリをクラックしにくくします。

ここでのあなたの「データ保護」の概念を公開しています。アプリケーションで本当に保護する必要があるのは、いくつかの重要なデータ、つまりシークレットトークンです。

アプリケーションがそれ自体を保護できない場合、どのようにデータを保護しますか?

責任はオペレーティングシステムに渡されます。オペレーティングシステムが提供できる保護には、アクセス制御と暗号化の2つのタイプがあります。データの読み取りまたは特定のアクションの実行を許可または拒否するときに使用する保護のほとんどは、アクセス制御です。

アクセス制御は、アクションとアクションを実行したいユーザーの識別子を入力として受け取ります。その出力は、アクションを実行する許可を承認または拒否します。アクセス制御は、セット、ルール、またはテーブルを使用して、識別子にアクションの実行を許可するかどうかを決定します。

たとえば、アリスはコンピュータ上にゲームFunGameを持っています。コンピューターのアクセス制御には、アリスのみがFunGameを実行できるというルールがあります。ボブはコンピューターの前に座り、FunGameを実行しようとします。コンピュータのアクセス制御は、入力として「run FunGame」と「Bob」を実行します。 「アリスのみがFunGameを実行できる」というルールに基づいて、アクセス制御の出力は拒否されます。

アクセス制御は、許可または拒否に関する決定を行うための直接的かつ一般的な方法を提供しますが、暗号化は、許可または拒否のより間接的な方法を提供します。暗号化と復号化により、データを変換して、意味のあるデータまたは意味のないデータにすることができます。

暗号化と復号化には、少なくとも1つの暗号化キーが必要です。キーの値は、「キーを持っている人は誰でも理解できるデータを取得して理解できないようにする」と「キーを持っている人は誰でも理解できないデータを取得して理解できるようにする」という2つのルールによるアクセス制御になります。データを理解不能にすることは、データが理解されることを防ぐだけです。個人はまだデータを読み取ることができるかもしれませんが、それは彼らが理解する形にはなりません。

アクターの識別子の代わりにキーが重要なコンポーネントになることに注意してください。キーを持っている人は、キーの入手方法に関係なく、誰でもデータにアクセスできます。これにより、キーの保存が問題になります。キーをデータと同じシステムに保存する場合、提供するデータにアクセスするための手段としてanyoneを指定します。これが、パスフレーズに暗記が必要な理由です。パスフレーズを記憶すると、キー(パスフレーズ)がシステムではなく頭に保存されます。

したがって、トークンを保護するには、オペレーティングシステムのアクセス制御を使用するか、トークンを暗号化するか、またはその両方を行うことができます。誰かが独自のアクセス制御を強制しないオペレーティングシステムを持っている場合(ジェイルブレイクされたiPhoneまたはrooted Android電話))、オペレーティングシステムのアクセス制御に依存することはできません。ただし、キートークンの暗号化に使用されるものは、暗号化されたトークンと同じシステムに存在しないため、オペレーティングシステムが侵害された場合でも、トークンは保護されます。

ただし、問題のシステムにキーを保持しないことは、キー管理と呼ばれるもう1つの難しい問題です。

[2]それでもクラックされる可能性がある場合、アプリが誰かまたは自分自身にクラックされたことを通知し(チェックサムや証明書、またはアプリに対してそれを実行しているOSに対してチェックするなど)、何らかのアクションを実行できる方法はありますか?

プログラムがメモリ内にあるときにも、アプリのバイナリが感染したり、不正なコードが挿入されたりする可能性があるため、提案されたメソッドはこれらの両方のケースに対処できるはずです

データを最後に検査してから変更されていないかどうかを検査する概念は、整合性チェックと呼ばれます。データのチャンクの状態を効率的に評価する方法は、暗号ハッシュと呼ばれます。整合性チェックを実行するには、最初にデータの暗号化ハッシュを計算してから、結果のハッシュ値を保護する必要があります。後で、同じデータの暗号化ハッシュを再計算します。再計算されたハッシュ値を保護されたハッシュ値と比較します。 2つの値が同一の場合、データは変更されません。 2つのハッシュ値が異なる場合、データは変更されています。

ストレージ内のアプリケーションバイナリをデータの一部として扱い、その整合性チェックを実行できます。また、メモリ内のアプリケーションバイナリをデータの一部として扱い、整合性チェックを実行することもできます。

実行中のプログラムを検査して、それが設計どおりに処理されているかどうかを確認する概念は、証明と呼ばれます。実行中のコードが使用するすべてのメモリをチェックすることは通常実行不可能であるため、認証は通常、特定のデータセットの値や実行中のプログラムの状態や状態間の遷移など、少し単純なものをチェックします。証明は達成が難しいため、商用ソフトウェアでは広く使用されていません。

5
this.josh

これらは、Obj-C、Java/Dalvik、IPA、JAR、およびAPKの非常にインテリジェントな自己変更(パッキングなど)およびセルフチェックコードメソッドですが、すべて同じくらい簡単に破壊されると信じていますASM、C、C++、PE、およびELFのいとこ。リバースエンジニアの機能は、2012年には非現実的です。

私の提案は、ルートキット以外のMMORPGが不正行為をキャッチする方法(例:PunkBusterなど)と同様に、すべての知的財産をサーバー側に保持し、すべてのアクションまたは非アクションを慎重に認証および承認することです。

モバイルアプリは非常にシンプルでなければならず、すべてのクライアント側アプリと同様に、ユーザーを決して信頼してはなりません。

4
atdre

リバースエンジニアリングを試み、真に防止することは、実りのない試みのように見えるかもしれませんが、ここでの概念は、攻撃者にとってより困難にすることだと思います。以下は、Androidでの逆コンパイルを防ぐために開発者が取ることができるいくつかの予防策です。

  1. コア機能のいくつかをネイティブコードで記述(Android NDK)
  2. 暗号化を使用する
  3. ロジックをサーバー側にシフト
  4. さまざまな形式の難読化(変数の分割、オブジェクトへのスカラーの昇格、変数の有効期間の変更、インスタンス変数の並べ替え、インスタンス変数の並べ替え、スクランブル識別子、配列の分割/折りたたみ/マージ、継承関係の変更)を使用します。これらは単なるデータ難読化の例です。コントロールの難読化をご覧ください。これらの方法は、ずさんなコードを促進し、メンテナンスに伴うオーバーヘッドを増加させることに気づくでしょう-あなたのアプリを逆転させる人々はあなたを憎むでしょう。

これらはほんの数例ですが、Java難読化手法に関するこのペーパーを読むことを強くお勧めします。この手法はどの言語にも適用できます。幸運を祈ります。

1 ‘‘A Taxonomy of Obfuscating Transformations,’’ Computer Science Technical Reports 148 (1997), https://researchspace.auckland.ac.nz/handle/2292/3491.
3
Claudio Lacayo