LoginSignup
1461
1437

More than 3 years have passed since last update.

ゲームでよくされるチート手法とその対策 〜アプリケーションハッキング編〜

Last updated at Posted at 2018-03-19

ゲーム、特にソシャゲ、ネトゲにおいて様々なハッキング(チート)が実際に行われます。
大きく分類すると、アプリケーションハッキング(クライアントサイドでのハッキング)とネットーワークハッキング(サーバーへのハッキング)とその他のハッキングがあります。
多くはエンジニアがよくやらかすバグであったり、知識(経験)不足を狙ってくるものです。
今回は内容のボリュームの関係上、アプリケーションハッキングについてのみ、実際によく行われるチート行為やその方法、対策などについて中心に挙げていきたいと思います。

ボタン連打

何が起こる?

コスト(課金石など)を払うことなく無限にアイテムが増殖する。

やり方

8ac9161721c15418d17e5dfd95c67ff1.png
上記のような「ボタン」を連打する。

対策

  1. データベースの排他制御(トランザクション + ロック)を行う。
  2. 連打ができないように一度ボタンを押したら処理が完了するまで押せないようにする。

具体例・解説

1.について、具体的な対策例として、以下にMySQLで実行可能なSQLを記述します。

トランザクション

/* トランザクション */
BEGIN
/* INSERT文 または UPDATE文 または DELETE文 などの更新系SQLを記述 */
...
/* 更新したデータを反映してトランザクションを終了したい場合はCOMMIT トランザクションスタート前の状態に戻したい場合はROLLBACK*/
COMMIT
/* または */
ROLLBACK

悲観的ロック

/* トランザクション + 悲観的ロック */
BEGIN
SELECT ... FOR UPDATE
/* INSERT文 または UPDATE文 または DELETE文 などの更新系SQLを記述 */
...
COMMIT
/* または */
ROLLBACK

楽観的ロックなどそのほかのSQLについての詳細についてはこちらを参照
データベース入門

被害例(参考)

  1. 「探検ドリランド」でまた複製技が発覚 グリー、一部トレード機能を停止

上記の他にも最近のゲームにおいて、多数の発生ケースが多くあります。

デコンパイル(逆コンパイル)

デコンパイルとは?

逆コンパイルとも言います。
アプリの実行ファイルからソースコードの形式に戻すことを「デコンパイル」といいます。デコンパイルすることでサーバーにアクセスしているパスワード、秘密鍵の情報や暗号化されているものを解除するためのアルゴリズムなどがわかってしまいます。

やり方

プラットフォーム 説明
ブラウザ ブラウザのデベロッパーツールを開く。取得できたjavascriptはクライアントで実行されているソースコードになります
Android dex2jarjadやというツールを用いることでデコンパイルすることが可能です。詳しくはこちら。AndroidのAPKを逆コンパイルする
iOS 具体的なやり方などはこちらを参照。iOS Reverse Engineeringの操作手順

対策

  1. 重要な値はサーバーにのみ保持し、ネットワークを用いてデータを取得する。その上でデータの更新はサーバー上でのみ行うようにする。
  2. C/C++を使ったネイティブコードで処理を書く。

具体例・解説

1.の具体例として、ガチャを行う処理を実装する場合、サーバー側で抽選を行い、抽選の結果のみをクライアント(端末)に送るようにする。ガチャ抽選の実装内容をシーケンス図に表すと以下のようになる。
cdraw.png

2.の具体例としてAndroid NDK, iOS(Objective-C++), UnityIL2CPP などそれぞれ対応したプラットフォームでビルドするようにする。
2.の詳しい解説として、C/C++で記述されたコードをコンパイルすると機械語に変換されます。これを逆コンパイルしても、逆アセンブラまでにしかなりません。そのため、この状態ではソースコードの中身を解析するのは(人間では)非常に困難なため、ネイティブコードで書いた処理というのはデコンパイルへの対策となります。

参考

メモリ改ざん

何ができる?

アプリ実行時にメモリ値を可視化し、そのメモリ値を変更することができます。これにより、明らかにおかしい値にしてゲームバランスを崩壊させてしまったり、そのデータをそのまま端末内に保存させたりすることでゲームを破壊したり、メモリ値からサーバーとの認証鍵を解析、取得することでサーバーへのハッキングが可能となる、といったことができるようになります。
メモリ改ざん

やり方

Android、iOSでメモリを改ざんできるツール(ソフト)はいくつかあります。「iOS memory hack」「Android memory hack」で検索すると紹介動画やツール紹介サイトがいくつか出てきます。以下、サイトの一例を紹介します。

割と有名なツールとしてはFrida,
など

対策

  1. データの更新はサーバー上でのみ行い、端末(クライアント)では行わない。
  2. メモリに乗っている値のチェックサムMD5 ハッシュ値をみる。

具体例や解説

1.の例として、サーバー側でガチャの抽選を行い、抽選結果のみをサーバーから受け取るように実装する。
2.の解説として、チェックサムMD5 ハッシュ値というものは値がわずかに変更されれば値が変更されてしまうものです。変数の参照先が変わった場合も値が変化するため、チェックサムMD5 ハッシュ値を監視することでメモリ値が変更されれば検知することができます。
しかし、厳しく対応しようとすれば、対応箇所が膨大となり、対応コストが高くなります。また、対応することでパフォーマンスが犠牲になる可能性もあります。メモリ改ざんを行ったからといって、サーバー上のデータが書き換わるわけではないので、ケースバイケースで対応することをおすすめします。

Log検知

アプリを起動した時に出力されるアプリ専用のLogを検出することがLog検出です。
logcat

何ができる?

処理の中身を解析するヒントを与えてしまいます。これ自体で何かをハッキングするということはないのですが、ハッキングするための方針、ヒントを与えることになります。

やり方

ケース ツール 参考
ブラウザ デベロッパーツール Web開発でよく使う、特に使えるChromeデベロッパー・ツールの機能
Android Android Studio->Logcat Android Studio の logcat を快適にする
iOS Xcode他 iPhoneの実機ログを確認する方法

対策

  1. Logを全て消す
  2. Buildする時に環境を切り分けるようにし、それぞれの環境において出力するLogレベルを切り替えるようにする
  3. エラーなど、ログとして検知したいものは直接出力はせず、違う表現にして出力したり、一部だけ出力する。

具体例や解説

2.の具体例としてDebugビルドやReleaseビルドといったビルドの環境を分け、logレベルがDebugのものはReleaseビルドでは出力されない、といった設定、ルールを儲ける。(各プラットフォームの開発環境の中にはそのような、制御ができるような仕組みがあるはずです)
3.の解説として、検知したエラーや文言はサーバーに送ったり、サーバーでログとして記録するが、ユーザーが検知できる形としては表示せず、以下のような共通の文言として出力(表示)する。これにより詳しいことは開発側は検知し対応でき、またユーザーには何か問題が起きたことがそれとなく伝えることができるので、お互いの住み分けができる。
エラー文言の例.png

参考

脱獄(root化)

脱獄とは?

root権限を取得することを脱獄といいます。
root権限を取得することですべての操作が可能になります。
端末の中のデータを全て消すといった、本来なら操作ができないように制限されているようなこともできるようになります。
また、脱獄することでアプリ内に用意された、アクセスが制限されているような領域にもアクセスすることができてしまうため、この領域に保存されている秘密鍵やアカウント情報といった特有の情報も見ることができるようになります。
全ての情報を見ることができるので、情報次第ではハッキングできなかったものが可能になったり、といったハッキングへの足がかりとすることが可能になります。
また、Android(Linux)ではroot化、iOSでは脱獄と呼ぶのが一般的です。

やり方

プラットフォーム ツール例 参考
Android KingoRoot, dr.fone-Android root化 Android root化アプリ-Androidをroot化するアプリ6選
iOS Electra Electra(Github), 「iOS 11.0〜11.1.2」を脱獄する方法!全デバイス対応&Cydia対応『Electra』

なお、脱獄すると端末の保証対象外となったり、端末の挙動が不安定になったり、端末が起動しなくなるなど、大きなリスクがあります。脱獄する場合はこれらのリスクを十分理解し、端末を一台、破壊するつもりで行ってください。

対策

  1. アプリ内で脱獄したかどうかを検知可能なため、脱獄していたら処理を変えるように実装する。
  2. データを暗号化して保存する。

ill02-1.gif

具体例や解説

1.の実装方法を以下にあげます。

2.の解説としてAES暗号などの共通鍵暗号の処理を施して、人間がデータを見てもわからないように加工する。(データの暗号化に関しては改めて別の機会にまとめます)

参考

乱数調整

乱数調整とは?

乱数の特性を掴み、狙ったものを出せるようにすることです。
本来「乱数」とは、「全く規則性が無く予測がつかない数字の並び」と言う意味ですが、必ず書いた通りに動くというプログラムの宿命上そのようなものをプログラムだけで仮想することは出来ません。
そのため、不規則な数が出現するような数式であったり、何らかの方法で作成した乱数の羅列の一部を移植する事で「擬似乱数」を生成して用います。この乱数を生成する特性をつかみ、操作することで調整する(狙ったものを出す)ことが可能になります。
20170921194329.gif

乱数の生成方法

乱数生成によく使われるアルゴリズムとしては線形合同法メルセンヌツイスタがあります。乱数生成時、どのアルゴリズムが標準で使われるかどうかは開発言語ごとに異なります。
なお、乱数を生成する際、現在時刻を基にして、擬似乱数を生成することが多いので、特定のタイミング(時刻)を狙うとうまくいく、といった都市伝説みたいな論調はあながち間違っているわけではありません。

対策

乱数を生成するとき、「真の乱数」を用いる。

具体例や解説

「真の乱数」とは自然界の中で生じてしまう(物理的な)誤差やノイズのことをいいます。具体的には通信時間やセンサーの検出した生のデータ(誤り検出訂正していない値)などを乱数生成時に用いることです。
最も簡単な実装方法としては抽選処理は全てサーバーで行い、抽選結果のみ取得することで乱数を調整することが困難にすることができます。

被害例

  1. 乱数調整(ポケモン)

この他、クライアントで乱数を用いた抽選処理を行っているゲームでは乱数調整を行ったというケースに度々存在します。

参考

バックアップ改ざん

バックアップ改ざんとは?

主にiOS, Androidにて用いられる手法です。
まずiOS, Android端末のデータをPCにバックアップします。
バックアップしたデータを編集して端末に戻すことでアプリ内において意図しない挙動を再現させたり、機密にしたい情報を抜き取ることができます。
またこのバックアップ改ざんは脱獄(Root化)しなくても再現できる方法を紹介します。脱獄(Root化)した場合はアプリ内のデータにもアクセスすることできるので対策としては以下の限りではありません。

やり方

iOSの場合

iPhoneとPCを接続 → PCのiTunesよりBackupを行う

ipodbackup.png

バックアップが完了すると、Macの場合 ~/Library/Application\ Support/MobileSync/Backup/[端末ID]/ 以下にバックアップした内容が置かれています。
この中の各種ハッシュ値のファイル(ディレクトリ)がバックアップされているファイルの本体です(中身は暗号化されています。AES暗号で暗号化されているようです)
またバックアップをすると同時に Manifest.db というファイルも抽出されています。
このファイルはSQLiteで開いて操作することができます。Manifest.db にはアプリに該当するハッシュ値のファイルと暗号化している鍵の情報など記録されているので、解析して復号することでBackupの中身を抽出することができます。
あとはバックアップファイルを改ざんして同様に暗号化して、端末に戻せばアプリ内のデータを改ざんすることができます。

参考

Androidの場合

やり方は以下の方法があります。

  • adbコマンドでfull backupを行う
  • Android Studio → Device File Exporterからファイルをのぞき見る

adbコマンドでfull backupを行う

adbコマンドとは接続しているAndroidを操作するコマンドです。すでにadbコマンドを実行できる状態であるとします。
full backup のやり方は以下のコマンドを実行することで全てのアプリの full backupファイル を取得することができます。

adb backup -f backup.ab -apk -obb-shared -all -system

これで backup.ab というバックアップファイルが取得できます。
また以下のコマンドで行うことで特定のアプリにおけるバックアップを取得できます。

adb backup -f app.ab アプリのパッケージ名

なお full backup するよりもパッケージ名を入力して抽出した方が完全なデータの抽出がうまくいくようです。

バックアップファイルである abファイル の中身を参照するためには
AndroidBackupExtractor というツールを用いてtarファイル に変換することで中身を見ることができます。詳しい使い方などはこちらを参照してください。
android-backup-extractor

Android Studio → Device File Exporterからファイルをのぞき見る

PCとデバイスをつないでいる状態で Android Studio を起動します。 Android Studio の右側にある Device File Exporter を選択し、data/data/アプリのパッケージ名/ 以下のアプリケーションの保存領域を参照します。

AndroidData.png

参考

対策

  • 端末に保存するデータを暗号化する
  • バックアップ時にアプリ内のデータが含まれないような設定にする

端末に保存するデータを暗号化する

端末内のデータを保存するときは処理の中でデータを暗号化した状態で保存します。
暗号化はAES暗号RSA暗号などの暗号・複号アルゴリズムを用いてアプリケーション内の処理の中で行います。
例えば Unityを用いている場合は暗号化ライブラリを作成し、内容をこちらにて紹介しているので参照・活用してください。
Unity(C#) で「正しい」暗号化処理をするライブラリを作成しました

バックアップ時にアプリ内のデータが含まれないような設定にする

iOSの場合

iOSには現状、開発時にバックアップできないようにする機能はありません (調査した限りでは見つかりませんでした。もし方法をご存知でしたら教えていただきますと幸いです)

Androidの場合

以下のように AndroidManifest.xmlapplication の項目に android:allowBackup="false" の項目を追加します。

AndroidManifest.xml
<manifest>
    ...
    <application
        android:allowBackup="false">
    ...
    </application>
</manifest>

この設定がされているアプリではバックアップを行なってもアプリ内に保存された情報を見ることができません。

androidpackage.png

参考

まとめ

以上がよく行われる有名なアプリケーションハッキングになります。
まだ他にもあるかもしれませんがご希望ご指摘などいただけたらと思います。

関連記事

1461
1437
23

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1461
1437