X-Git-Url: http://git.sourceforge.jp/view?p=ffftp%2Fffftp.git;a=blobdiff_plain;f=protectprocess.c;h=f0669a8866a480df236405296da89f9b22ad7159;hp=f118ae94ffcef6c4421d44705d12be9d19ab65de;hb=0d9559ea57ae201a5b1fe0161f88545141674c09;hpb=484a8d06abde1b0de9bd794aac5a03fb629625f0 diff --git a/protectprocess.c b/protectprocess.c index f118ae9..f0669a8 100644 --- a/protectprocess.c +++ b/protectprocess.c @@ -1,20 +1,20 @@ -// protectprocess.c +// protectprocess.c // Copyright (C) 2011 Suguru Kawamoto -// ƒvƒƒZƒX‚Ì•ÛŒì +// プロセスの保護 -// ŽŸ‚Ì’†‚©‚ç1ŒÂ‚Ì‚Ý—LŒø‚É‚·‚é -// ƒtƒbƒNæ‚̊֐”‚̃R[ƒh‚ð‘‚«Š·‚¦‚é -// ‘S‚Ă̌Ăяo‚µ‚ðƒtƒbƒN‰Â”\‚¾‚ªŒ´—“I‚É“ñdŒÄ‚яo‚µ‚ɑΉž‚Å‚«‚È‚¢ +// 次の中から1個のみ有効にする +// フック先の関数のコードを書き換える +// 全ての呼び出しをフック可能だが原理的に二重呼び出しに対応できない #define USE_CODE_HOOK -// ƒtƒbƒNæ‚̊֐”‚̃Cƒ“ƒ|[ƒgƒAƒhƒŒƒXƒe[ƒuƒ‹‚ð‘‚«Š·‚¦‚é -// “ñdŒÄ‚яo‚µ‚ª‰Â”\‚¾‚ªŒÄ‚яo‚µ•û–@‚É‚æ‚Á‚Ă̓tƒbƒN‚ð‰ñ”ð‚³‚ê‚é +// フック先の関数のインポートアドレステーブルを書き換える +// 二重呼び出しが可能だが呼び出し方法によってはフックを回避される //#define USE_IAT_HOOK -// ƒtƒbƒN‘Ώۂ̊֐”–¼ %s -// ƒtƒbƒN‘Ώۂ̌^ _%s -// ƒtƒbƒN‘Ώۂ̃|ƒCƒ“ƒ^ p_%s -// ƒtƒbƒN—p‚̊֐”–¼ h_%s -// ƒtƒbƒN‘Ώۂ̃R[ƒh‚̃oƒbƒNƒAƒbƒv c_%s +// フック対象の関数名 %s +// フック対象の型 _%s +// フック対象のポインタ p_%s +// フック用の関数名 h_%s +// フック対象のコードのバックアップ c_%s #include #include @@ -61,20 +61,20 @@ BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename); BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash); BOOL IsModuleTrusted(LPCWSTR Filename); -// •Ï”‚̐錾 +// 変数の宣言 #ifdef USE_CODE_HOOK #define HOOK_FUNCTION_VAR(name) _##name p_##name;BYTE c_##name[HOOK_JUMP_CODE_LENGTH * 2]; #endif #ifdef USE_IAT_HOOK #define HOOK_FUNCTION_VAR(name) _##name p_##name; #endif -// ŠÖ”ƒ|ƒCƒ“ƒ^‚ðŽæ“¾ +// 関数ポインタを取得 #define GET_FUNCTION(h, name) p_##name = (_##name)GetProcAddress(h, #name) -// ƒtƒbƒN‘Ώۂ̃R[ƒh‚ð’uŠ·‚µ‚ătƒbƒN‚ðŠJŽn +// フック対象のコードを置換してフックを開始 #define SET_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, FALSE) -// ƒtƒbƒN‘ΏۂðŒÄ‚яo‚·‘O‚ɑΏۂ̃R[ƒh‚𕜌³ +// フック対象を呼び出す前に対象のコードを復元 #define START_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, TRUE) -// ƒtƒbƒN‘ΏۂðŒÄ‚яo‚µ‚½Œã‚ɑΏۂ̃R[ƒh‚ð’uŠ· +// フック対象を呼び出した後に対象のコードを置換 #define END_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, NULL, FALSE) HOOK_FUNCTION_VAR(LoadLibraryA) @@ -100,9 +100,10 @@ DWORD g_ProcessProtectionLevel; DWORD g_LockedThread[MAX_LOCKED_THREAD]; WCHAR* g_pTrustedFilenameTable[MAX_TRUSTED_FILENAME_TABLE]; BYTE g_TrustedMD5HashTable[MAX_TRUSTED_MD5_HASH_TABLE][20]; +WNDPROC g_PasswordEditControlProc; -// ˆÈ‰ºƒtƒbƒNŠÖ” -// ƒtƒbƒN‘ΏۂðŒÄ‚яo‚·ê‡‚Í‘OŒã‚ÅSTART_HOOK_FUNCTION‚ÆEND_HOOK_FUNCTION‚ðŽÀs‚·‚é•K—v‚ª‚ ‚é +// 以下フック関数 +// フック対象を呼び出す場合は前後でSTART_HOOK_FUNCTIONとEND_HOOK_FUNCTIONを実行する必要がある HMODULE WINAPI h_LoadLibraryA(LPCSTR lpLibFileName) { @@ -189,7 +190,7 @@ HMODULE WINAPI h_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFla return r; } -// ˆÈ‰ºƒwƒ‹ƒp[ŠÖ” +// 以下ヘルパー関数 BOOL LockThreadLock() { @@ -356,7 +357,7 @@ BOOL HookFunctionInIAT(void* pOriginal, void* pNew) } #endif -// ƒtƒ@ƒCƒ‹‚ð•ÏX•s”\‚ɐݒè +// ファイルを変更不能に設定 HANDLE LockExistingFile(LPCWSTR Filename) { HANDLE hResult; @@ -366,7 +367,7 @@ HANDLE LockExistingFile(LPCWSTR Filename) return hResult; } -// DLL‚̃nƒbƒVƒ…‚ðŒŸõ +// DLLのハッシュを検索 BOOL FindTrustedModuleSHA1Hash(void* pHash) { BOOL bResult; @@ -431,7 +432,7 @@ BOOL VerifyFileSignature_Function(LPCWSTR Filename) return bResult; } -// ƒtƒ@ƒCƒ‹‚̏–¼‚ðŠm”F +// ファイルの署名を確認 BOOL VerifyFileSignature(LPCWSTR Filename) { BOOL bResult; @@ -454,7 +455,7 @@ BOOL VerifyFileSignature(LPCWSTR Filename) return bResult; } -// ƒtƒ@ƒCƒ‹‚̏–¼‚ðƒJƒ^ƒƒOƒtƒ@ƒCƒ‹‚ÅŠm”F +// ファイルの署名をカタログファイルで確認 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename) { BOOL bResult; @@ -496,8 +497,8 @@ BOOL WINAPI GetSHA1HashOfModule_Function(DIGEST_HANDLE refdata, PBYTE pData, DWO return CryptHashData(*(HCRYPTHASH*)refdata, pData, dwLength, 0); } -// ƒ‚ƒWƒ…[ƒ‹‚ÌSHA1ƒnƒbƒVƒ…‚ðŽæ“¾ -// ƒ}ƒjƒtƒFƒXƒgƒtƒ@ƒCƒ‹‚Ìfile—v‘f‚Ìhash‘®«‚ÍŽÀs‰Â”\ƒtƒ@ƒCƒ‹‚̏ꍇ‚ÉImageGetDigestStream‚ÅŽZo‚³‚ê‚é +// モジュールのSHA1ハッシュを取得 +// マニフェストファイルのfile要素のhash属性は実行可能ファイルの場合にImageGetDigestStreamで算出される BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash) { BOOL bResult; @@ -581,14 +582,14 @@ BOOL IsSxsModuleTrusted_Function(LPCWSTR Catalog, LPCWSTR Manifest, LPCWSTR Modu return bResult; } -// ƒTƒCƒhƒoƒCƒTƒCƒhDLL‚ðŠm”F -// ƒpƒX‚Í"%SystemRoot%\WinSxS"ˆÈ‰º‚ð‘z’è -// ˆÈ‰º‚̃tƒ@ƒCƒ‹‚ª‘¶Ý‚·‚é‚à‚Ì‚Æ‚·‚é -// "\xxx\yyy.dll"A"\manifests\xxx.cat"A"\manifests\xxx.manifest"‚̃ZƒbƒgiXP‚Ì‘S‚Ä‚ÌDLLAVistaˆÈ~‚̈ꕔ‚ÌDLLj -// "\xxx\yyy.dll"A"\catalogs\zzz.cat"A"\manifests\xxx.manifest"‚̃ZƒbƒgiVistaˆÈ~‚Ì‚Ù‚Æ‚ñ‚Ç‚ÌDLLj -// –¼‚³‚ꂽƒJƒ^ƒƒOƒtƒ@ƒCƒ‹‚ð—p‚¢‚ă}ƒjƒtƒFƒXƒgƒtƒ@ƒCƒ‹‚ª‰ü₂³‚ê‚Ä‚¢‚È‚¢‚±‚Æ‚ðŠm”F -// ƒnƒbƒVƒ…’l‚Í ƒ}ƒjƒtƒFƒXƒgƒtƒ@ƒCƒ‹‚Ìfile—v‘f‚Ìhash‘®«‚É‹Lq‚³‚ê‚Ä‚¢‚é‚à‚Ì‚ð—p‚¢‚é -// ƒ}ƒjƒtƒFƒXƒgƒtƒ@ƒCƒ‹“à‚ÉSHA1ƒnƒbƒVƒ…’l‚Ì16i”•\‹L‚𒼐ڌŸõ‚µ‚Ä‚¢‚邪Šm—¦“I‚É–â‘è‚È‚µ +// サイドバイサイドDLLを確認 +// パスは"%SystemRoot%\WinSxS"以下を想定 +// 以下のファイルが存在するものとする +// "\xxx\yyy.dll"、"\manifests\xxx.cat"、"\manifests\xxx.manifest"のセット(XPの全てのDLL、Vista以降の一部のDLL) +// "\xxx\yyy.dll"、"\catalogs\zzz.cat"、"\manifests\xxx.manifest"のセット(Vista以降のほとんどのDLL) +// 署名されたカタログファイルを用いてマニフェストファイルが改竄されていないことを確認 +// ハッシュ値は マニフェストファイルのfile要素のhash属性に記述されているものを用いる +// マニフェストファイル内にSHA1ハッシュ値の16進数表記を直接検索しているが確率的に問題なし BOOL IsSxsModuleTrusted(LPCWSTR Filename) { BOOL bResult; @@ -679,7 +680,7 @@ BOOL IsSxsModuleTrusted(LPCWSTR Filename) return bResult; } -// DLL‚ðŠm”F +// DLLを確認 BOOL IsModuleTrusted(LPCWSTR Filename) { BOOL bResult; @@ -712,11 +713,11 @@ BOOL IsModuleTrusted(LPCWSTR Filename) return bResult; } -// kernel32.dll‚ÌLoadLibraryExW‘Š“–‚̊֐” -// ƒhƒLƒ…ƒƒ“ƒg‚ª–³‚¢‚½‚ߏڍׂ͕s–¾ -// ˆê•”‚̃EƒBƒ‹ƒX‘΍ôƒ\ƒtƒgiAvast!“™j‚ªLdrLoadDll‚ðƒtƒbƒN‚µ‚Ä‚¢‚邽‚ßLdrLoadDll‚ð‘‚«Š·‚¦‚é‚ׂ«‚Å‚Í‚È‚¢ -// ƒJ[ƒlƒ‹ƒ‚[ƒh‚̃R[ƒh‚ɑ΂µ‚Ä‚ÍŒø‰Ê‚È‚µ -// SeDebugPrivilege‚ªŽg—p‰Â”\‚ȃ†[ƒU[‚ɑ΂µ‚Ä‚ÍŒø‰Ê‚È‚µ +// kernel32.dllのLoadLibraryExW相当の関数 +// ドキュメントが無いため詳細は不明 +// 一部のウィルス対策ソフト(Avast!等)がLdrLoadDllをフックしているためLdrLoadDllを書き換えるべきではない +// カーネルモードのコードに対しては効果なし +// SeDebugPrivilegeが使用可能なユーザーに対しては効果なし HMODULE System_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { HMODULE r = NULL; @@ -792,7 +793,7 @@ void SetProcessProtectionLevel(DWORD Level) g_ProcessProtectionLevel = Level; } -// ƒtƒ@ƒCƒ‹‚ÌSHA1ƒnƒbƒVƒ…‚ðŽæ“¾ +// ファイルのSHA1ハッシュを取得 BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash) { BOOL bResult; @@ -834,7 +835,7 @@ BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash) return bResult; } -// DLL‚̃nƒbƒVƒ…‚ð“o˜^ +// DLLのハッシュを登録 BOOL RegisterTrustedModuleSHA1Hash(void* pHash) { BOOL bResult; @@ -860,7 +861,7 @@ BOOL RegisterTrustedModuleSHA1Hash(void* pHash) return bResult; } -// DLL‚̃nƒbƒVƒ…‚Ì“o˜^‚ð‰ðœ +// DLLのハッシュの登録を解除 BOOL UnregisterTrustedModuleSHA1Hash(void* pHash) { BOOL bResult; @@ -881,7 +882,7 @@ BOOL UnregisterTrustedModuleSHA1Hash(void* pHash) return bResult; } -// M—Š‚Å‚«‚È‚¢DLL‚ðƒAƒ“ƒ[ƒh +// 信頼できないDLLをアンロード BOOL UnloadUntrustedModule() { BOOL bResult; @@ -946,7 +947,7 @@ BOOL UnloadUntrustedModule() return bResult; } -// ŠÖ”ƒ|ƒCƒ“ƒ^‚ðŽg—p‰Â”\‚ȏó‘Ԃɏ‰Šú‰» +// 関数ポインタを使用可能な状態に初期化 BOOL InitializeLoadLibraryHook() { BOOL bResult; @@ -977,8 +978,8 @@ BOOL InitializeLoadLibraryHook() return bResult; } -// SetWindowsHookEx‘΍ô -// DLL Injection‚³‚ꂽê‡‚͏ã‚Ìh_LoadLibraryŒnŠÖ”‚Ńgƒ‰ƒbƒv‰Â”\ +// SetWindowsHookEx対策 +// DLL Injectionされた場合は上のh_LoadLibrary系関数でトラップ可能 BOOL EnableLoadLibraryHook(BOOL bEnable) { BOOL bResult; @@ -1034,8 +1035,8 @@ BOOL EnableLoadLibraryHook(BOOL bEnable) return bResult; } -// ReadProcessMemoryAWriteProcessMemoryACreateRemoteThread‘΍ô -// TerminateProcess‚Ì‚Ý‹–‰Â +// ReadProcessMemory、WriteProcessMemory、CreateRemoteThread対策 +// TerminateProcessのみ許可 BOOL RestartProtectedProcess(LPCTSTR Keyword) { BOOL bResult; @@ -1089,3 +1090,55 @@ BOOL RestartProtectedProcess(LPCTSTR Keyword) return bResult; } +INT_PTR CALLBACK PasswordEditControlWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch(Msg) + { + case EM_GETPASSWORDCHAR: + break; + case EM_SETPASSWORDCHAR: + break; + default: + return CallWindowProcW(g_PasswordEditControlProc, hWnd, Msg, wParam, lParam); + } + return 0; +} + +BOOL ProtectPasswordEditControl(HWND hWnd) +{ + BOOL bResult; + WCHAR ClassName[MAX_PATH]; + WNDPROC Proc; + bResult = FALSE; + if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT) + { + if(GetClassNameW(hWnd, ClassName, MAX_PATH) > 0) + { + if(_wcsicmp(ClassName, WC_EDITW) == 0) + { + Proc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_WNDPROC); + if(Proc != (WNDPROC)PasswordEditControlWndProc) + { + g_PasswordEditControlProc = Proc; + SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)PasswordEditControlWndProc); + bResult = TRUE; + } + } + } + } + return bResult; +} + +BOOL CALLBACK ProtectAllEditControlsEnumChildProc(HWND hwnd , LPARAM lParam) +{ + ProtectPasswordEditControl(hwnd); + return TRUE; +} + +BOOL ProtectAllEditControls(HWND hWnd) +{ + if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT) + EnumChildWindows(hWnd, ProtectAllEditControlsEnumChildProc, 0); + return TRUE; +} +