(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!


メモリ改ざんの抑止やPlayerPrefsの暗号化、端末時間の改ざんの検出にオンライン上の時間の取得など、様々なチート対策ができるAnti-Cheat Toolkit【Unity】【アセット】


このエントリーをはてなブックマークに追加


この記事でのバージョン
Unity 2018.3.4f1
Anti-Cheat Toolkit 1.6.7


はじめに

今回は様々なチート対策ができるAnti-Cheat Toolkitというアセットの紹介です!


メモリ改ざんの抑止やPlayerPrefsの暗号化など、よくあるチートに対する対策が簡単に実装でき、

しかも、最悪それらが突破されてたとしても、チートの検出も可能という万能チート対策アセットです。

Anti-Cheat Toolkit 2021 | Utilities Tools | Unity Asset Store



メモリ改ざんの抑止

チートでよくある方法にメモリに載っている値を変更する、メモリ改ざんという手口があります。



ざっくり説明すると、プログラム内の特定の値を検索し、変更(改ざん)するといった感じです。


f:id:kan_kikuchi:20190510065216j:plain
f:id:kan_kikuchi:20190510065224j:plain


Anti-Cheat Toolkitを使えばこのメモリ改ざん(値の検索)を難しくする事が出来ます。

やり方は簡単で、int→ObscuredIntのようにプログラム内の型を変えるだけです。

using CodeStage.AntiCheat.ObscuredTypes; //ObscuredIntなどを使うのに必要に
//普通のint
public int Lives = 5;

//メモリ改ざんを難しくするint
public ObscuredInt ObscuredLives = 5;


型は変わりますが、Inspectorで普通に設定できますし、


f:id:kan_kikuchi:20190511063916j:plain


プログラム内でも普通のintと同じように扱えます。

//数値を演算する事も可能
ObscuredLives += 10;

//intの型と演算する事も可能
int num = 2;
ObscuredLives *= num;

//Debug.Logの引数にする事も可能
Debug.Log(ObscuredLives);


もちろん、intだけでなくfloatやbool といった基本的なC#の型のObscured版や、

Vector2やQuaternionといったUnity固有の型のObscured版も実装されています。


ただし、LINQはまだサポートされておらず、

また、Vector3などのUnity固有の型の場合は、実装されてない処理もあります。

//Obscured版のVector3
ObscuredVector3 obscuredVector3 = new Vector3(1, 1, 1);

//normalizedは実装されていないのでこれはエラー
//ObscuredVector3 normalizedObscuredVector3 = obscuredVector3.normalized;

//一旦Vector3にキャストすればnormalizedを実行できる
ObscuredVector3 normalizedObscuredVector3 = ((Vector3)obscuredVector3).normalized;



メモリ改ざんの検出

先ほど、「メモリ改ざんを難しくする」と述べた通り、

絶対に出来なくするわけではありません。(そもそも不可能)


ただし、Anti-Cheat Toolkitはメモリの改ざんの検出が出来ます。

これもやり方は簡単、ObscuredCheatingDetector.StartDetectionに処理を登録するだけ。

using CodeStage.AntiCheat.Detectors; //ObscuredCheatingDetectorなどを使うのに必要
private void Start() {
  //メモリが改ざんされた時に実行されるメソッドを登録
  ObscuredCheatingDetector.StartDetection(OnFalsifiedMemory);
}

//メモリが改ざんされた時に実行される
private void OnFalsifiedMemory(){

  /*メモリが改ざんされた時の処理(強制的にタイトルに戻すとか)*/

}


なお、どの値が改ざんされたかは分からないようですし、

この改ざんの検出を掻い潜って改ざんする事が可能かはちょっと分かりません。


また、AwakeからStartDetectionは使えないので注意が必要です。


PlayerPrefsの暗号化

メジャーなチート方法の1つにセーブデータの改ざんがあります。

UnityではPlayerPrefsを使って簡単にデータが保存出来ますが、

PlayerPrefsはユーザが簡単に変更する事が可能なので改ざんの標的にされやすいです。


なのでAnti-Cheat ToolkitはPlayerPrefsの値を暗号化する事が出来ます。

もちろんこれも簡単で、PlayerPrefsの代わりにObscuredPrefsを使うだけ。

using CodeStage.AntiCheat.ObscuredTypes; //ObscuredPrefsなどを使うのに必要
//普通にPlayerPrefsに保存
PlayerPrefs.SetInt("IntKey", 100);

//暗号化してPlayerPrefsに保存
ObscuredPrefs.SetInt("ObscuredIntKey", 100);


ちなみにPlayerPrefsに保存された値を確認する機能も付いていたりします。


f:id:kan_kikuchi:20190511064355j:plain


暗号化されている値は緑で表示されますが、表示自体は元の数値で表示されるので確認が容易ですし、

ここで値を変更したり、新たに値を作成したり、検索したりもできます。


f:id:kan_kikuchi:20190511064336j:plain


PlayerPrefsの改ざんの検出

メモリの改ざん同様、暗号化していたとしもPlayerPrefsの改ざんを100%防ぐ事は不可能です。


という事はもちろん、Anti-Cheat ToolkitはPlayerPrefsの改ざんの検出も出来ます。

これもやり方は簡単、ObscuredPrefs.onAlterationDetectedに処理を登録するだけ。

using CodeStage.AntiCheat.ObscuredTypes; //ObscuredPrefsなどを使うのに必要
private void Start(){
  //PlayerPrefsが改ざんされた時に実行されるメソッドを登録
  ObscuredPrefs.onAlterationDetected = OnFalsifiedPrefs;
}
  
//PlayerPrefsが改ざんされた時に実行される
private void OnFalsifiedPrefs(){

  /*PlayerPrefsが改ざんされた時の処理(警告を出すとか)*/

}


ちなみに、これもどの値が改ざんされたかは分かりませんし、

この改ざんの検出を掻い潜って改ざんする事が可能かはちょっと分かりません。


端末時間の改ざんの検出

Unity(というかC#)ではSystem.DateTime.Nowで簡単に現在の時間を取得出来ます。

ただこの時間は端末の時間なので、簡単に変更する事ができ、

時間で回復するようなものをこれで管理していると、簡単にチートされてしまいます。


そしてその端末時間の改ざんの検出にはTimeCheatingDetectorを使います。

TimeCheatingDetectorはシーン上に配置し、

Detection Eventに端末時間の改ざん時に実行するメソッドを登録するだけで使えます。


f:id:kan_kikuchi:20190511080136j:plain


なお、TimeCheatingDetectorは自動でDontDestroyOnLoadされるので注意が必要です。


ちなみに、プログラムから端末時間の改ざんが既にされているかをチェックする事も可能です。

(この場合もシーン上にTimeCheatingDetectorは必要)

using CodeStage.AntiCheat.Detectors; //TimeCheatingDetectorなどを使うの必要
private void Start() {
  MakeForcedCheckAsync();
}

//非同期で端末時間が改ざんされているチェック
private async void MakeForcedCheckAsync(){
  var result = await TimeCheatingDetector.Instance.ForceCheckTask();

  switch (result) {
    case TimeCheatingDetector.CheckResult.Unknown: //改ざんされていないが、改ざん途中?
      break;
    case TimeCheatingDetector.CheckResult.CheckPassed: //改ざんされていない(正常)
      break;
    case TimeCheatingDetector.CheckResult.WrongTimeDetected: //改ざんされていないが、値がおかしい?
      break;
    case TimeCheatingDetector.CheckResult.CheatDetected: //改ざんされている
      break;
    case TimeCheatingDetector.CheckResult.Error: //チェック失敗(オフラインとか)
      break;
    default:
      break;
  }
    
}



オンライン上の時間を取得

端末時間の改ざんをチェック出来るという事は、

どこかオンライン上の時間を取得し、比較しているという事です。


なら最初からオンライン上の時間を取得し、それを使えば良い

という話になりますが、それもTimeCheatingDetectorで行えます。

(この場合はシーン上にTimeCheatingDetectorは必要ない)

using CodeStage.AntiCheat.Detectors; //TimeCheatingDetectorなどを使うのに必要
private void Start(){
  StartCoroutine(TimeCheatingDetector.GetOnlineTimeCoroutine("http://google.com", OnOnlineTime));
}
 
//非同期でオンライン上の時間をgoogle.comから取得
private void OnOnlineTime(TimeCheatingDetector.OnlineTimeResult result){

  //取得成功
  if (result.success){
    //現在のオンライン上の時間を秒数で表示
    Debug.Log(result.onlineSecondsUtc);
  }

}


なお、asyncとawaitを使えば、以下のようにもっと簡潔に書けます。

private async void Start(){

  //非同期でオンライン上の時間をgoogle.comから取得
  TimeCheatingDetector.OnlineTimeResult result = await TimeCheatingDetector.GetOnlineTimeTask("http://google.com");

  //取得成功
  if (result.success){
      //現在のオンライン上の時間を秒数で表示
      Debug.Log(result.onlineSecondsUtc);
  }

}



おわりに

今回紹介した機能の他にゲーム速度の変更や、壁すり抜けなどのチート対策機能があったり、

Behavior DesignerPlayMakerといった他のアセットとの連携も出来たりするようです。


なお、このアセットを使えば、チートへの色々な対策ができ、実際に被害も減りますが、

ストアページの説明にもあるように100%解決出来るわけではないことには、注意が必要です。

このツールキットを使っても 100%のチート対策を保証することは出来ません。
熟練かつ意欲的なチート仕掛人は如何なる保護さえも突破します!

Anti-Cheat Toolkit 2021 | Utilities Tools | Unity Asset Store