株式会社Ninjastars
セキュリティエンジニア:一瀬健二郎
CheatEngine・うさみみハリケーン等のプロセスメモリエディタツールにはゲーム内時間を加速・減速させる機能が付属しています。
このような機能は一般的にスピードハック(Speed Hack)と呼ばれています。
この機能は脅威となる場合もあるため、簡単な原理の紹介と対策をご紹介いたします。
※詳細な実装などについては触れません。
原理
様々な手法がありますが、Cheat Engine等では時間関連のAPIを改変することで実現します。
Windows上でCheat Engineの場合Speed Hackを実現するにあたり改変するWindowsAPIは以下の3つです。
GetTickCount
GetTickCount64
QueryPerformanceCounter
これらの時間関連のAPIの戻り値を以下の計算式で改変します。
start_time =スピードハック開始時間 current_time = 現在時間 return_time = 戻り値 speed = 加速・減速率 return_time = start_time + ((current_time - start_time)*speed)
このタイプのSpeed Hackは上記のように経過時間をシステムに誤認させることで加速・減速を実現させます。
またAPIの改変は一般的に以下のような手法で実現されます。
・先頭処理をjmp命令に書き換え、偽の関数に置き換える。
・関数アドレステーブル(IAT等)の値を偽の関数のアドレスに置き換える。
etc
対策
一例としてCheat EngineのSpeed Hackを検知するシステムを考えます。
上記に記載した通り、Cheat Engineは3つの時間関連のAPIのみ改変します。
つまりこの3つに依存しない別の時間関連の関数で経過時間を計測し、比較することでSpeed Hackを検知することが可能です。
以下のプログラムをVisualStudio等でビルドし、Cheat EngineでアタッチしてSpeed Hackを有効にしてみましょう。
Speed Hackを検知してシステムが終了するはずです。
DetectSpeedHack.cpp
#include <windows.h> #include <iostream> using namespace std; int main() { DWORD start_time = 0; DWORD elapsed_time = 0; while (true) { //開始時刻 start_time = GetTickCount(); //1秒待機 Sleep(1000); //GetTickCountによる経過時間を取得 elapsed_time = GetTickCount() - start_time; //GetTickCountが改変されSpeed Hackされてる場合プロセス終了する。 if (elapsed_time < 900 || elapsed_time > 1100) { ExitProcess(0); } else { cout << elapsed_time << endl; } } return 0; }
※勿論Sleep関数も同時に改変された場合、上記は有効ではありません。
Speed Hackに対しては様々な対策があると思いますが、以下は例です。
・定期的なサーバとの経過時間の整合性チェック。
・時間関連の関数の実行プログラムのハッシュチェック(CRC等)。
・関数に依存しない経過時間の取得。
・DLLインジェクション等の阻止(一般的に偽の関数の用意のためにDLLインジェクションが行われるため)。
etc
まとめ
セキュリティ対策全般において、敵を知ることにより様々な視点からの対策が可能になると思います。
今回の記事が読者の皆様のセキュリティ対策の一助となれば幸いです。
注意事項
本レポートに記載されている内容を許可されていないソフトウェアで行うと、場合によっては犯罪行為となる可能性があります。そのため、記事の内容を試す際には許可されたソフトウェアに対してのみ実施するようにしてください。
本レポートについて
お問い合せ
E-mail:ichise@ninjastars-net.com
株式会社Ninjastarsエンジニア
一瀬健二郎