HackShieldはMMORPGの為に開発されたアンチハッキングツールキットのセットである.Combat Arms, メイプルストーリー, マビノギなど数多くのオンラインゲームで採用されている. HackShieldは韓国のセキュリティ・ソリューション・プロバイダであるアンラボ社(AhnLab,Inc.)によって開発され, 韓国では2001年から, アメリカでは2005年から, 日本では2006年から広く利用されるようになった.
製品
AhnLab HackShield にはHackShield Basic For OnlineGame, HackShield Plus For OnlineGame, HackShield Pro For OnlineGameの三種類があるが日本で主に販売されているのはProである.
機能
以下に示すオンラインゲームセキュリティに特化する優れた機能を多数有しており機能面ではライバルの nProtect GameGuard とほぼ同等である.
- メモリハッキング遮断
- スピードハック遮断
- デバッガ遮断
- メッセージフック遮断
- オートマウス遮断
- ファイル改ざん遮断
- ランタイム改ざん遮断
- 実行ファイルパッキング/暗号化
- パケット暗号化
- データファイル暗号化
- サーバサイドクラック保護
- スマートアップデート
HackShieldコンポーネント
- EhSvc.dll
- HackShieldのインターフェースのDLLでありゲームクライアントとHackShield間の通信およびHackShieldドライバ(EagleNT.sys)との通信を担っている
- このDLLによって主なハッキング検出エンジンが実行されるため,Bypassを行う上ではこのDLLに手が加えられることが多い
- V3Pro32s.dll
- ハッキングツール検出インターフェースのDLLである
- このDLLによってハッキングツールの検出エンジンが実行され,既知のハッキングツールシグニチャのスキャンが開始される
- 3N.mhe
- ヒューリスティックエンジンのためのファイルであり既知のハッキングを検索するためのパターンが含まれている
- psapi.dll
- プロセスステートヘルパーDLL
- プロセスシグニチャとプロセス制御関数のスキャンに利用される
- V3Warp(d)(n)s.v3d
- アンチハッキングエンジンパターンファイル
- 3N.mheファイルを読み込んでいる
- EagleNT.sys
- HackShieldのカーネルドライバ
- ゲームクライアントプロセスの保護,特定のAPIのフックなどアンチハッキング機能を実行する
HackShieldの動作
HackShieldの特徴は強力な暗号システムの実装であり,クライアントとサーバ間で送信されるすべてのデータがAES-256を用いて行われている.
ハッキングやマルウェアのシグニチャをメモリ上から走査するとともに, サーバやライブラリ(.dll)の妥当性をリアルタイムで検証している.
また,HackShieldのコンポーネントはThemidaという非常に強力なパッカーでパッキングされている.
HackShieldの機能を傍受するためにはその実行の流れを把握することが重要である.
HSUpdate
ゲームを起動時に右下にプログレスバーを含むアップデートダイアログが表示されるように,HackShieldはゲーム起動毎にHSUpdate.exeを実行してファイルの更新を行っている.
この更新システムはFTPとWEBの2つのプロトコルに基づいている.
- FTP
- FTPプロトコルはHackShield開発者に応じてカスタマイズされている
- HSUpdateはMMORPGのサーバに接続してアップデートファイルのCRCハッシュを検証した後でファイルを交換する
- WEB
- 単にデータを取得するためにGETおよびPOSTリクエストを送信する
- これらはFiddler2というHTTPプロキシスニファで傍受可能である
アップデートが終了するとゲームクライアントはHackShieldの根幹機能をロード(Kernel32.LoadLibraryA)してハッキング検出エンジンが実行される.
EHSvc
HackShieldのインターフェースDLLでありハッキング検出エンジンの実行およびゲームクライアントとHackShield間の通信およびHackShieldドライバ(EagleNT.sys)との通信を担っている.
このライブラリがHackShieldのバイパスにおける最も重要なコンポーネントである.
EHSvcではHackShieldにおけるすべての内部操作のロギング(暗号化されている)を行い, すべてのトラフィックが暗号化されているHSMSサーバ(HackShield Monitoring Server)にログを送信している.
この情報が不正であればゲームサーバとの通信が断たれてしまうため, HSを完全にバイパスするためには偽のログ情報を送信しなければならない.
HSの動作を理解するにはこのライブラリに焦点を当てるべきである.
EagleNT
EagleNTはライブラリの変更を防止するためのカーネルドライバである.
ゲームクライアントプロセスの保護,特定のAPIのフックなどアンチハッキング機能を実行する.
V3Pro32
ハッキングツールや任意のマルウェアの感染をスキャンするエンジンを含むインターフェースのDLLである.
HackShieldの導入
ゲームの開発者にとってHackShieldを導入することはさほど難しいことではない.
開発者はまず始めにアップデータを呼び出す.
DWORD ReturnCode = NULL;
ReturnCode = _AhnHS_HSUpdateEx(
szFullFilePath, // hshieldフォルダパス
1000 * 600, // 更新のタイムアウト時間
1234, // ゲームコード(ライセンスに付属)
AHNHSUPDATE_CHKOPT_HOSTFILE| AHNHSUPDATE_CHKOPT_GAMECODE, // 追加オプション
HsExtError, // エラーコード
1000* 20 // サーバ接続のタイムアウト時間
);
switch (ReturnCode)
{
case HSERROR_ENVFILE_NOTREAD:
// HSUpdate.envを読み込めない
break;
case HSERROR_ENVFILE_NOTWRITE:
// HSUpdate.envに書き込めない
break;
case HSERROR_NETWORK_CONNECT_FAIL:
// サーバに接続できない
break;
[Eccetera per i vari e vari errori]
}
HackShieldはエラーやハッキングの検出を警告すると多くの場合メッセージボックスを表示してゲームを終了する.これらはゲームクライアントのコールバック(スイッチ文)によって管理されている.
一昔前はこのコールバックを中断することでHackShieldを容易にバイパスすることが可能であった.
EHSvcについては呼び出し方がアップデータとは少し異なる.
EHSvcはゲーム開発者が購入した有効なライセンスで起動する必要があり,この情報はライブラリがロードされる際に与えられている.
BOOL HS_Init()
{
// [...]
// 任意の変数宣言
DWORD dwOption = AHNHS_CHKOPT_ALL; // 全てのオプションを実行
nRet = _AhnHS_Initialize (
szFullFilePath, // hshieldフォルダパス
HS_CallbackProc, // このコールバックはEHSvcと同じモジュールによって呼び出されクライアントからは実行されない
1234, // ゲームコード(ライセンスに付属)
"B228F291B7D7FAD361D7A4B7", // ライセンスキー
dwOption, // オプションフラグ
AHNHS_SPEEDHACK_SENSING_RATIO_NORMAL // スピードハックをチェックする頻度を設定
);
if (nRet != HS_ERROR_OK)
// ...
}
なお, ゲームクライアントのライセンスキーとゲームコードを見つけるのは難しいことではない.
HackShieldのバイパスを最初に考える上で安易に考えつくのがEHSvc.dllをロードさせないようにするというアイデアであるがこれは間違いである.
なぜなら, EHSvcが初期化された後でゲームクライアント側で簡単な関数 _AhnHS_StartService() が呼び出されることによってHackShieldが正常に実行されているかどうかを監視する機能が実行されるからである.
HackShieldの調査
まず第一に, ThemidaでパックされているEHSvc.dllをアンパックしてプロセスメモリのダンプを実行することがHackShieldのバイパスをを探す上で常に最善の選択である(Themidaのアンパックについてはtuts4youなどのサイトを参考にするとよい).
この調査では, "MaplsStory"というオンラインゲームに同梱されているHackShieldの最新バージョンを利用している.
現時点でのバージョンは5.6.34.449である.
分析に必要なツール:
- IDA Pro
- Olly(Strong ODやPhantOmなどのアンチ-アンチデバッグプラグインが導入済みのもの)
- PEiDとKrypto Analyzer
バイパスの構築に必要な知識:
- PE構造についての知識
- CまたはC++の知識
- Microsoft Detours 3 (または 1.5)
- メモリ編集機能についての知識
- Injector (RemoteDLLなど)
IDA Proによる分析が完了した後でEHSvcの構造について認識する必要がある. エクスポートテーブルを見れば序数だけで構成された関数を確認することができる.
これらの関数のほとんどが各種更新やAhnlabのスワップ機能でありそれらは役に立たないが, それ以外のコールバックを呼び出しエラーを返す関数はバイパスを行う上で重要である.
インポートテーブルを確認するのは, EHSvc内で行われるいくつかの機能を特定するのに有用であろう.
+
|
インポート一覧 |
Address Ordinal Name Library
------- ------- ---- -------
10120000 AddAce ADVAPI32
10120004 GetLengthSid ADVAPI32
10120008 CopySid ADVAPI32
1012000C GetTokenInformation ADVAPI32
10120010 RegOpenKeyA ADVAPI32
10120014 RegDeleteValueA ADVAPI32
10120018 OpenThreadToken ADVAPI32
1012001C RegEnumValueA ADVAPI32
10120020 RegQueryInfoKeyA ADVAPI32
10120024 RegEnumKeyExA ADVAPI32
10120028 OpenProcessToken ADVAPI32
1012002C LookupPrivilegeValueA ADVAPI32
10120030 AdjustTokenPrivileges ADVAPI32
10120034 RegCreateKeyExA ADVAPI32
10120038 RegCloseKey ADVAPI32
1012003C RegOpenKeyExA ADVAPI32
10120040 RegSetValueExA ADVAPI32
10120044 RegQueryValueExA ADVAPI32
10120048 AllocateAndInitializeSid ADVAPI32
1012004C LookupAccountSidA ADVAPI32
10120050 FreeSid ADVAPI32
10120054 InitializeSecurityDescriptor ADVAPI32
10120058 SetSecurityDescriptorDacl ADVAPI32
1012005C InitializeAcl ADVAPI32
10120060 EqualSid ADVAPI32
10120064 GetExplicitEntriesFromAclA ADVAPI32
10120068 GetNamedSecurityInfoA ADVAPI32
1012006C GetAce ADVAPI32
10120070 GetAclInformation ADVAPI32
10120074 IsValidSid ADVAPI32
10120078 GetSidSubAuthority ADVAPI32
1012007C GetSidSubAuthorityCount ADVAPI32
10120080 CloseServiceHandle ADVAPI32
10120084 CreateServiceA ADVAPI32
10120088 OpenSCManagerA ADVAPI32
1012008C DeleteService ADVAPI32
10120090 OpenServiceA ADVAPI32
10120094 StartServiceA ADVAPI32
10120098 ControlService ADVAPI32
1012009C QueryServiceStatus ADVAPI32
101200A0 UnlockServiceDatabase ADVAPI32
101200A4 ChangeServiceConfigA ADVAPI32
101200A8 LockServiceDatabase ADVAPI32
101200AC RegSetValueExW ADVAPI32
101200B0 GetKernelObjectSecurity ADVAPI32
101200B4 SetNamedSecurityInfoA ADVAPI32
101200BC CryptMsgUpdate CRYPT32
101200C0 CryptQueryObject CRYPT32
101200C4 CertFreeCertificateChain CRYPT32
101200C8 CertGetSubjectCertificateFromStore CRYPT32
101200CC CryptMsgControl CRYPT32
101200D0 CertOpenSystemStoreA CRYPT32
101200D4 CertCloseStore CRYPT32
101200D8 CryptMsgClose CRYPT32
101200DC CertFreeCRLContext CRYPT32
101200E0 CertVerifySubjectCertificateContext CRYPT32
101200E4 CertFindCertificateInStore CRYPT32
101200E8 CryptMsgGetParam CRYPT32
101200EC CryptDecodeObject CRYPT32
101200F0 CertGetNameStringA CRYPT32
101200F4 CryptMsgOpenToDecode CRYPT32
101200F8 CertOpenStore CRYPT32
10120100 SelectObject GDI32
10120104 DeleteObject GDI32
10120108 CreateCompatibleDC GDI32
1012010C GetObjectA GDI32
10120110 BitBlt GDI32
10120114 StretchBlt GDI32
10120118 GetStockObject GDI32
1012011C SetBkMode GDI32
10120120 SetTextColor GDI32
10120124 CreateFontA GDI32
10120128 DeleteDC GDI32
1012012C GetBitmapBits GDI32
10120130 CreateCompatibleBitmap GDI32
10120134 GetDeviceCaps GDI32
10120138 CreateDCA GDI32
10120140 lstrcat kernel32
10120144 lstrcpyn kernel32
10120148 GlobalMemoryStatus kernel32
1012014C GetSystemInfo kernel32
10120150 FileTimeToSystemTime kernel32
10120154 FileTimeToLocalFileTime kernel32
10120158 GetFileTime kernel32
1012015C GetLocalTime kernel32
10120160 lstrlen kernel32
10120164 LocalFree kernel32
10120168 lstrcpy kernel32
1012016C LocalAlloc kernel32
10120170 DeleteFileA kernel32
10120174 OutputDebugStringA kernel32
10120178 FormatMessageA kernel32
1012017C CreateProcessW kernel32
10120180 CreateFileW kernel32
10120184 GetExitCodeProcess kernel32
10120188 GetExitCodeThread kernel32
1012018C SetThreadPriority kernel32
10120190 ResetEvent kernel32
10120194 OpenEventA kernel32
10120198 QueryPerformanceCounter kernel32
1012019C QueryPerformanceFrequency kernel32
101201A0 CreateProcessA kernel32
101201A4 OpenProcess kernel32
101201A8 MultiByteToWideChar kernel32
101201AC LoadLibraryExA kernel32
101201B0 lstrlenW kernel32
101201B4 ExitThread kernel32
101201B8 TlsAlloc kernel32
101201BC TlsSetValue kernel32
101201C0 TlsGetValue kernel32
101201C4 CreateMutexA kernel32
101201C8 GetLongPathNameA kernel32
101201CC SetEndOfFile kernel32
101201D0 WriteFile kernel32
101201D4 ReleaseMutex kernel32
101201D8 CreateFileMappingW kernel32
101201DC Module32Next kernel32
101201E0 Module32First kernel32
101201E4 CreateToolhelp32Snapshot kernel32
101201E8 OpenMutexA kernel32
101201EC OpenFileMappingA kernel32
101201F0 FlushViewOfFile kernel32
101201F4 DuplicateHandle kernel32
101201F8 lstrcmp kernel32
101201FC WaitForSingleObjectEx kernel32
10120200 DefineDosDeviceA kernel32
10120204 QueryDosDeviceA kernel32
10120208 TerminateProcess kernel32
1012020C SetFileAttributesA kernel32
10120210 GetShortPathNameA kernel32
10120214 MoveFileExA kernel32
10120218 IsBadWritePtr kernel32
1012021C IsBadReadPtr kernel32
10120220 InitializeCriticalSectionAndSpinCount kernel32
10120224 OpenSemaphoreA kernel32
10120228 ReadProcessMemory kernel32
1012022C Process32Next kernel32
10120230 Process32First kernel32
10120234 GetDriveTypeA kernel32
10120238 FindClose kernel32
1012023C FindNextFileA kernel32
10120240 FindFirstFileA kernel32
10120244 ReadFile kernel32
10120248 Thread32Next kernel32
1012024C Thread32First kernel32
10120250 lstrcpynW kernel32
10120254 VirtualFreeEx kernel32
10120258 HeapReAlloc kernel32
1012025C GetComputerNameA kernel32
10120260 GetDiskFreeSpaceA kernel32
10120264 GetVolumeInformationA kernel32
10120268 GetTempFileNameA kernel32
1012026C GetTempPathA kernel32
10120270 GetPrivateProfileStringA kernel32
10120274 GetCurrentProcessId kernel32
10120278 CopyFileA kernel32
1012027C CreateDirectoryA kernel32
10120280 GetProcessAffinityMask kernel32
10120284 SetThreadAffinityMask kernel32
10120288 GetVersion kernel32
1012028C GetThreadLocale kernel32
10120290 GetStartupInfoA kernel32
10120294 GetLocaleInfoA kernel32
10120298 GetCommandLineA kernel32
1012029C ExitProcess kernel32
101202A0 UnhandledExceptionFilter kernel32
101202A4 RtlUnwind kernel32
101202A8 RaiseException kernel32
101202AC GetStdHandle kernel32
101202B0 TlsFree kernel32
101202B4 lstrcpyW kernel32
101202B8 lstrcmpiW kernel32
101202BC lstrcatW kernel32
101202C0 WriteProcessMemory kernel32
101202C4 WaitForMultipleObjects kernel32
101202C8 VirtualQueryEx kernel32
101202CC OpenMutexW kernel32
101202D0 OpenFileMappingW kernel32
101202D4 OpenEventW kernel32
101202D8 GetTempPathW kernel32
101202DC GetTempFileNameW kernel32
101202E0 GetFileAttributesW kernel32
101202E4 GetFileAttributesA kernel32
101202E8 GetCurrentDirectoryW kernel32
101202EC GetCurrentDirectoryA kernel32
101202F0 DeleteFileW kernel32
101202F4 CreatePipe kernel32
101202F8 CreateMutexW kernel32
101202FC CreateEventW kernel32
10120300 LockResource kernel32
10120304 SizeofResource kernel32
10120308 LoadResource kernel32
1012030C FindResourceA kernel32
10120310 GetSystemTime kernel32
10120314 GetEnvironmentVariableA kernel32
10120318 FatalAppExitA kernel32
1012031C HeapSize kernel32
10120320 GetCPInfo kernel32
10120324 GetACP kernel32
10120328 GetOEMCP kernel32
1012032C VirtualAllocEx kernel32
10120330 HeapDestroy kernel32
10120334 HeapCreate kernel32
10120338 DeviceIoControl kernel32
1012033C CreateFileMappingA kernel32
10120340 MapViewOfFile kernel32
10120344 GetWindowsDirectoryA kernel32
10120348 GetCurrentThread kernel32
1012034C CreateThread kernel32
10120350 TerminateThread kernel32
10120354 SetThreadContext kernel32
10120358 SetLastError kernel32
1012035C GetModuleFileNameA kernel32
10120360 VirtualQuery kernel32
10120364 SuspendThread kernel32
10120368 GetThreadContext kernel32
1012036C GetCurrentThreadId kernel32
10120370 LCMapStringA kernel32
10120374 LCMapStringW kernel32
10120378 SetUnhandledExceptionFilter kernel32
1012037C FlushFileBuffers kernel32
10120384 FreeEnvironmentStringsA kernel32
10120388 FreeEnvironmentStringsW kernel32
1012038C GetEnvironmentStrings kernel32
10120390 GetSystemDirectoryA kernel32
10120394 LoadLibraryW kernel32
10120398 GetProcessHeap kernel32
1012039C HeapAlloc kernel32
101203A0 HeapFree kernel32
101203A4 GetVersionExA kernel32
101203A8 GetSystemDirectoryW kernel32
101203AC GetModuleFileNameW kernel32
101203B0 GetModuleHandleW kernel32
101203B4 UnmapViewOfFile kernel32
101203B8 CloseHandle kernel32
101203BC InterlockedIncrement kernel32
101203C0 InterlockedDecrement kernel32
101203C4 DeleteCriticalSection kernel32
101203C8 InterlockedCompareExchange kernel32
101203CC Sleep kernel32
101203D0 GetModuleHandleA kernel32
101203D4 InitializeCriticalSection kernel32
101203D8 EnterCriticalSection kernel32
101203DC LeaveCriticalSection kernel32
101203E0 GetCurrentProcess kernel32
101203E4 FlushInstructionCache kernel32
101203E8 GetLastError kernel32
101203EC VirtualAlloc kernel32
101203F0 InterlockedExchange kernel32
101203F4 VirtualFree kernel32
101203F8 WideCharToMultiByte kernel32
101203FC GetTickCount kernel32
10120400 FreeLibrary kernel32
10120404 LoadLibraryA kernel32
10120408 GetProcAddress kernel32
1012040C ResumeThread kernel32
10120410 SetEvent kernel32
10120414 WaitForSingleObject kernel32
10120418 CreateEventA kernel32
1012041C CreateFileA kernel32
10120420 GetFileSize kernel32
10120424 VirtualProtectEx kernel32
10120428 SetFilePointer kernel32
1012042C VirtualProtect kernel32
10120430 GetEnvironmentStringsW kernel32
10120434 GetStringTypeA kernel32
10120438 GetStringTypeW kernel32
1012043C IsBadCodePtr kernel32
10120440 SetStdHandle kernel32
10120444 IsValidLocale kernel32
10120448 IsValidCodePage kernel32
1012044C EnumSystemLocalesA kernel32
10120450 GetUserDefaultLCID kernel32
10120454 SetConsoleCtrlHandler kernel32
10120458 GetLocaleInfoW kernel32
1012045C CompareStringA kernel32
10120460 CompareStringW kernel32
10120464 SetEnvironmentVariableA kernel32
10120468 CompareFileTime kernel32
1012046C GetTimeZoneInformation kernel32
10120470 SetCurrentDirectoryA kernel32
10120474 SetFileTime kernel32
10120478 MoveFileA kernel32
1012047C GetFullPathNameA kernel32
10120480 GetFileInformationByHandle kernel32
10120484 lstrcmpi kernel32
10120488 PeekNamedPipe kernel32
1012048C GetFileType kernel32
10120494 CreateErrorInfo oleaut32
10120498 VariantChangeType oleaut32
1012049C SetErrorInfo oleaut32
101204A0 GetErrorInfo oleaut32
101204A4 SysReAllocStringLen oleaut32
101204A8 VariantInit oleaut32
101204AC VariantClear oleaut32
101204B0 SysStringLen oleaut32
101204B4 SysAllocString oleaut32
101204B8 SysFreeString oleaut32
101204BC OleLoadPicturePath oleaut32
101204C4 Shell_NotifyIcon SHELL32
101204C8 ShellExecuteEx SHELL32
101204D0 SendMessageA USER32
101204D4 EnumThreadWindows USER32
101204D8 PostMessageA USER32
101204DC FindWindowExA USER32
101204E0 GetWindowLongA USER32
101204E4 GetWindowModuleFileName USER32
101204E8 EnumWindows USER32
101204EC RegisterClipboardFormatA USER32
101204F0 FindWindowA USER32
101204F4 DefWindowProcA USER32
101204F8 IsWindow USER32
101204FC GetWindowInfo USER32
10120500 SendMessageTimeoutA USER32
10120504 GetClassNameA USER32
10120508 IsWindowUnicode USER32
1012050C EnumChildWindows USER32
10120510 CharUpperBuffA USER32
10120514 CharLowerBuffA USER32
10120518 CallNextHookEx USER32
1012051C UnhookWindowsHookEx USER32
10120520 SetWindowsHookExA USER32
10120524 GetKeyboardType USER32
10120528 PeekMessageA USER32
1012052C OpenInputDesktop USER32
10120530 GetForegroundWindow USER32
10120534 GetWindowThreadProcessId USER32
10120538 CreateDialogParamA USER32
1012053C GetMessageA USER32
10120540 IsDialogMessage USER32
10120544 TranslateMessage USER32
10120548 DispatchMessageA USER32
1012054C IsIconic USER32
10120550 GetDlgItem USER32
10120554 ShowWindow USER32
10120558 GetClientRect USER32
1012055C GetParent USER32
10120560 GetDesktopWindow USER32
10120564 GetWindowRect USER32
10120568 GetSystemMetrics USER32
1012056C SetWindowPos USER32
10120570 SetTimer USER32
10120574 KillTimer USER32
10120578 PostQuitMessage USER32
1012057C CopyImage USER32
10120580 LoadImageA USER32
10120584 MessageBoxA USER32
10120588 wsprintfW USER32
1012058C wvsprintfA USER32
10120590 wsprintfA USER32
10120594 CharUpperA USER32
10120598 MsgWaitForMultipleObjects USER32
1012059C GetUserObjectInformationA USER32
101205A0 GetThreadDesktop USER32
101205A4 CloseDesktop USER32
101205AC VerQueryValueA VERSION
101205B0 GetFileVersionInfoSizeW VERSION
101205B4 GetFileVersionInfoW VERSION
101205B8 VerQueryValueW VERSION
101205BC GetFileVersionInfoSizeA VERSION
101205C0 GetFileVersionInfoA VERSION
101205C8 HttpQueryInfoA WININET
101205CC InternetReadFileExA WININET
101205D0 HttpSendRequestA WININET
101205D4 InternetSetStatusCallback WININET
101205D8 InternetConnectA WININET
101205DC InternetCloseHandle WININET
101205E0 HttpOpenRequestA WININET
101205E4 DeleteUrlCacheEntry WININET
101205E8 InternetReadFile WININET
101205EC InternetCrackUrlA WININET
101205F0 InternetCanonicalizeUrlA WININET
101205F4 InternetOpenA WININET
101205FC timeGetTime winmm
10120600 timeSetEvent winmm
10120604 timeKillEvent winmm
1012060C WSAStartup WS2_32
10120610 WSACleanup WS2_32
10120614 htons WS2_32
10120618 gethostbyname WS2_32
1012061C inet_ntoa WS2_32
10120624 ImageEnumerateCertificates imagehlp
10120628 ImageGetCertificateHeader imagehlp
10120630 GetAdaptersInfo iphlpapi
10120638 CoUninitialize ole32
1012063C CoSetProxyBlanket ole32
10120640 CoCreateInstance ole32
10120644 CoInitializeSecurity ole32
10120648 CoInitializeEx ole32
10120650 URLDownloadToFileA urlmon
|
バイパスに必要な機能を検索するにはアンパックされていないEHSvcをゲームクライアントを介して起動し, その実行挙動を確認して行かなければならない.
残念ながら, ThemidaによってパッキングされているためIDAやOllyでこれを行うことは困難である.Cheat Engineの
デバッグ機能を活用する方法はある).
アンパックされたEHSvcをアンパックされたゲームクライアントを介して起動して分析する方法も考えられるが, この方法ではモジュールがサーバの署名と一致しないために分析は失敗に終わるだろう.
いずれにせよ, 真のバイパスを実現するために見つけなければならないEHSvcに実装されている関数を以下に示す:
- LMP Check
- EHSvcまたはゲームクライアントはサーバに登録されたディジタル署名によって改竄が行われていないかどうかをチェックしている.
- このチェックを回避する唯一の方法が, 我々が独自に実装したもので本来の機能を置き換えるものである.
- Main Thread
- スキャンの開始を処理する関数であり, これを回避するためには独自の機能に置き換えた上で偽のスキャンスレッドによって動作を偽装する必要がある.
- Heuristic Scan
- この関数は,ゲームクライアントからあらゆるチート行為をスキャンしている.
- Heuristic Module Scan
- この関数は,EHSvcの走査モジュールの改竄を監視している.
- Integrity Check
- モジュールが完全であるかどうかをチェックし,内部の整合性を確認するためにサーバへのコールを実行する.
- Kernel Tracer [KDTrace]
- メモリ改ざんを検出するために, EHSvcとドライバ間でコールモニタリングを実行する.
EHSvcモジュール内のすべての文字列を識別するのは良いアイデアだが, 残念ながらいくつかの文字列はBase64または各文字列キーによるXORでエンコードされている.
これらの文字列を復号するためには暗号化アルゴリズムとそのキーを調査する必要があるが, これはバイパスにおいて必須ではない.
これら重要な関数を特定することはそこまで難しいものではない:
HSは我々がバイパスするべきスレッドを起動する上でCreateEventA, CreateEventW, CreateThread, SetEventなどの関数を利用している.
一度リバースエンジニアリングおよびデバッギングによってバイパスすべきスレッドを識別してしまえば, それを独自のスレッドと置き換えることは容易である.
また, CRCによるチェックを特定するには, 単にKrypto Analyzerなどのツールを利用してCRCが行われている関数を明らかにしてしまえば良い.
これらの操作はIDA Proによって容易に実行することが可能である.
Tip & Tricks
ログを利用した機能の追跡
DEBUGモードを有効にすることでEHSvcの収集するログ情報を監視して興味深い関数呼び出しを見つけるのに役立てるトリックを紹介する.
DEBUGモードはシングルバイトで管理されており, Kernel32.wsprintfAを呼び出す関数を調べることによって見つけることができる.
このシングルバイトを0x01または0x02に変更した上で, 単にOutputDebugStringA()による出力をロギングするだけでよい.
引用元文献
最終更新:2014年12月03日 10:57