Slide 1

Slide 1 text

ゲームセキュリティからみたAndoird解析 Kenjiro Ichise 2020/6/20 ーメモリチートからカーネル改変までー

Slide 2

Slide 2 text

自己紹介 一瀬 健二郎(Kenjiro Ichise) 株式会社Ninjastars セキュリティエンジニア 業務内容:ソーシャルゲームの脆弱性診断、セキュリティセミナー・社内 CTFの開催など。 所属はゲームセキュリティ専門企業。チート対策などで Androidネイティブの部分に触れる事が多い。 twitter:@DoranekoSystems(猫) 日頃勉強したことや調査したことを元に、本日はお話しさせていただきます。

Slide 3

Slide 3 text

目次 1. ゲームのセキュリティ診断について 2. メモリチートって何だろう 3. スピードハックの原理とその対策 4. soインジェクションについて 5. Fridaによる通信解析 6. Androidカーネル改変入門(してみた話) 7. 終わりに

Slide 4

Slide 4 text

1.ゲームのセキュリティ診断について 会社では主にソーシャルゲームの脆弱性診断を行っています。(Unity,Cocos2dが多いです) 私自身が診断時に良く使うツールはFrida,lldb,Ghidra,PacketProxy等。 そこまで得意ではありませんがプログラミングが好きで、社内向けの診断効率化ツール等も開発しています。 商用ゲームのリバースエンジニアリングは一つ一つの謎を解き明かしていくようで、とても面白いです。 診断期間が2週間ほどの場合、最初の1週間でチート対策の回避や通信を解析し、残り1週間で網羅的にみる感じです。 最初は苦戦してた通信解析などもツールの進歩もあり、早ければ1日以内で解析できることもあります(後述のツールで。)

Slide 5

Slide 5 text

環境 ● AndroidStudio付属のAndroidエミュレータ(x86) ● Unityのチュートリアル(SurvivalShooter)※il2cppビルド ○ 一部説明用に機能を改造したもの。 ● 自作の解析ツール(MemoryScanner) ● 自作の解析ツール(Interceptor)

Slide 6

Slide 6 text

MemoryScanner ● リモート専用のメモリ検索・解析ツール。 ● Android端末内でサーバを起動し、 PC上のプログラムと 通信して解析を行う。 ● サーバ側:C++(AndroidNDK) ○ サーバ側でメモリの読み書き・検索を行う。 ● PC側:C#(.NET Framework) ○ 表示用のプログラム。

Slide 7

Slide 7 text

2.メモリチートって何だろう ● ゲームアプリのメモリ上に保存されている ScoreやHPの数値をツールなどにより検索を行いアドレスを見つ け出し、数値を書き換えることでゲームを優位にさせるチート行為の事。

Slide 8

Slide 8 text

メモリチートの説明

Slide 9

Slide 9 text

メモリを読み書きする方法の色々 ● ptraceシステムコール ○ Read:ptrace(PTRACE_PEEKDATA…)、ptrace(PTRACE_PEEKTEXT…) ○ Write:ptrace(PTRACE_POKEDATA…)、ptrace(PTRACE_POKETEXT…) ※32bitで4バイト毎、64bitで8バイト毎とメモリを読むのが非常に遅い。 ● 仮想ファイルシステム空間経由 ○ /proc/pid/memをopenする。 ○ lseek、read/writeを用いてメモリを読み書きする。 ○ 速度的にはptrace経由より大分高速化する。 ● process_vm_readv/process_vm_writev ○ AndroidNDKでは標準では呼び出せない。 ○ syscallシステムコール経由で呼び出す必要がある。 ○ アタッチを必要とせず、対象プロセスでの一時的な停止が発生しない。

Slide 10

Slide 10 text

ptraceでメモリを読み書きする例 右は指定したPIDの指定アドレスを読み書きする例。 注意) PTRACE_PEEKDATAは失敗した場合-1を返す。 読み取った値と区別がつかないためerrnoを参照する。

Slide 11

Slide 11 text

非root端末なら安全? 基本的にはroot権限がないと他のプロセスのメモリにアクセスできない。 1. run-asコマンドの利用 apkのAndroidManifest.xmlをdebbugable=”true”に改変してadbのrun-asコマンドを利用。 2. frida-gadget等 apk改変を行いsoファイルを読み込ませ、自分自身でメモリを読み書きする。 スタンドアロン型のフッキングが可能で非常に強力。 3. fork型 apk改変を行いsoファイルを読み込ませ、 forkで子プロセスを生成して親プロセスを解析する。

Slide 12

Slide 12 text

メモリ暗号化すれば安全? 単純な暗号化だと、メモリ検索を工夫することで絞り込まれてしまう。 実装した暗号化がメモリ上にどう展開されるのか、強度は充分か意識すると良い。 コマンドラインモードのメモリ解析ツール(Xorサーチ)

Slide 13

Slide 13 text

メモリを読み書きされることを防ぐには ● アンチデバッグ ○ forkシステムコール等で子プロセスを生成し、子プロセスから親プロセスにアタッチする。 ○ アタッチできるのは一つのプロセスまでなので、外部からのアタッチを防止できる。 ● メモリの暗号化 ○ 数値に対して乱数と xorを取るなどして生の値をメモリ上に置かない。 (強度は必要) ● メモリの改竄検知 ○ 数値に対してハッシュ値を保存し、整合性を取ることで改竄を検知する。 ● 端末のroot権限の監視 ○ root化されていたらアプリを起動終了させるなどの対応をする。 apk改変の検知などと合わせて行う。 ● その他 ○ /proc/pid/mem等のファイルオープンを監視する。

Slide 14

Slide 14 text

3.スピードハックの原理とその対策 プロセスメモリ改竄ツールには通常、ゲーム内時間を加速・減速させる機能が付属しています。 このような機能は一般的にスピードハック (Speed Hack)と呼ばれています。 この機能は脅威となる場合もあるため、簡単な原理の紹介と対策をご紹介いたします。

Slide 15

Slide 15 text

スピードハックの原理 一般的な手法では時間関連の関数を改変することで実現する。 この手法では、システムに対して経過時間を偽装することでスピードハックを実現している。 また上記を実現するために、対象プロセスに soファイルをインジェクションすることが多い。 soファイル内の偽の時間関連の関数に、実際の関数をすり替える ためである。 例えばGameGuardianはスピードハック時libN.so(Nは数値)というsoファイルをインジェクションする。 libN.soのシンボル情報を調査すると、偽の時間関連の関数が見つかる。

Slide 16

Slide 16 text

スピードハックの説明

Slide 17

Slide 17 text

スピードハックの対策例(クライアント側) 例:経過時間の不整合によるチェック 時間関連の関数を偽の関数にすり替えるが、 全ての時間関連の関数をすり換えるわけではない 。 一般的にフックされる関数とそうでない関数を調査し、経過時間の差を比較する。 Linux系OSの場合、特に以下の二つの関数はフッキングされることが多い。 clock_gettime gettimeofday

Slide 18

Slide 18 text

4.soインジェクションについて ● soインジェクション…soファイル(共有ライブラリ)を他のプロセスに読み込ませる手法のこと。 ● ptraceシステムコールを利用して、対象プロセスのメモリやレジスタの値を書き換えて soファイルを対象プ ロセスに読み込ませる。 ● 例えばFridaは解析の開始時に、対象プロセスに soファイル(frida-agent)をインジェクションする。 ● Android7.0以降はOSのセキュリティ機構により今回紹介する手法ではインジェクション出来ない。

Slide 19

Slide 19 text

soファイルを動的に読み込ませる方法1 ● Android,Linux等ではdlopen関数を利用するとsoファイルを動的にロードすることが可能。 ● void *dlopen(const char *pathname, int mode) ● 対象プロセスにsoファイルをインジェクションするためには、対象プロセスで dlopenを呼び出させれば良 い。 ● 自プロセスでない他のプロセスで任意の関数を呼び出すということは通常は出来ないが、 ptraceシステム コールを利用すれば可能になる。 ● ※端末のSELinuxがPermissiveになってる必要がある。

Slide 20

Slide 20 text

soファイルを動的に読み込ませる方法2 ptraceを利用し対象プロセスにアタッチが成功すると、対象プロセスは停止する。 この停止している間に以下を実行する。 1. プログラムカウンタを dlopenのアドレスに書き換える 2. dlopenの引数であるsoファイルのパスをメモリに書き込む 3. レジスタ(ARM)またはスタック上(x86)にdlopenの引数をセットする 4. 戻りアドレスを0に設定する(※ここが重要) この状態でプロセスを再開すると dlopenが実行されsoファイルがロードされた後、不正な戻りアドレスがセットさ れていたことにより制御が戻り対象プロセスは再度停止する。 ここで事前に保存して置いた最初の状態の レジスタの値をセットし、再開させることでプログラムは正常に動き 出す。

Slide 21

Slide 21 text

5.Fridaによる通信解析・改変 Androidに限らず、アプリケーションの通信処理を特定し解析するのは脆弱性診断時等に非常に重要。 Fridaでないと出来ない訳ではないが、 Fridaを用いることで効率的な解析が可能になる。 実現できること ● 通信の暗号化/復号関数の特定や調査。 ○ 大量の関数を同時にフッキングすることで処理の特定が容易になる。 ● フッキングによるリプレイアタック。 ○ 通信を発生させる特定の関数を任意回数強制的に呼び出す。 ● 暗号化/復号ロジックを無視した通信傍受、改変。 ● 端末のプロキシ設定を無視するアプリに対する対応。 ○ 宛先アドレスを強制的に変更する。 DNS偽装ではない別の方法。 ● 通信のタイムアウト等がある場合無効化する。 etc… ※上記は全てアプリの実装や保護レベルによって不可能な場合もあります。

Slide 22

Slide 22 text

Interceptor ● Fridaベースの通信解析・改変ツール。 ● 暗号化/復号処理等をフッキングし、プロキシツール の代わりにデータ取得・改変を行う。 ● 原理は違うがプロキシツール的感覚で操作できる。 ● 処理さえ見つければ、暗号ロジック等の解析が不要。 GUI:python+Qt 動作OS:マルチプラットフォーム Androidに限らず、iOSでも使える!!

Slide 23

Slide 23 text

デモ

Slide 24

Slide 24 text

6.Androidカーネル改変入門(してみた話) iOSと違い、AndroidはOSSであるからソースコードを弄れば何でも出来るはず。 自分だけの最強の解析用 Androidが欲しい...。 ということでAndroidカーネルの改変とビルドに挑戦してみました。 端末:Nexus5X Androidバージョン:6.0.1 ※具体的な手法は述べません。

Slide 25

Slide 25 text

出来たこと ● ptraceアンチデバッグの無効化 ○ 1つのプロセスに対して複数プロセスがアタッチできない制限を撤廃。 アンチデバッグを無効化して無限にアタッチできるように !! ● root権限無しで他のプロセスにアタッチ ● root権限無しで権限的に本来不可能なファイルを開く etc 少し修正するだけでも、本来有り得ない恐ろしい AndroidOSが完成する。 攻撃者が突き詰めれば、通常の Androidを前提としたセキュリティ対策は全て突破される危険性がある。 一方でマルウェア等を調査するとき、こうした手法は一定の実用性を持つかも ?

Slide 26

Slide 26 text

7.終わりに リバースエンジニアリングで解析していくのは、謎を解き明かすようで知的で楽しい行為だと思います。 本来の制限を回避して、自分が想定した通りに動作したときは非常に嬉しい気持ちになります。 情報セキュリティに携わる者一同、法律やルールを守って楽しくハッキングしていきましょう !! 最後にこうした場を設けていただいた日本ハッカー協会様および lumin様、誠に有難うございました。 拙いながら、本日の内容が皆様の情報セキュリティの知見にささやかでも貢献できたなら嬉しい限りです。 ご清聴ありがとうございました。