Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

[CEDEC2017] LINEゲームのセキュリティ診断手法

7,348 views

Published on

LINEゲームのセキュリティ診断手法
愛甲健二(LINE株式会社 セキュリティ室)

CEDEC2017の講演資料です
http://cedec.cesa.or.jp/2017/session/ENG/s5911733aab37a/

Published in: Technology
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

[CEDEC2017] LINEゲームのセキュリティ診断手法

  1. 1. LINEゲームのセキュリティ診断手法 LINE株式会社 セキュリティ室 Kenji Aiko 1
  2. 2. 自己紹介 愛甲健二(LINE株式会社) セキュリティエンジニア:リリース前のWebサービス、 GameのSecurity Riskを調査/判断する仕事 セキュリティエンジニアからみたUnityのこと(LINE Eng ブログ) https://engineering.linecorp.com/ja/blog/detail/110 2
  3. 3. 自己紹介 愛甲健二(LINE株式会社) セキュリティエンジニア:リリース前のWebサービス、 GameのSecurity Riskを調査/判断する仕事 3 攻撃者の視点で自社サービスを分析すること 攻撃者の視点(手法)を知ることで、 よりSecureなサービスの提供を行える
  4. 4. • 一般的なチート手法 • Gameの分析 • 対策法 • まとめ 4
  5. 5. • 一般的なチート手法 • Gameの分析 • 対策法 • まとめ 5
  6. 6. Memory Cheat 10 STOP • Gameを一時的に停止させ、メモリ内で”特定の値”を検索 • SCOREと同じ値を絞り込みにより特定 -> 改変 /proc/<PID>/mem 一般的なチートツールの代表的な機能 Android: vm_read_overwriteiOS: Memory https://github.com/Lazenca/Lazenca-A-Andoird https://github.com/Lazenca/Lazenca-A-iOS 6
  7. 7. Demo 7
  8. 8. Speed Hack • Game内時間を加速させてスタミナの回復を早める • Game速度を遅くしてプレイを簡単にする、など Game Hacker, Game Guardianといったツールに実装されている 経過時間をClientのみで管理しないことが大事 Server側でも時間をチェックする 8
  9. 9. Demo 9
  10. 10. Local File の改ざん • Local File内にGame情報を保存(ex: PlayerPerfs of Unity) • 暗号化されていないため、容易に変更可能 playerprefs.xml 仮に暗号化していたとしても、 Gameファイルを解析すれば復号処理を見つけられる 可能な限りServer側に保持するべき 10
  11. 11. Demo 11
  12. 12. Man-in-the-Middle Client Server 証明書 すべての通信を取得/改変できる Proxy Serverの証明書Proxyの証明書 Serverの公開鍵Proxyの公開鍵 Client Server Serverの証明書 Serverの公開鍵 Clientに任意の証明書をインストールできるため、 SSLの有無に関係なく、通信は自由に取得/改変できる12
  13. 13. SSL Pinning Client Server 証明書 Proxy Serverの証明書Proxyの証明書 Serverの公開鍵Proxyの公開鍵 証明書のチェック public static bool ValidateServerCertificate ( object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { string chash = certificate.GetCertHashString (); if (chash == "(hardcoded hash)") return true; // SSL certificate check ok return false; } Serverの証明書かどうかを チェックする For Unity 13
  14. 14. • 一般的なチート手法 • Gameの分析 • 対策法 • まとめ 14
  15. 15. • 静的解析 • 動的解析 Gameの分析 15
  16. 16. • 静的解析 • 動的解析 Gameの分析 16
  17. 17. 静的解析 • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) プログラムを動作させずに、機械語(あるいは中間言語)の分析 を行うこと(≒コードリーディング) 17
  18. 18. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 18
  19. 19. GameCode of Unity (Mono) • ILSpy – http://ilspy.net/ • JustDecompile – http://www.telerik.com/products/decompiler.aspx • dnSpy(推奨) – https://github.com/0xd4d/dnSpy • monodis – http://www.mono- project.com/docs/tools+libraries/tools/monodis/ 上記ツールを使うことで、 可読性の高いコードに変換(Decompile)できる19
  20. 20. GameCode of Unity (Mono) assetsbinDataManagedAssembly-CSharp.dll Assembly-Csharp.dll内にすべてのGameCodeが入っている • .apkを展開し、Assembly-Csharp.dllをデコンパイルする • PlayerHealth -> TakeDamageメソッドを表示 20
  21. 21. GameCode of Unity (Mono) assetsbinDataManagedAssembly-CSharp.dll ほぼソースコードに戻っている 21
  22. 22. GameCode of Unity (Mono) assetsbinDataManagedAssembly-CSharp.dll • ILの編集も可能(Reflexil: http://reflexil.net/) • dnSpyならメソッドをC#のまま編集できる 対策してない場合、ほぼC#の状態でファイルの編集ができる 22
  23. 23. Demo 23
  24. 24. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 24
  25. 25. GameCode of Unity (IL2CPP) 機械語(ARM/x86)の解析には、 IDAという商用のツールを使う(無料版はx86のみ対応) https://www.hex-rays.com/ https://blogs.unity3d.com/jp/2015/05/06/an-introduction-to-ilcpp-internals/ • ILからCPPのコードに変換され、機械語(ARM/x86)になる • Gameファイル内の.so(ARM/x86)を解析する必要がある 25
  26. 26. GameCode of Unity (IL2CPP) assetsbinDataManagedAssembly-CSharp.dll もともとのソースコード 26
  27. 27. .text:004855FC PlayerHealth$$TakeDamage .text:004855FC STMFD SP!, {R4,R10,R11,LR} .text:00485600 ADD R11, SP, #8 .text:00485604 MOV R4, R0 .text:00485608 MOV R0, #1 .text:0048560C STRB R0, [R4,#0x45] .text:00485610 LDR R0, [R4,#0x10] .text:00485614 SUB R1, R0, R1 .text:00485618 STR R1, [R4,#0x10] .text:0048561C LDR R0, [R4,#0x14] .text:00485620 CMP R0, #0 .text:00485624 BEQ loc_485680 .text:00485628 VMOV S0, R1 .text:0048562C LDR R2, [R0] .text:00485630 VCVT.F32.S32 S0, S0 .text:00485634 LDR R3, [R2,#0x22C] .text:00485638 LDR R2, [R2,#0x230] .text:0048563C VMOV R1, S0 .text:00485640 BLX R3 .text:00485644 LDR R0, [R4,#0x38] .text:00485648 CMP R0, #0 .text:0048564C BEQ loc_485680 .text:00485650 MOV R1, #0 .text:00485654 BL AudioSource$$Play_0 .text:00485658 LDR R0, [R4,#0x10] .text:0048565C CMP R0, #0 .text:00485660 LDMGTFD SP!, {R4,R10,R11,PC} .text:00485664 LDRB R0, [R4,#0x44] .text:00485668 CMP R0, #0 .text:0048566C BEQ loc_485674 .text:00485670 LDMFD SP!, {R4,R10,R11,PC} .text:00485674 loc_485674 .text:00485674 MOV R0, R4 .text:00485678 LDMFD SP!, {R4,R10,R11,LR} .text:0048567C B PlayerHealth$$Death .text:00485680 loc_485680 .text:00485680 BL loc_52DF78 .text:00485684 MOV LR, PC .text:00485688 B loc_48D21C .text:0048568C EnemyHealth$$_ctor .text:0048568C MOV R1, #0x64 .text:00485690 MOV R2, #0xA .text:00485694 STR R1, [R0,#0xC] .text:00485698 MOV R1, #0x40200000 .text:004856A0 STR R1, [R0,#0x14] .text:004856A4 MOV R1, #0 .text:004856A8 STR R2, [R0,#0x18] .text:004856AC B MonoBehaviour$$_ctor .text:004856AC ; End of function PlayerHealth$$TakeDamage IDA 27
  28. 28. Demo 28
  29. 29. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 29
  30. 30. GameCode of Cocos2d-x Touch Count up bool HelloWorld::onTouchBegan(Touch* touch, Event* event) { g_counter += 1; label->setString(StringUtils::format("%d", g_counter)); if (200000000 <= g_counter) { label1->setString("Thank you for counting up!"); } return true; } HelloWorldScene.cpp 30
  31. 31. .text:0012BAF8 ; _DWORD __fastcall HelloWorld::onTouchBegan( HelloWorld *__hidden this, cocos2d::Touch *, cocos2d::Event *) .text:0012BAF8 .text:0012BAF8 var_30= -0x30 .text:0012BAF8 var_2C= -0x2C .text:0012BAF8 var_24= -0x24 .text:0012BAF8 var_20= -0x20 .text:0012BAF8 var_1C= -0x1C .text:0012BAF8 .text:0012BAF8 MOVS R1, #0xB0 .text:0012BAFA PUSH {R4-R7,LR} .text:0012BAFC LDR R6, =(__stack_chk_guard_ptr - 0x12BB06) .text:0012BAFE LDR R4, =(g_counter_ptr - 0x12BB0A) .text:0012BB00 SUB SP, SP, #0x1C .text:0012BB02 ADD R6, PC ; __stack_chk_guard_ptr .text:0012BB04 LDR R6, [R6] ; __stack_chk_guard .text:0012BB06 ADD R4, PC ; g_counter_ptr .text:0012BB08 LDR R4, [R4] ; g_counter .text:0012BB0A LDR R3, [R6] .text:0012BB0C LSLS R1, R1, #2 .text:0012BB0E ADD R5, SP, #0x30+var_20 .text:0012BB10 STR R3, [SP,#0x30+var_1C] .text:0012BB12 LDR R3, [R4] .text:0012BB14 MOVS R0, R5; this .text:0012BB16 ADDS R2, R3, #1 .text:0012BB18 LDR R3, =(label_ptr - 0x12BB20) .text:0012BB1A STR R2, [R4] .text:0012BB1C ADD R3, PC ; label_ptr .text:0012BB1E LDR R3, [R3] ; label .text:0012BB20 LDR R7, [R3] 31
  32. 32. .text:0012BB22 LDR R3, [R7] .text:0012BB24 LDR R3, [R3,R1] .text:0012BB26 LDR R1, =(aD - 0x12BB2E) .text:0012BB28 STR R3, [SP,#0x30+var_30] .text:0012BB2A ADD R1, PC; "%d" .text:0012BB2C BL j_j__ZN7cocos2d11StringUtils6formatEPKcz ; j_cocos2d::StringUtils::format(char const*,...) .text:0012BB30 MOVS R3, #0x2C0 .text:0012BB34 STR R3, [SP,#0x30+var_2C] .text:0012BB36 MOVS R0, R7 .text:0012BB38 MOVS R1, R5 .text:0012BB3A LDR R3, [SP,#0x30+var_30] .text:0012BB3C BLX R3 .text:0012BB3E MOVS R0, R5 .text:0012BB40 BL sub_4BB420 .text:0012BB44 LDR R2, [R4] .text:0012BB46 LDR R3, =0xBEBC1FF .text:0012BB48 CMP R2, R3 .text:0012BB4A BLE loc_12BB72 .text:0012BB4C LDR R3, =(label1_ptr - 0x12BB56) .text:0012BB4E LDR R2, [SP,#0x30+var_2C] .text:0012BB50 LDR R1, =(aThankYouForCou - 0x12BB5A) .text:0012BB52 ADD R3, PC ; label1_ptr .text:0012BB54 LDR R3, [R3] ; label1 .text:0012BB56 ADD R1, PC; "Thank you for counting up!" .text:0012BB58 MOVS R0, R5 .text:0012BB5A LDR R4, [R3] .text:0012BB5C LDR R3, [R4] .text:0012BB5E LDR R7, [R3,R2] .text:0012BB60 ADD R2, SP, #0x30+var_24 32
  33. 33. .text:0012BB62 BL sub_4BD944 .text:0012BB66 MOVS R0, R4 .text:0012BB68 MOVS R1, R5 .text:0012BB6A BLX R7 .text:0012BB6C MOVS R0, R5 .text:0012BB6E BL sub_4BB420 .text:0012BB72 loc_12BB72 ; CODE XREF: HelloWorld::onTouchBegan( cocos2d::Touch *,cocos2d::Event *)+52 .text:0012BB72 LDR R2, [SP,#0x30+var_1C] .text:0012BB74 LDR R3, [R6] .text:0012BB76 MOVS R0, #1 .text:0012BB78 CMP R2, R3 .text:0012BB7A BEQ loc_12BB8C .text:0012BB7C BL j_j___stack_chk_fail .text:0012BB80 B loc_12BB82 .text:0012BB82 loc_12BB82; CODE XREF: HelloWorld::onTouchBegan( cocos2d::Touch *,cocos2d::Event *)+88 .text:0012BB82 MOVS R0, R5 .text:0012BB84 BL sub_4BB420 .text:0012BB88 BL __cxa_end_cleanup .text:0012BB8C .text:0012BB8C loc_12BB8C; CODE XREF: HelloWorld::onTouchBegan( cocos2d::Touch *,cocos2d::Event *)+82 .text:0012BB8C ADD SP, SP, #0x1C .text:0012BB8E POP {R4-R7,PC} libMyGame.so33
  34. 34. .text:0012BB46 LDR R3, =0xBEBC1FF .text:0012BB48 CMP R2, R3 .text:0012BB4A BLE loc_12BB72 .text:0012BB4C LDR R3, =(label1_ptr - 0x12BB56) .text:0012BB4E LDR R2, [SP,#0x30+var_2C] .text:0012BB50 LDR R1, =(aThankYouForCou - 0x12BB5A) .text:0012BB52 ADD R3, PC ; label1_ptr .text:0012BB54 LDR R3, [R3] ; label1 .text:0012BB56 ADD R1, PC; "Thank you for counting up!" .text:0012BB58 MOVS R0, R5 .text:0012BB5A LDR R4, [R3] .text:0012BB5C LDR R3, [R4] .text:0012BB5E LDR R7, [R3,R2] .text:0012BB60 ADD R2, SP, #0x30+var_24 .text:0012BB62 BL sub_4BD944 .text:0012BB66 MOVS R0, R4 .text:0012BB68 MOVS R1, R5 .text:0012BB6A BLX R7 .text:0012BB6C MOVS R0, R5 .text:0012BB6E BL sub_4BB420 libMyGame.so if (200000000 <= g_counter) { label1->setString("Thank you for counting up!"); } HelloWorldScene.cpp34
  35. 35. signed int __fastcall HelloWorld::onTouchBegan(HelloWorld *this, cocos2d::Touch *a2, cocos2d::Event *a3) { ++g_counter; v3 = label; v4 = *(void (__fastcall **)(int, char *))(*(_DWORD *)label + 704); j_cocos2d::StringUtils::format((cocos2d::StringUtils *)&v9, "%d"); v4(v3, &v9); sub_4BB420(&v9); if ( g_counter > 199999999 ) { v5 = label1; v6 = *(void (__fastcall **)(int, char *))(*(_DWORD *)label1 + 704); sub_4BD944(&v9, "Thank you for counting up!", &v8); v6(v5, &v9); sub_4BB420(&v9); } result = 1; if ( v10 != _stack_chk_guard ) j_j___stack_chk_fail(1); return result; } libMyGame.so 35 IDAデコンパイラを使った例
  36. 36. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 36
  37. 37. GameCode of UE4 Unreal Engine4 はCPPとBlueprintでGameCodeを書ける • CPP – libUE4.soにGameEngineと共にGameCodeも入る – アセンブラのためIDAで解析できる • Blueprint – main.obb.png(*.pak)にGameCodeが入る – 独自の中間言語(?)が入っている 37
  38. 38. GameCode of UE4(CPP) libarmeabi-v7alibUE4.so 38
  39. 39. GameCode of UE4(CPP) libarmeabi-v7alibUE4.so libUE4.soにはGameEngineといっしょにGameCodeも入っている (サイズが大きいためIDAの読み込みに時間がかかる)39
  40. 40. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 40
  41. 41. GameCode of UE4(Blueprint) Blueprintは、UE4のVisual Scripting System 視覚的なブロックを組み合わせてプログラミングが行える https://www.unrealengine.com/marketplace/blueprint-quick-time-events?lang=ja Blueprintで書かれたコードは、 apk内の assetsmain.obb.png に保存されている (PCビルドだと*.pakがすでにある)41
  42. 42. 1. main.obb.png を zip展開 2. [GameName]ContentPaks*.pakを取得 3. u4pak.pyで*.pakを展開 – https://github.com/panzi/u4pak 4. *.uasset, *.uexpにGameCodeが存在する 完全に対応したデコンパイラが見当たらないため、 IL, Javaバイトコードのようにはいかない Main.obb.png folder ZIP展開 *.pak u4pak.py展開 folder *.uasset *.uexp GameCode of UE4(Blueprint) 42
  43. 43. • Unity (Mono) • Unity (IL2CPP) • Cocos2d-x • Unreal Engine (CPP) • Unreal Engine (Blueprint) • dex (Java) 43
  44. 44. dex (Java) 44 Java Decompiler: http://jd.benow.ca/ $ apktool d –r –o $1 $1.apk $ java –jar smali.jar –o $1/classes.dex $1/smali/ $ sh dex2jar-2.1/d2j-dex2jar.sh $1/classes.dex *.jar GameCodeそのものがJavaで書かれていることは少ない ただし、Androidアプリの基礎言語なので知っておいた方がよい
  45. 45. • 静的解析 • 動的解析 Gameの分析 45
  46. 46. 動的解析 Program Debugger コードの解析(Debug) プログラムを動作させながら、機械語(あるいは中間言語)の分析 を行うこと(≒デバッグ) 46
  47. 47. 動的解析 端末 PC game gdb $ gdbserver tcp:9090 –attach [pid] $ gdb (gdb) target remote 1.1.1.1:9090 0xb7704923 in ?? () (gdb) コードの解析(Debug) Gameをプレイ(デバッグ)しながら、 各ステップ命令ごとの動作を確認する プログラムを動作させながら、機械語(あるいは中間言語)の分析 を行うこと(≒デバッグ) 47
  48. 48. 動的解析 端末 PC game gdb $ gdbserver tcp:9090 –attach [pid] $ gdb (gdb) target remote 1.1.1.1:9090 0xb7704923 in ?? () (gdb) Burp PC GameServer 通信の解析 コードの解析(Debug) 実際には通信もキャプチャし、 “どのタイミングで通信が発生したか”なども調べる プログラムを動作させながら、機械語(あるいは中間言語)の分析 を行うこと(≒デバッグ) 48
  49. 49. 動的解析 端末 game Burp PC GameServer 通信の解析 プログラムを動作させながら、機械語(あるいは中間言語)の分析 を行うこと(≒デバッグ) 49 Burp https://portswigger.net/burp BurpはWebアプリケーションの診断ツール 一般的にはブラウザとサーバの中間に入って通信内容をキャプチャ/ 変更するツールだが、Gameの分析にも使用できる
  50. 50. 動的解析 .text:004855FC PlayerHealth$$TakeDamage .text:004855FC STMFD SP!, {R4,R10,R11,LR} .text:00485600 ADD R11, SP, #8 .text:00485604 MOV R4, R0 .text:00485608 MOV R0, #1 .text:0048560C STRB R0, [R4,#0x45] .text:00485610 LDR R0, [R4,#0x10] .text:00485614 SUB R1, R0, R1 .text:00485618 STR R1, [R4,#0x10] .text:0048561C LDR R0, [R4,#0x14] .text:00485620 CMP R0, #0 .text:00485624 BEQ loc_485680 .text:00485628 VMOV S0, R1 .text:0048562C LDR R2, [R0] .text:00485630 VCVT.F32.S32 S0, S0 .text:00485634 LDR R3, [R2,#0x22C] .text:00485638 LDR R2, [R2,#0x230] .text:0048563C VMOV R1, S0 .text:00485640 BLX R3 .text:00485644 LDR R0, [R4,#0x38] .text:00485648 CMP R0, #0 .text:0048564C BEQ loc_485680 .text:00485650 MOV R1, #0 .text:00485654 BL AudioSource$$Play_0 .text:00485658 LDR R0, [R4,#0x10] .text:0048565C CMP R0, #0 .text:00485660 LDMGTFD SP!, {R4,R10,R11,PC} .text:00485664 LDRB R0, [R4,#0x44] .text:00485668 CMP R0, #0 .text:0048566C BEQ loc_485674 .text:00485670 LDMFD SP!, {R4,R10,R11,PC} .text:00485674 loc_485674 .text:00485674 MOV R0, R4 .text:00485678 LDMFD SP!, {R4,R10,R11,LR} .text:0048567C B PlayerHealth$$Death .text:00485680 loc_485680 .text:00485680 BL loc_52DF78 .text:00485684 MOV LR, PC .text:00485688 B loc_48D21C .text:0048568C EnemyHealth$$_ctor .text:0048568C MOV R1, #0x64 .text:00485690 MOV R2, #0xA .text:00485694 STR R1, [R0,#0xC] .text:00485698 MOV R1, #0x40200000 .text:004856A0 STR R1, [R0,#0x14] .text:004856A4 MOV R1, #0 .text:004856A8 STR R2, [R0,#0x18] .text:004856AC B MonoBehaviour$$_ctor .text:004856AC ; End of function PlayerHealth$$TakeDamage break 実行時の状態を解析できる • レジスタの状態 • メモリの状態 • スタックトレース 通信データの復号処理直後のメモリを 確認すれば、平文が得られる CMP R0, #0 CMP R0, #1 動的に命令を変えて処理を観察 動的に変わる状態を 分析できる 50
  51. 51. Demo 51
  52. 52. 動的解析 任意のメソッドのcall logを出したり、動作そのものを変えられる (いわゆるAPI Hookと同じ仕組み) Xposed: http://repo.xposed.info/module/de.robv.android.xposed.installer FRIDA: https://www.frida.re/docs/android/ Cydia Substrate: http://www.cydiasubstrate.com/ 動的に命令を書き換えて、 処理をHookするFrameworkもある 52
  53. 53. • 一般的なチート手法 • Gameの分析 • 対策法 • まとめ 53
  54. 54. 対策法 • 難読化 – 意図的にコードを難しくする • 暗号化 – ファイルを暗号化しておき、実行時に復号する 静的解析の対策 54
  55. 55. 難読化の例 Unityの*.dllをAppFuscatorで難読化 Game実行に問題はないが、デコンパイルしても可読性は低い AppFuscator: http://appfuscator.com/55
  56. 56. 暗号化の例 Assembly-CSharp.dll https://github.com/Unity-Technologies/mono mono/metadata/image.c MonoImage * mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name) { MonoCLIImageInfo *iinfo; MonoImage *image; char *datac; // add DLL decrypt code if (name != NULL && strstr(name, "Assembly-CSharp.dll")) { // decrypt code for(int i=0; i < data_len; i++) { data[i] ^= 0xFF; } } 56
  57. 57. Demo 57
  58. 58. UnityPlayerActivity.java → onCreate () → new UnityPlayer () → System.loadLibrary (“libmain.so”); # in Static initializer libmain.so → JNI_Onload () → NativeLoader.load, unload <-> load, unload in libmain.so Unity起動処理 → NativeLoader.load(); # in Constructor of UnityPlayer libmain.so → load “libmono.so” and “libunity.so” libunity.so → JNI_Onload () → NativeXXX <-> UnityPlayer → load “libil2cpp.so” → load *.dll libmono.so 復号処理を追加 暗号化済み58
  59. 59. Cocos2dxActivity.java → onCreate () → init () → new Cocos2dxRenderer () → onSurfaceCreated () → nativeInit () javaactivity-android.cpp (libMyGame.so) → Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit () → onLoadNativeLibraries () → cocos2d::Application::getInstance()->run(); CCApplication-android.cpp (libMyGame.so) → applicationDidFinishLaunching () Classes/AppDelegate.cpp (libMyGame.so) → System.loadLibrary (“android.app.lib_name”); javaactivity-android.cpp (libMyGame.so) → JNI_Onload () → cocos_android_app_init () proj.android/jni/hellocpp/main.cpp (libMyGame.so) Cocos2d-x起動処理 59
  60. 60. 対策法 • 難読化 – 意図的にコードを難しくする • 暗号化 – ファイルを暗号化しておき、実行時に復号する 静的解析の対策 コードの可読性を下げたり、 GameCode以外の部分も解析しなければならないように コードを追加/変更する 60
  61. 61. 対策法 • プロセスの保護 – デバッガからのAttachを検知する • メモリ内容のエンコード or 暗号化 – メモリ内のDataは使用する直前に復号/暗号化する 動的解析の対策 プロセスを保護する手法が一般的 ただし、root権限からプロセスを完全に守るのは不可能 Gameそのものの安定性を阻害する原因にもなりうる 61
  62. 62. 対策法 Client側でGameの処理をしている以上、100%の対策は不可能 • Server側でClientのログを分析する – 不正ユーザーの多くはログを分析することで検知可能 • すべてをServer側に置く設計にする – ブラウザベースのゲーム、クラウドゲームなど 62
  63. 63. クラウドゲーム(Cloud gaming) 入力情報 入力情報をそのまま送信 Client Server 動画、音声を返す input output • Clientは”入力受け取り”と”動画再生”のみを担う • Clientを分析してもチート行為はできない • リアルタイム画像分析によるBot行為は可能 構造的にゲームの不正行為ができない仕組み 63
  64. 64. Game における Security Risk 1. 悪意あるPlayerが攻略を簡略化できるもの 2. 悪意あるPlayerが他Playerに被害を与えられるもの 本当にマズいのは 2. であるため、 仮にGameプロトコルを解析されたとしても、 他Playerに直接影響が出ないように設計するべき 64
  65. 65. 対策法 Client側でGameの処理をしている以上、100%の対策は不可能 • Server側でClientのログを分析する – 不正ユーザーの多くはログを分析することで検知可能 • すべてをServer側に置く設計にする – ブラウザベースのゲーム、クラウドゲームなど • 他Playerに被害が及ばない設計にする 65
  66. 66. • 一般的なチート手法 • Gameの分析 • 対策法とその仕組み • まとめ 66
  67. 67. まとめ • ツール対策はしておきたい – ツールを使えば簡単にCheatできるのは阻止したい • 時間をかければ必ず解析できる – 費用対効果を考えてセキュリティ対策を – Server側で調査できるようにログをとっておくなど • 解析されたとしても安全な設計を – 無関係のPlayerに被害が及ぶのはよろしくない – Server側の脆弱性が露見するなど 67
  68. 68. References 68 mono-project http://www.mono-project.com/ CIL http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf An introduction to IL2CPP internals https://blogs.unity3d.com/jp/2015/05/06/an-introduction-to-ilcpp-internals/ cocos2d-xでAndroidの起動シーケンスを追いかけてみる http://qiita.com/yosizo@github/items/53c74f0267becd6a81df [Unity/C#]WWW/HttpWebRequestにおける中間者攻撃の危険性を考慮した通信プログラムまとめ http://qiita.com/harmegiddo/items/b72ca4f430292251c8a6 DeNAtechcon_DeNAのセキュリティの取り組みと、スマートフォンセキュリティ https://www.slideshare.net/harupu/denatechcondenasameorigin-policy スマートフォンゲームのチート事情 https://www.slideshare.net/ssuser8200d3/ss-59926328 セキュリティエンジニアからみたUnityのこと https://engineering.linecorp.com/ja/blog/detail/110 Unityゲーム開発 オンライン3Dアクションゲームの作り方 https://www.amazon.co.jp/dp/B00QJINRHK 作れる! 学べる! Unreal Engine 4 ゲーム開発入門 https://www.amazon.co.jp/dp/4798149373
  69. 69. References 69 Unity https://unity3d.com Cocos2d-x http://www.cocos2d-x.org/ Unreal Engine 4 https://www.unrealengine.com IDA https://www.hex-rays.com/ apktool https://ibotpeaches.github.io/Apktool/ dex2jar https://sourceforge.net/projects/dex2jar/ AppFuscator http://appfuscator.com/ Unity Technologies mono https://github.com/Unity-Technologies/mono Unity metadata loader https://github.com/kenjiaiko/unity_metadata_loader https://github.com/nevermoe/unity_metadata_loader

×