ゲーム リバース エンジニアリング - Android でゲーム コンテンツの読み取りと書き込みを行う

1. 背景

Android プラグインの実装には、対応するゲーム コンテンツの読み取りと書き込みが必要です。コードやデータを含むゲーム コンテンツの読み取りと書き込み

さまざまな読み取りおよび書き込みオブジェクトの一般的な手順は、オブジェクトのアドレス (場所) を検索し、対応する権限を取得し、読み取りと書き込みを行うことです。実装については、以下でさらに詳しく説明します。

2. 実施方法

実装は、注入型と非注入型の 2 つのカテゴリに分類できます。

インジェクション: 対応するゲームプロセス空間にインジェクションする必要があり、ptrace と zygote を介してインジェクトするのが一般的な方法です。

非インジェクション: ゲーム プロセス空間にインジェクションする必要はなく、ゲーム コンテンツは Android システム メカニズムを通じて他の場所から読み書きされます。

読み書きする必要があるゲーム コンテンツの性質に応じて、さまざまなアプローチを使用できます。インジェクション型は、ゲーム中に計算される中間変数(ダメージなど)、動的にロードされる属性(ライフ値など)、ゲームステータス(成功フラグなど)、動的にコンパイルされたコードなどの動的データの読み書きに適しています。 (Unity、lua スクリプトなど)。非インジェクションは、静的コードやリソース情報などを変更する場合により適しています (アンチインジェクション保護のあるゲームの場合、動的データを取得するために非インジェクションを使用することもできます)。

(1) 非注入タイプ:

1. /data/data/$PackageName のプライベート フォルダー内のデータ変更 (lib ディレクトリ内の SO の変更など) (ゲームの実行中に実際に SO ライブラリをロードします)。ROOT権限を取得すると、内部の内容を変更することができます。たとえば、メイン ロジック モジュールを変更するには、16 進エディタ (UltraEdit およびその他のツール) を直接使用して変更し、保存します。

2. APKTOOL などのツールを直接使用して APK ファイルを復号し、ゲーム リソース情報を取得します。APK の共通ファイル ディレクトリは次のように紹介されます。

AndroidManifest.xml すべてのアプリケーションには、パッケージ名、権限、アクティビティ、その他の関連情報が含まれている必要があります。

META-INF アプリケーションの署名情報はこのディレクトリに保存されます。

Res このディレクトリにはリソース ファイル (画像文字列など) が保存されます。

Lib このディレクトリには SO ファイルが保存されます。

アセット このディレクトリには構成ファイルが保存されます (ただし、プロセスにはリソース ファイル情報が含まれます)。

Classes.dex Java バイトコード ファイル (Java ソース コードからコンパイル)。

resource.arsc コンパイルされたバイナリ リソース ファイル。

このようにして、多くのゲーム コンテンツを取得できることがわかります。たとえば、セキュリティが不十分な一部の Lua エンジン モバイル ゲームの場合、Lua スクリプトはプレーン テキスト (通常は lua またはスクリプト関連の文字で名前が付けられます) で Assets ディレクトリに保存されます。もう 1 つの例は、図 1 に示すように、Unity ゲームです。C# スクリプトのコンパイル済み DLL は、assets/bin/Data/Manated/Assembly-CSharp.dll に保存され、ゲーム スクリプト コードは、次のようなツールを使用して直接逆コンパイルできます。 as ILSpy (Unity の補助版またはクラック版には、このファイルの内容を直接変更する機能があります)。
ここに画像の説明を挿入
3. /proc ファイル システムを使用すると、各プロセスはこのフォルダー内に対応するファイルを持ちます (前述のプロセスは、もちろんプロセスの実行中にのみ使用できます)。図 2 に示すように、このファイルにはいくつかの重要なファイルが含まれます。いくつかの重要な文書を以下に紹介します。

/proc/$pid/cmdline プロセスの開始に使用されるコマンド。

/proc/$pid/cwd 現在のプロセスの作業ディレクトリへのリンク。

/proc/$pid/environ 使用可能なプロセス環境変数のリスト。

/proc/$pid/exe はプロセス内で実行されているプログラムへのリンクです。

/proc/$pid/fd/ プロセスによって開かれた各ファイルへのリンク。

/proc/$pid/mem メモリ内のプロセスの内容。

/proc/$pid/stat プロセスのステータス情報。

/proc/$pid/statm プロセスのメモリ使用量情報。

/proc/$pid/maps 仮想アドレス空間の使用状況情報を処理します。

これらのファイルを通じて、対応するゲーム情報を取得できます。このうち、mem ファイルはゲームのメモリイメージを取得できるため、ファイルを変更することでゲームプロセス空間の内容を変更する目的が実現できることを意味します。たとえば、Huluxia モディファイアは、この非インジェクション方式によって一般的なモディファイア関数を実装しています (図 3 に示す「デバッグハック」のサンプル コードでは、読み取りや書き込みなどの関数を直接使用して、処理内容の読み書きを行うことができます。一般的に)。 、マップ内のコンテンツを含むモジュールのベース アドレス情報を取得する必要があります。)
ここに画像の説明を挿入
ここに画像の説明を挿入
(2) インジェクション:

挿入された読み取りおよび書き込みには強力な目的があります。つまり、静的または動的デバッグを通じて、コンテンツ アドレスが特定の場所で取得できることが判明し、その後、動的実行中に対応するアドレス コンテンツの読み取りおよび書き込みを行う必要があります。ゲームの操作 (メモリの読み取りと書き込みを含む)、memset、memcpy、mmap、strcpy およびその他の関数など)。その具体的な実装は次のとおりです。

1. ゲーム プロセス空間に挿入した後、特定の場所でアセンブリ命令を直接変更して、特定のアドレスの読み取りおよび書き込みロジックを変更します。たとえば、ゲームのプラグインで一般的に使用される関数パラメータを変更する方法は、特定の関数を解析して特定した後、その関数の最初のアセンブリ命令セグメントでパラメータの使用ポイントを見つけ、その割り当てを変更することで実現できます。図4に示すように、あるゲームの関数パラメータR1はエネルギー値を表しており、赤枠内のアドレスの命令をFF25(MOVS R5, #0xFF)に書き換えることで関数パラメータを0xFFに動的に変更する目的を達成できます。 (一定エネルギーのフルプラグイン機能を実現するため)。

このメソッドは、ARM や Thumb などのアセンブリ命令の一般的な読み取りおよび書き込み命令を理解する必要があります。たとえば、書き込み操作、ARM アセンブリ命令 MOV R3、#0 のオペコードは 00 30 A0 E3 です。
ここに画像の説明を挿入
2. 上記の方法は実は最も基本的な単射的書き込み方法であり、アドレスの静的解析→ページ属性の書き換え(mprotect関数で属性の書き換え)→内容を直接変更するという最も単純なロジックとなっています。さらに、一部の読み取りおよび書き込み操作で大量のバイトを占有する必要があり、対応するアセンブリ命令を元のアドレスで構築できない場合は、HOOK テクノロジが必要です。MSHOOKFUNCTIONやGOTテーブル置換等を利用して関数のアドレス置換を実現する方法と、Inline Hookを利用して関数の中間処理ジャンプを実現する方法の2種類があります。この記事は HOOK トピックの記事ではないため、これらのメソッドの比較的簡単な紹介は次のとおりです。

A. MSHOOKFUNCTIONやGOTテーブル置換などは関数を呼び出すだけで実装できるので便利です。ただし制限が強く、関数の中間変数データは取得できず、パラメータと戻り値の読み書きに限られます。

B. Inline Hook メソッドは実装がより複雑ですが、関数の中間操作データを読み書きできるという明らかな利点があります。例えば、ゲームにはダメージや防御力を計算する膨大な攻撃計算機能がありますが、ダメージ値は一時的な変数にすぎず、このときダメージ値の格納場所(ダメージ値)を静的に解析する必要があります。 register はどの位置です) を指定し、Inline Hook を使用して、対応するデータの読み取りと書き込みを行うことができます。

おすすめ

転載: blog.csdn.net/douluo998/article/details/130113203