$30 off During Our Annual Pro Sale. View Details »

Unityでのチート対策を簡単かつ高品質に行う為の取り組み

trapezoid
February 03, 2023

 Unityでのチート対策を簡単かつ高品質に行う為の取り組み

モバイルゲームにおけるチート対策はユーザ体験の為にも重要な要求である一方で、チート対策の実装やゲームへの組み込みには相応の工数や深い知見が必要になり、非常に難しい領域になっています。
DeNAでは社内/社外の開発問わず横断チームからチート対策へのサポートを幅広く行っており、高品質なチート対策を高い透過性で組み込める仕組みを、横断部門から提供しています。
本セッションでは、チート対策の強度を高める手法ではなく、組み込みにあたっての透過性を高めるために行っている工夫にフォーカスを当てて解説していきます。

trapezoid

February 03, 2023
Tweet

More Decks by trapezoid

Other Decks in Programming

Transcript

  1. Unityでのチート対策を簡単かつ
    高品質に行う為の取り組み
    大竹悠人
    ゲーム事業本部開発事業部開発二部テクノロジー推進グループ
    株式会社ディー・エヌ・エー
    © DeNA Co.,Ltd.

    View Slide

  2. 自己紹介
    2
    ● 大竹 悠人(Haruto Otake)
    ○ ゲーム事業本部開発事業部開発二部テクノロジー推進グループ
    ○ Twitter: @Trapezoid
    ● 2013年よりDeNAにジョイン
    ○ Unityに関連した技術サポートと様々な内製ライブラリの実装・保守に従事
    ○ クライアントチート対策のサポート
    /実装も複数のタイトルで担当

    View Slide

  3. 3
    クライアントチート対策の性質と
    それに向けたDeNAの体制
    透過性のあるクライアントチート対策が必要な理由について

    View Slide

  4. モバイルゲームのチート対策の大分類
    4
    ● クライアントチート対策
    ○ クライアントアプリへの不正な操作を
    困難にし、検出する
    ○ 完璧に防ぐことは不可能
    ■ 対策の強度が高ければ、 攻撃者にとっての合理性 を低くすることは出来る
    ○ 突破されては対策してを繰り返す、一定のイタチごっこが必要
    ● サーバチート対策
    ○ サーバ側への入力を検証して不正な操作や状態遷移を阻止する
    ○ 入力として有効な範囲で行われたクライアントチート
    の検出は困難
    ゲームに適合するバランスで両立することが必要

    View Slide

  5. モバイルゲームのチート対策の大分類
    5
    ● クライアントチート対策
    ○ クライアントアプリへの不正な操作を
    困難にし、検出する
    ○ 完璧に防ぐことは不可能
    ■ 対策の強度が高ければ、 攻撃者にとっての合理性 を低くすることは出来る
    ○ 突破されては対策してを繰り返す、一定のイタチごっこが必要
    ● サーバチート対策
    ○ サーバ側への入力を検証して不正な操作や状態遷移を阻止する
    ○ 入力として有効な範囲で行われたクライアントチートの検出は困難
    今回はクライアントチート対策に関しての話

    View Slide

  6. 6
    モバイルゲームのクライアントチート対策のコストの性質
    ● 運用中は継続的にチート対策コストがかかり続ける
    ○ 攻撃にさらされ続けるので、対策範囲と強度の見直しを継続的に行う必要がある
    ○ 運用での機能追加がされた際にもチート対策を行う必要がある
    ● 重要である一方で、積極的に(多く)払いたいコストではない
    ○ チート対策は実行性能/実装工数の両面へのトレードオフを伴う
    ○ チート対策がUXに寄与するのは、チート行為を減らせるかという成果面のみ

    View Slide

  7. 7
    結果、クライアントチート対策は既存の実装に対して適用される
    ● 最初からクライアントチート対策された状態の実装を書くのは非常に困難
    ○ 特に試行錯誤を伴う段階で行うのは工数の無駄が非常に大きい
    ○ チート対策はパブリックに公開される段階で適用されていれば良い
    ● 運用中の機能への適用範囲/強度の拡大(チータとのいたちごっこ)
    ○ 当然、常に既存の実装に対して適用することになる

    View Slide

  8. 8
    既存実装に対して後からチート対策を適用するリスク
    ● クライアントチート対策でゲーム自体が変化することはあってはならない
    ○ チート対策の適用による実装変更の量が多ければ不具合混入の危険も大きい
    クライアントチート対策には
    既存実装の動作を極力変えない、高い透過性が求められる

    View Slide

  9. 9
    今回の主題
    透過性に着目した
    DeNAのクライアントチート対策

    View Slide

  10. 透過性の高いクライアントチート対策を行うための体制
    10
    ● 透過性の高いチート対策ライブラリ
    を横断部門から各タイトルに提供
    ○ 横断部門の専門性の高いメンバーが、専門性が必要な領域を担える
    ○ チート対策ライブラリのアップデートによる簡単な強度強化も可能に
    ● 各タイトルの担当者は、チート対策を必要なだけ導入する
    ○ 透過性が高いので好きな時に、限りなく少ない影響で安全に
    導入できる
    高品質なクライアントチート対策を
    できるだけ少コストで利用可能な環境を実現する

    View Slide

  11. 11
    主なクライアントチート対策
    動作中のアプリの
    メモリを改ざんする
    (読み込まれたマスタ/プレイヤー
    データやステータスを、有利な状態
    に強制的に変更する )
    行為を制限し、検出する。
    メモリ改ざんソフトや、チート対策
    の回避を行うソフトの
    動作環境となる環境
    (Root / 脱獄, エミュレータ等)で
    のアプリの動作を制限する
    ゲームロジックそのものや他の
    チート対策を解読して、チート対策
    の回避をしたり、ゲームの挙動を
    変化させる
    行為を制限し、検出する。

    View Slide

  12. 12
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  13. 13
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  14. 14
    GuardProperty
    透過性の高いメモリ保護ライブラリ

    View Slide

  15. 15
    GuardPropertyによるメモリヒープ上の値の改ざん保護
    ● 透過性の高いメモリ保護を可能にする、DeNAの内製ライブラリ
    ● 直接メモリを書き換える事によるメモリヒープ上の値のデータ改ざんを保護する
    ○ 改ざんを検知したら登録した関数を呼び出してゲームの終了等を行う
    ● フィールドに指定する型を置き換えるだけでメモリ保護ができるというコンセプト
    型を置換

    View Slide

  16. 16
    型の透過性を高めるための仕組み
    ● 暗黙的に元の型と相互変換を行う互換型として実装
    ○ 暗黙的変換により、代入や演算も行える
    ○ ほぼ元の記述のまま適用することが可能
    ● readonly structで実装
    ○ 防御的コピーの回避 & 元の型と同等に扱う為
    ○ 保護状態でコピーすることで改竄検知を遅延

    View Slide

  17. 17
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  18. 18
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  19. 19
    チート対策用C++コンパイラ
    DeClangのしくみ

    View Slide

  20. 20
    クライアントチート対策の手動実装を代替するコンパイラ
    ● 手動実装時のクライアントチート対策の流れはかなり固定的
    ○ ある関数を通った時に(When)
    ○ 様々なチート検知ロジックを実行し
    (What, To)
    ■ 改ざん検知 / 不正環境(Root/脱獄/エミュレータ…)の検知 など
    ○ チート検知時にアプリケーションの終了等の処理を行う関数を呼び出す
    (Then)
    ● チート対策用C++コンパイラ
    ○ clang等のC++コンパイラと差し替えて利用するチート対策ソリューション
    ○ コンパイル時に透過的にLLVM IRを改変し、ソース変更せずにチート対策を施す
    ○ コンパイル時に動くので、関数単位での改竄検知も可能
    ● When/What/To/Thenを設定として記述することで、チート対策の内容を指定する

    View Slide

  21. 21
    チート対策用C++コンパイラの選択肢
    ● Digital.ai App Protection (EnsureIT)
    ○ Digital.ai社開発の有償ソリューション
    ○ 保護の品質はとても高い(外部ベンダのソリューションの為、詳細は省略
    )
    ● DeClang
    ○ DeNA セキュリティ部により提供されている
    DeNA内製のプロダクト
    ○ OSSとして公開していて、無料で利用可能。
    Unity(IL2CPP)に対応
    ○ DeNA専用の拡張版が存在(OSS版にはないチート対策機能を多数搭載
    )

    View Slide

  22. 22
    DeClangの詳細については開発者による過去の講演を参照
    ● DeClang 誕生!Clang ベースのハッキング対策コンパイラ
    ● DeClang : Anti-hacking Compiler

    View Slide

  23. 23
    チート対策用C++コンパイラの使用例
    シーン管理処理と、
    ダメージ計算関数、
    そして改竄された際のログ関数を
    まず仮定する。
    シーン開始時にScene1Startが
    シーン終了時にScene1Endが
    それぞれ呼ばれるとする。

    View Slide

  24. 24
    チート対策用C++コンパイラの使用例
    シーン開始時と終了時にそれぞれ
    ダメージ計算関数の改竄を検出
    改竄されていたら
    改竄検知ログ送信関数を呼び出す。
    このような改竄検知処理を
    コンパイル時に既存コードに挿入できる

    View Slide

  25. 25
    多層的な改竄検知によるチート対策の強化
    ● 改竄検知処理自体を改竄検知する
    ○ 改竄検知処理自体の改竄によって突破
    されても、その改竄を検出できる
    ○ これを何重にも積み重ねる
    ○ すべてを改竄しないと突破できない
    ● クライアントチート対策全般を巻き込んで保護
    ですると非常に効果が大きい
    ○ 下層で不正環境検知を行ったり、メモリ
    保護のコードを改竄検知する

    View Slide

  26. 26
    チート対策用コンパイラ(のUnityでの)共通のメリット/デメリット
    ● メリット
    ○ コードを変更せずチート対策を差し込める事による、
    透過性の高さ
    ■ 開発用に検知を外すコードパスを用意する必要がなくなる (ビルドフローで対応可 )
    ■ パフォーマンス問題があったときに強度を弱めるなどの調整が容易
    ○ 手動実装では困難な多層的な改竄検知による、強力なチート対策性能
    ● デメリット
    ○ コードに強く依存する設定としてチート対策の構成を生成する必要がある
    ■ いつ/どの対象の/どんな事象を検知し違反時にどうするか
    ■ シンボル名ベースで指定する必要があり、
    IL2CPPの命名規則を知る必要も
    ○ 多層的な改竄検知を構築するにはチート対策への深い理解と多大な工数が必要
    ○ 設定の形式は実際のチート対策用コンパイラ毎に異なり、ロックインされる

    View Slide

  27. 27
    そのまま使うコストは高い
    ● 性能/透過性は高いが、扱うためのコストが高い
    ● 設定(と導入)のコストを大幅に下げるような仕組み
    が必要

    View Slide

  28. 28
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  29. 29
    CodeGuardConfigurator
    Unity向けのDeClang/EnsureITの共通フロントエンド

    View Slide

  30. 30
    CodeGuardConfigurator
    ● チート対策用C++コンパイラをUnityで簡単に利用する為のフロントエンド
    ○ C#コードの保護を、C#コードによるDSLとして記述できる
    ○ 保護の対象/起点/内容を独立して記述すると保護設定を
    自動的に構築する
    ○ 複数のチート対策用C++コンパイラに対して、同一の手法で設定を記述できる
    ● 最近のDeNAのゲームの多くで利用中

    View Slide

  31. 31
    多層的な検知構造の自動生成 自動的に階層的な改
    竄検知を生成
    各々を独立に記述

    View Slide

  32. 32
    多層的な検知構造の自動生成 Seedに応じて
    構成を変更
    Seed以外は同じ入力

    View Slide

  33. 33
    C#コード(対象/起点)の指定
    ● 単体指定と範囲指定で宣言的に区別
    ○ 保護の起点は単体指定
    ○ 保護の対象は範囲指定
    ● リファクタリングでも追跡される記述
    ○ Generics / nameof / typeof
    ○ コードと設定の乖離を防止
    ● 合成をサポート
    ○ 単体 + 単体 = 範囲
    ○ 範囲 + 範囲 = 範囲
    FunctionExpression.OfMethod(
    nameof(Chara.DealDamage)
    );
    対象はメソッド単体 対象のクラス
    対象のメソッド
    RangeExpression.OfClass();
    対象はクラス全体の 範囲 対象のクラス
    RangeExpression rangeExpression =
    functionExpression1 +
    functionExpression2;
    単体指定同士を
    範囲指定に合成

    View Slide

  34. 34
    保護内容の指定(の擬似コード)
    ● 保護内容の種類毎のプロパティに指定
    ○ 対象がある場合引数にコードを指定
    ○ 保護対象毎にオプションも指定
    ■ 強度や起点の選択条件など
    ● いくつかの設定は演算子で合成可能
    ○ 設定の責任範囲の分解が可能になる
    ○ ライブラリ側で難読化や改竄検知を行うべき
    範囲を定義できる
    ○ 内製サーバSDK等で実施
    new GuardNetworkBuilder(
    //利用ミドルウェアとプラットフォームを指定
    MiddlewareTypes.DeClang,
    MiddlewareTargetPlatforms.Android
    ) {
    Seed = seed,
    FirePointSets = new () {
    //保護起点をFunctionExpressionで指定
    scene1Start, scene2Start
    },
    CheckSumPoints = new (){
    //改竄保護対象を指定
    charaClass, enemyClass,
    scene1Start, scene2Start
    },
    Obfuscates = new (){
    //難読化対象を指定 (強度も指定できる )
    {charaClass, 2f}, enemyClass,
    scene1Start, scene2Start
    },
    //Root検知を実施
    DetectJailbreakAndRooted =
    DetectJailbreakAndRootedSource
    .OfDefaultPhase()
    /* 省略 */
    );

    View Slide

  35. 35
    Unityのメタデータ(global-metadata.dat)暗号化機能
    ● メタデータファイルが平文だと、容易にシンボル名などが解析されてしまう
    ○ IL2CPPで変換されるコードの動作にはメタデータファイルは必須
    ○ 暗号化が望ましいが、ナイーブな組み込みが必要になる
    ● CodeGuardConfigurator側で機能を提供
    ○ Unityのポストプロセス処理として暗号化プロセスを実装
    ○ 有効化するだけで、自動的に暗号化
    /復号化実装が組み込まれる

    View Slide

  36. 36
    CodeGuardConfiguratorを介したUnityプレイヤービルド

    View Slide

  37. 37
    従来の問題点の解決
    ● コードに強く依存する設定としてチート対策の構成を生成する必要がある
    ○ C#で使った記述を可能にし、実際のコードへの追従性を担保
    ● 多層的な改竄検知を構築するにはチート対策への理解と多大な工数が必要
    ○ 定義するべきことを絞り、本当に知るべきことだけを知るだけで設定可能
    ○ 実際の検知の構築を自動化して、多層的な改竄検知の品質を安定させる
    ● 設定の形式は実際のチート対策用コンパイラ毎に異なり、ロックインされる
    ○ 設定手法は共通なので、どちらを使ってもノウハウを共有することが可能
    ○ 導入後の切り替えや、どちらにするかの意思決定の遅延が可能

    View Slide

  38. 38
    DeNAのクライアントチート対策ソリューションの技術スタック

    View Slide

  39. 39
    真に透過性のある
    クライアントチート対策を提供することで
    簡単かつ高品質にチート対策を
    ゲームに取り入れられるようになった

    View Slide

  40. 40

    View Slide

  41. 41

    View Slide