Upgrade to Pro — share decks privately, control downloads, hide ads and more …

チート対策コンパイラDeClangの自動テスト【DeNA TechCon 2021】/techcon2021-11

チート対策コンパイラDeClangの自動テスト【DeNA TechCon 2021】/techcon2021-11

DeNAではスマホゲームのチート対策として、チート対策コンパイラDeClangを内製で開発しています。ゲームのチートを防ぐには、DeClangが正常に動作しているか確認するテストが必要です。そのテスト自体も手動で行うとミスが発生しやすい上に手間もかかるため、テストを自動化し一定以上の品質を担保しなければなりません。
一方で自動でテストを行うには、Mac, Linux, Windows, Android, iOSと各OSに対応させた上で自動でチートを行いそれが検知されるか確認する、つまりアプリのコード改ざんなどを自動で行う複雑なシナリオを実行する必要があります。また、OSS版と内部拡張版でリポジトリが分かれている点も対応が必要ですし、DeClang自体のビルドを高速に処理する必要もあります。
この発表では、それらの問題にどのように対応し、クラウド上でDeClangの自動テストをいかに実現したかを解説します。

8a84268593355816432ceaf78777d585?s=128

DeNA_Tech

March 03, 2021
Tweet

Transcript

  1. 森 槙悟

  2. 所属 • システム本部 セキュリティ部 セキュリティ技術グループ 経歴 • DeNA新卒 8年目、セキュリティエンジニア 8年目

    • ICFPC 2020 世界10位(Rust) セキュリティ技術グループの業務内容 • 脆弱性診断 • セキュリティ相談対応 • NW診断 • ログ管理 • セキュリティツール作成、チート対策ライブラリ開発など
  3. 所属 • システム本部 セキュリティ部 セキュリティ技術グループ 経歴 • DeNA新卒 8年目、セキュリティエンジニア 8年目

    • ICFPC 2020 世界10位(Rust) セキュリティ技術グループの業務内容 • 脆弱性診断 • セキュリティ相談対応 • NW診断 • ログ管理 • セキュリティツール作成、 など
  4. • そもそもDeClangって何? • DeClangを使ってビルドする方法 • もっと知りたい方へ DeClangの動作確認 クラウドの各OS上で動作させる テスト内容の詳細 結果・まとめ

  5. • いわゆるコンパイラ ◦ LLVM・Obfuscator-LLVMを拡張して作成 • スマホゲームのチートを対策 ◦ コンパイル時に難読化・コード改ざん検知などを 埋め込む •

    Apache License 2.0 でOSSとして一部公開中
  6. Unityのビルドフロー

  7. DeClangを使ったフロー

  8. もっと詳しく知りたい人は過去の発表を参照 • DeNA TehCon 2020 ◦ https://www.slideshare.net/dena_tech/declang-clang-dena-techcon-2020 • CODE BLUE

    2020 ◦ https://speakerdeck.com/dena_tech/declang-anti-hacking-compiler • OSS部分のソースコード ◦ https://github.com/DeNA/DeClang
  9. DeClangとは? • 開発時の動作確認 • 動作確認の手順 • 自動テストの難所 クラウドの各OS上で動作させる テスト内容の詳細 結果・まとめ

  10. • 追加した機能が動くか? • サポートしている環境でビルドが通るか? • デグレしてないか? ◦ 例えば、コード改ざん検知にバグがあると、 導入の意味が無いしQAでの発見が困難

  11. Mac・Linux・Windowsで以下をやる 1. OSS版をcloneする 2. 内部拡張版(Plugin)をcloneする 3. DeClangをコンパイルする 4. ndk(Xcode Project)のコンパイラを差し替える

    5. Android(iOS)アプリをコンパイルする 6. アプリのコードを改ざんする 7. Android(iOS)をPCに繋ぎ、アプリをインストールする 8. アプリ起動後に改ざん検知が動くか確認する
  12. • 1環境でテストするだけでも数十分かかる • 手順を少しでも間違えると確認できない ◦ ビルドキャッシュが残っていたり • なるべく全部クラウドでやりたい

  13. リポジトリ更新時に で以下をやる 1. OSS版をcloneする 2. 内部拡張版(Plugin)をcloneする 3. DeClangをclangでコンパイルする 4. ndk(Xcode

    Project)のコンパイラを差し替える 5. Android(iOS)アプリをコンパイルする 6. アプリのコードを改ざんする 7. Android(iOS)をPCに繋ぎ、アプリをインストールする 8. アプリ起動後に改ざん検知が動くか確認する Mac・Linux・Windowsを クラウドで動かす必要がある
  14. Mac・Linux・Windowsで以下をやる 1. 2. 3. DeClangをコンパイルする 4. ndk(Xcode Project)のコンパイラを差し替える 5. Android(iOS)アプリをコンパイルする

    6. アプリのコードを改ざんする 7. Android(iOS)をPCに繋ぎ、アプリをインストールする 8. アプリ起動後に改ざん検知が動くか確認する 基本的に内部拡張版の方で開発している ので、内部拡張版の更新をトリガにして OSS版をcloneする必要がある
  15. リポジトリ更新時にMac・Linux・Windowsで以下をやる 1. OSS版をcloneする 2. 内部拡張版(Plugin)をcloneする 3. DeClangをコンパイルする 4. ndk(Xcode Project)のコンパイラを差し替える

    5. Android(iOS)アプリをコンパイルする 6. 7. Android(iOS)をPCに繋ぎ、アプリをインストールする 8. アプリ起動後に改ざん検知が動くか確認する Android・iOSアプリのコードを全自動 で改ざんする必要がある 複数のシナリオを動かす必要がある
  16. リポジトリ更新時にMac・Linux・Windowsで以下をやる 1. OSS版をcloneする 2. 内部拡張版(Plugin)をcloneする 3. DeClangをコンパイルする 4. ndk(Xcode Project)のコンパイラを差し替える

    5. Android(iOS)アプリをコンパイルする 6. アプリのコードを改ざんする 7. 8. Android・iOSをクラウドで動かしてアプリ のインストール・起動・ログの確認が必要
  17. DeClangとは? DeClangの動作確認 • 各OS(Mac, Linux, Windows, Android, iOS)への対応 • テストフローの概略

    テスト内容の詳細 結果・まとめ
  18. • Bitriseを使う • AWSのEC2(spot instance)のJenkinsを使う • HeadSpinを使う

  19. Bitriseはモバイルアプリケーション(iOS, Android)に特化 したCIプラットフォーム • Mac, Ubuntuが利用可能 • Xcodeのバージョン指定が簡単 • Provisioning

    Profileなどの設定が簡単 • プリセット済みのステップが多くCIのワークフローが 簡単に書ける ◦ bashのスクリプトも実行可能
  20. • GitHub Enterpriseへのアクセスを確保 • GitHub Statusの変更(Pendingにする) • Provisioning Profileを設定 •

    次ページで説明 • GitHub Statusの変更 • Slackへの通知
  21. • プリセットのステップだと 対応が難しいのでスクリプトで実行 • ビルドに1時間くらいかかる ccacheを使えば2回目は5分 • キャッシュはS3とsyncする • Bats

    + HeadSpinでやる
  22. • 環境構築したAMI(イメージ)を作成する • JenkinsのEC2 PluginでそのAMIのノードを作る • Windows版はMSYS2(UnixライクなCLI)を使う ◦ Mac・Linuxと処理(bashスクリプト)を共通化 させるため

    • 他はBitriseとだいたい同じ
  23. HeadSpinはAndroid・iOS実機用デバイスファーム • 専用端末が安定して動作する • WebUI・APIから実機を操作ができる ◦ デバイス情報・ログの取得 ◦ アプリのインストール ◦

    デバッグ接続など • アプリのテストにAppiumが使える
  24. Appiumとは • Seleinumのアプリ版みたいなもの • AppiumのサーバにHTTPでコマンドを送信すると アプリの操作ができる • DeClangでビルドしたアプリのテストだとアプリ起 動・ログ取得ができるので十分

  25. GitHub Enterprise * JenkinsのロゴはJenkins projectに帰属します https://jenkins.io/ * 正式名称は右記の通りです S3 :

    Amazon Simple Storage Service EC2 : Amazon Elastic Compute Cloud Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3 HeadSpin (Android, iOS) GitHub
  26. GitHub GitHub Enterprise Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3

    HeadSpin (Android, iOS) 1. リポジトリ更新時にBitrise, Jenkinsをトリガ
  27. GitHub GitHub Enterprise Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3

    HeadSpin (Android, iOS) 2. DeClang本体をclone
  28. GitHub GitHub Enterprise Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3

    HeadSpin (Android, iOS) 3. 内部拡張版をclone
  29. GitHub GitHub Enterprise Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3

    HeadSpin (Android, iOS) 4. ビルドキャッシュ(ccache)をS3と同期 & DeClangをビルド
  30. GitHub GitHub Enterprise Bitrise(Mac) EC2 + Jenkins (Linux, Windows) S3

    HeadSpin (Android, iOS) 5. DeClangを使ってアプリをビルド & HeadSpinのAppiumを使ってテスト
  31. DeClangとは? DeClangの動作確認 クラウドの各OS上で動作させる • コード改ざん検知機能とは? • コード改ざん検知機能の自動テスト • 複数のテストシナリオへの対応 結果・まとめ

  32. • 関数の先頭をジャンプ命令に書き換える • その対策としてDeClangは関数の機械語の列が コンパイル時から変わってないかを確認する ◦ コード改ざんを検知した場合は指定された 関数を呼び出す

  33. • テスト時に.soファイル・実行ファイルのコードを 自動的に書き換えれば機能の確認ができる • どうやって機械語を自動で改ざんするか?

  34. • テスト時に.soファイル・実行ファイルのコードを 自動的に書き換えれば機能の確認ができる • どうやって機械語を自動で改ざんするか?

  35. void func1() { int value = 0x2a791f3e; // = 712580926

    改ざん対象の値 printf("func1: %d\n", value); __android_log_print(ANDROID_LOG_DEBUG, "DeClang Test", "func1 %d", value); }
  36. libsample.so[0x8d8] <+0>: stp x29, x30, [sp, #-0x10]! libsample.so[0x8dc] <+4>: mov

    x29, sp libsample.so[0x8e0] <+8>: adrp x0, 1 libsample.so[0x8e4] <+12>: movz w3, #0x1f3e libsample.so[0x8e8] <+16>: add x0, x0, #0x980 ; =0x980 libsample.so[0x8ec] <+20>: movk w3, #0x2a79, lsl #16 ... 略 ...
  37. • コンパイル結果は基本的に同じになるので、 自動化の際は命令の確認はせずにいきなりsedする # movz w3, #0x1f3e -> movz w3,

    #0xffff xxd -p sample.so | tr -d '\n' | sed s/c3e78352/e3ff9f52/ | \ xxd -r -p > ${temp_file} cp ${temp_file} sample.so
  38. • アプリのリパッケージ自体は全てコマンドで可能 ◦ Androidはapktool, apksignerを使う ◦ iOSはcodesign, zipを使う

  39. • 改ざんしている場合は検知ログが出力される • 改ざんしてない場合は正常に動くべき • 指定した関数の難読化ができているか • Bats = Bash

    Automated Testing System • シナリオ自体はbashスクリプトとassertで構成
  40. @test "コード改ざん検知する" { make_modify_apk # コード改ざんしたアプリを作成(bashの関数) run ./headspin_appium.py \ #

    HeadSpinの実機で実行 --apk-path="${MODIFIED_APK_PATH}" \ # runを使うと後ろのassertで --app-package="${APP_PACKAGE_NAME}" # 戻り値・標準出力が使える assert_success # HeadSpinでの実行が成功した assert_line --partial "func1 is tampered" # 改ざん検知の出力がある refute_line --partial "func1 712580926" # 改ざん前の値は出力してない }
  41. DeClangとは? DeClangの動作確認 クラウドの各OS上で動作させる テスト内容の詳細

  42. • 動作確認のミスが無くなった • 各OSでDeClangが動作するのが保証出来る • 改ざん検知が正常動作しないバグ • OSのバージョンによってビルドできないバグ

  43. • Bitrise・EC2 + Jenkins・HeadSpinを利用して クラウドで実行 • コード改ざんを自動で再現するためにsedを利用 • Batsを使って複数のシナリオに対応

  44. None