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

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

ボタン連打

何が起こる?

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

やり方

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」で検索すると紹介動画やツール紹介サイトがいくつか出てきます。以下、サイトの一例を紹介します。

など

対策

  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. 乱数調整(ポケモン)

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

参考

次回予告

以上がよく行われる有名なアプリケーションハッキングになります。(まだ他にもあるかもしれませんが)
次回はネットワークハッキングについてご紹介します。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.