2 // Copyright (C) 2011 Suguru Kawamoto
\r
7 // 全ての呼び出しをフック可能だが原理的に二重呼び出しに対応できない
\r
8 #define USE_CODE_HOOK
\r
9 // フック先の関数のインポートアドレステーブルを書き換える
\r
10 // 二重呼び出しが可能だが呼び出し方法によってはフックを回避される
\r
11 //#define USE_IAT_HOOK
\r
17 // フック対象のコードのバックアップ c_%s
\r
20 #include <windows.h>
\r
21 #include <ntsecapi.h>
\r
22 #include <wincrypt.h>
\r
23 #include <wintrust.h>
\r
24 #include <softpub.h>
\r
27 #include <tlhelp32.h>
\r
28 #include <imagehlp.h>
\r
30 #include <dbghelp.h>
\r
33 #define DO_NOT_REPLACE
\r
34 #include "protectprocess.h"
\r
35 #include "mbswrapper.h"
\r
38 #pragma comment(lib, "dbghelp.lib")
\r
41 #ifdef USE_CODE_HOOK
\r
43 #define HOOK_JUMP_CODE_LENGTH 5
\r
44 #elif defined(_AMD64_)
\r
45 #define HOOK_JUMP_CODE_LENGTH 14
\r
49 BOOL LockThreadLock();
\r
50 BOOL UnlockThreadLock();
\r
51 #ifdef USE_CODE_HOOK
\r
52 BOOL HookFunctionInCode(void* pOriginal, void* pNew, void* pBackupCode, BOOL bRestore);
\r
55 BOOL HookFunctionInIAT(void* pOriginal, void* pNew);
\r
57 HANDLE LockExistingFile(LPCWSTR Filename);
\r
58 BOOL FindTrustedModuleSHA1Hash(void* pHash);
\r
59 BOOL VerifyFileSignature(LPCWSTR Filename);
\r
60 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename);
\r
61 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash);
\r
62 BOOL IsModuleTrusted(LPCWSTR Filename);
\r
65 #ifdef USE_CODE_HOOK
\r
66 #define HOOK_FUNCTION_VAR(name) _##name p_##name;BYTE c_##name[HOOK_JUMP_CODE_LENGTH * 2];
\r
69 #define HOOK_FUNCTION_VAR(name) _##name p_##name;
\r
72 #define GET_FUNCTION(h, name) p_##name = (_##name)GetProcAddress(h, #name)
\r
73 // フック対象のコードを置換してフックを開始
\r
74 #define SET_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, FALSE)
\r
75 // フック対象を呼び出す前に対象のコードを復元
\r
76 #define BEGIN_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, TRUE)
\r
77 // フック対象を呼び出した後に対象のコードを置換
\r
78 #define END_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, NULL, FALSE)
\r
80 HOOK_FUNCTION_VAR(LoadLibraryA)
\r
81 HOOK_FUNCTION_VAR(LoadLibraryW)
\r
82 HOOK_FUNCTION_VAR(LoadLibraryExA)
\r
83 HOOK_FUNCTION_VAR(LoadLibraryExW)
\r
85 typedef NTSTATUS (NTAPI* _LdrLoadDll)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
86 typedef NTSTATUS (NTAPI* _LdrGetDllHandle)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
87 typedef PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)(PVOID);
\r
88 typedef BOOL (WINAPI* _CryptCATAdminCalcHashFromFileHandle)(HANDLE, DWORD*, BYTE*, DWORD);
\r
90 _LdrLoadDll p_LdrLoadDll;
\r
91 _LdrGetDllHandle p_LdrGetDllHandle;
\r
92 _RtlImageNtHeader p_RtlImageNtHeader;
\r
93 _CryptCATAdminCalcHashFromFileHandle p_CryptCATAdminCalcHashFromFileHandle;
\r
95 #define MAX_LOCKED_THREAD 16
\r
96 #define MAX_TRUSTED_FILENAME_TABLE 16
\r
97 #define MAX_TRUSTED_SHA1_HASH_TABLE 16
\r
99 DWORD g_ProcessProtectionLevel;
\r
100 DWORD g_LockedThread[MAX_LOCKED_THREAD];
\r
101 WCHAR* g_pTrustedFilenameTable[MAX_TRUSTED_FILENAME_TABLE];
\r
102 BYTE g_TrustedSHA1HashTable[MAX_TRUSTED_SHA1_HASH_TABLE][20];
\r
103 WNDPROC g_PasswordEditControlProc;
\r
106 // フック対象を呼び出す場合は前後でBEGIN_HOOK_FUNCTIONとEND_HOOK_FUNCTIONを実行する必要がある
\r
108 HMODULE WINAPI h_LoadLibraryA(LPCSTR lpLibFileName)
\r
111 wchar_t* pw0 = NULL;
\r
112 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
113 r = LoadLibraryExW(pw0, NULL, 0);
\r
114 FreeDuplicatedString(pw0);
\r
118 HMODULE WINAPI h_LoadLibraryW(LPCWSTR lpLibFileName)
\r
121 r = LoadLibraryExW(lpLibFileName, NULL, 0);
\r
125 HMODULE WINAPI h_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
128 wchar_t* pw0 = NULL;
\r
129 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
130 r = LoadLibraryExW(pw0, hFile, dwFlags);
\r
131 FreeDuplicatedString(pw0);
\r
135 HMODULE WINAPI h_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
146 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
147 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | 0x00000020 | 0x00000040))
\r
151 if(hModule = System_LoadLibrary(lpLibFileName, NULL, DONT_RESOLVE_DLL_REFERENCES))
\r
154 if(pw0 = AllocateStringW(Length))
\r
156 if(GetModuleFileNameW(hModule, pw0, Length) > 0)
\r
160 if(GetModuleFileNameW(hModule, pw0, Length) + 1 <= Length)
\r
162 lpLibFileName = pw0;
\r
165 Length = Length * 2;
\r
166 FreeDuplicatedString(pw0);
\r
167 pw0 = AllocateStringW(Length);
\r
171 hLock = LockExistingFile(lpLibFileName);
\r
172 FreeLibrary(hModule);
\r
174 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_LOADED) && GetModuleHandleW(lpLibFileName))
\r
181 if(IsModuleTrusted(lpLibFileName))
\r
186 r = System_LoadLibrary(lpLibFileName, hFile, dwFlags);
\r
187 FreeDuplicatedString(pw0);
\r
189 CloseHandle(hLock);
\r
195 BOOL LockThreadLock()
\r
201 ThreadId = GetCurrentThreadId();
\r
203 while(i < MAX_LOCKED_THREAD)
\r
205 if(g_LockedThread[i] == ThreadId)
\r
209 if(i >= MAX_LOCKED_THREAD)
\r
212 while(i < MAX_LOCKED_THREAD)
\r
214 if(g_LockedThread[i] == 0)
\r
216 g_LockedThread[i] = ThreadId;
\r
226 BOOL UnlockThreadLock()
\r
232 ThreadId = GetCurrentThreadId();
\r
234 while(i < MAX_LOCKED_THREAD)
\r
236 if(g_LockedThread[i] == ThreadId)
\r
238 g_LockedThread[i] = 0;
\r
247 #ifdef USE_CODE_HOOK
\r
248 BOOL HookFunctionInCode(void* pOriginal, void* pNew, void* pBackupCode, BOOL bRestore)
\r
254 BYTE JumpCode[HOOK_JUMP_CODE_LENGTH] = {0xe9, 0x00, 0x00, 0x00, 0x00};
\r
257 Relative = (size_t)pNew - (size_t)pOriginal - HOOK_JUMP_CODE_LENGTH;
\r
258 memcpy(&JumpCode[1], &Relative, 4);
\r
261 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
263 memcpy(pOriginal, pBackupCode, HOOK_JUMP_CODE_LENGTH);
\r
264 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
271 memcpy(pBackupCode, pOriginal, HOOK_JUMP_CODE_LENGTH);
\r
272 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
274 memcpy(pOriginal, &JumpCode, HOOK_JUMP_CODE_LENGTH);
\r
275 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
280 #elif defined(_AMD64_)
\r
282 BYTE JumpCode[HOOK_JUMP_CODE_LENGTH] = {0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
285 Absolute = (size_t)pNew;
\r
286 memcpy(&JumpCode[6], &Absolute, 8);
\r
290 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
292 memcpy(pOriginal, pBackupCode, HOOK_JUMP_CODE_LENGTH);
\r
293 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
300 memcpy(pBackupCode, pOriginal, HOOK_JUMP_CODE_LENGTH);
\r
301 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
303 memcpy(pOriginal, &JumpCode, HOOK_JUMP_CODE_LENGTH);
\r
304 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
314 #ifdef USE_IAT_HOOK
\r
315 BOOL HookFunctionInIAT(void* pOriginal, void* pNew)
\r
321 IMAGE_IMPORT_DESCRIPTOR* piid;
\r
323 IMAGE_THUNK_DATA* pitd;
\r
326 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
328 me.dwSize = sizeof(MODULEENTRY32);
\r
329 if(Module32First(hSnapshot, &me))
\r
334 if(piid = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(me.hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size))
\r
336 while(!bFound && piid->Name != 0)
\r
338 pitd = (IMAGE_THUNK_DATA*)((BYTE*)me.hModule + piid->FirstThunk);
\r
339 while(!bFound && pitd->u1.Function != 0)
\r
341 if((void*)pitd->u1.Function == pOriginal)
\r
344 if(VirtualProtect(&pitd->u1.Function, sizeof(void*), PAGE_EXECUTE_READWRITE, &Protect))
\r
346 memcpy(&pitd->u1.Function, &pNew, sizeof(void*));
\r
347 VirtualProtect(&pitd->u1.Function, sizeof(void*), Protect, &Protect);
\r
357 while(!bFound && Module32Next(hSnapshot, &me));
\r
359 CloseHandle(hSnapshot);
\r
366 HANDLE LockExistingFile(LPCWSTR Filename)
\r
370 if((hResult = CreateFileW(Filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE)
\r
376 BOOL FindTrustedModuleSHA1Hash(void* pHash)
\r
382 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
384 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
394 BOOL VerifyFileSignature_Function(LPCWSTR Filename)
\r
398 PCCERT_CONTEXT pcc;
\r
399 CERT_CHAIN_PARA ccp;
\r
400 CERT_CHAIN_CONTEXT* pccc;
\r
401 CERT_CHAIN_POLICY_PARA ccpp;
\r
402 CERT_CHAIN_POLICY_STATUS ccps;
\r
404 if(CryptQueryObject(CERT_QUERY_OBJECT_FILE, Filename, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, NULL, &hStore, NULL, NULL))
\r
407 while(!bResult && (pcc = CertEnumCertificatesInStore(hStore, pcc)))
\r
409 ZeroMemory(&ccp, sizeof(CERT_CHAIN_PARA));
\r
410 ccp.cbSize = sizeof(CERT_CHAIN_PARA);
\r
411 if(CertGetCertificateChain(NULL, pcc, NULL, NULL, &ccp, 0, NULL, &pccc))
\r
413 ZeroMemory(&ccpp, sizeof(CERT_CHAIN_POLICY_PARA));
\r
414 ccpp.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
\r
415 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_EXPIRED)
\r
416 ccpp.dwFlags |= CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG;
\r
417 else if(g_ProcessProtectionLevel & PROCESS_PROTECTION_UNAUTHORIZED)
\r
418 ccpp.dwFlags |= CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
\r
419 ZeroMemory(&ccps, sizeof(CERT_CHAIN_POLICY_STATUS));
\r
420 ccps.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
\r
421 if(CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE, pccc, &ccpp, &ccps))
\r
423 if(ccps.dwError == ERROR_SUCCESS)
\r
429 CertFreeCertificateChain(pccc);
\r
432 while(pcc = CertEnumCertificatesInStore(hStore, pcc))
\r
435 CertCloseStore(hStore, 0);
\r
441 BOOL VerifyFileSignature(LPCWSTR Filename)
\r
444 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
445 WINTRUST_FILE_INFO wfi;
\r
448 ZeroMemory(&wfi, sizeof(WINTRUST_FILE_INFO));
\r
449 wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
\r
450 wfi.pcwszFilePath = Filename;
\r
451 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
452 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
453 wd.dwUIChoice = WTD_UI_NONE;
\r
454 wd.dwUnionChoice = WTD_CHOICE_FILE;
\r
456 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
459 bResult = VerifyFileSignature_Function(Filename);
\r
463 // ファイルの署名をカタログファイルで確認
\r
464 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename)
\r
467 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
468 WINTRUST_CATALOG_INFO wci;
\r
471 if(VerifyFileSignature(Catalog))
\r
473 ZeroMemory(&wci, sizeof(WINTRUST_CATALOG_INFO));
\r
474 wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
\r
475 wci.pcwszCatalogFilePath = Catalog;
\r
476 wci.pcwszMemberFilePath = Filename;
\r
477 if((wci.hMemberFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
479 p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, NULL, 0);
\r
480 if(wci.pbCalculatedFileHash = (BYTE*)malloc(wci.cbCalculatedFileHash))
\r
482 if(p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, wci.pbCalculatedFileHash, 0))
\r
484 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
485 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
486 wd.dwUIChoice = WTD_UI_NONE;
\r
487 wd.dwUnionChoice = WTD_CHOICE_CATALOG;
\r
488 wd.pCatalog = &wci;
\r
489 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
492 free(wci.pbCalculatedFileHash);
\r
494 CloseHandle(wci.hMemberFile);
\r
500 BOOL WINAPI GetSHA1HashOfModule_Function(DIGEST_HANDLE refdata, PBYTE pData, DWORD dwLength)
\r
502 return CryptHashData(*(HCRYPTHASH*)refdata, pData, dwLength, 0);
\r
505 // モジュールのSHA1ハッシュを取得
\r
506 // マニフェストファイルのfile要素のhash属性は実行可能ファイルの場合にImageGetDigestStreamで算出される
\r
507 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash)
\r
515 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
517 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
519 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
521 if(ImageGetDigestStream(hFile, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO, GetSHA1HashOfModule_Function, (DIGEST_HANDLE)&hHash))
\r
524 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
527 CloseHandle(hFile);
\r
529 CryptDestroyHash(hHash);
\r
531 CryptReleaseContext(hProv, 0);
\r
536 BOOL IsSxsModuleTrusted_Function(LPCWSTR Catalog, LPCWSTR Manifest, LPCWSTR Module)
\r
543 static char HexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
\r
550 if(hLock0 = LockExistingFile(Catalog))
\r
552 if(hLock1 = LockExistingFile(Manifest))
\r
554 if(VerifyFileSignatureInCatalog(Catalog, Manifest))
\r
556 if(GetSHA1HashOfModule(Module, &Hash))
\r
558 for(i = 0; i < 20; i++)
\r
560 HashHex[i * 2] = HexTable[(Hash[i] >> 4) & 0x0f];
\r
561 HashHex[i * 2 + 1] = HexTable[Hash[i] & 0x0f];
\r
563 HashHex[i * 2] = '\0';
\r
564 if((hFile = CreateFileW(Manifest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
566 Size = GetFileSize(hFile, NULL);
\r
567 if(pData = (char*)VirtualAlloc(NULL, Size + 1, MEM_COMMIT, PAGE_READWRITE))
\r
569 VirtualLock(pData, Size + 1);
\r
570 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
573 if(strstr(pData, HashHex))
\r
576 VirtualUnlock(pData, Size + 1);
\r
577 VirtualFree(pData, Size + 1, MEM_DECOMMIT);
\r
579 CloseHandle(hFile);
\r
583 CloseHandle(hLock1);
\r
585 CloseHandle(hLock0);
\r
591 // パスは"%SystemRoot%\WinSxS"以下を想定
\r
592 // 以下のファイルが存在するものとする
\r
593 // "\xxx\yyy.dll"、"\manifests\xxx.cat"、"\manifests\xxx.manifest"のセット(XPの全てのDLL、Vista以降の一部のDLL)
\r
594 // "\xxx\yyy.dll"、"\catalogs\zzz.cat"、"\manifests\xxx.manifest"のセット(Vista以降のほとんどのDLL)
\r
595 // 署名されたカタログファイルを用いてマニフェストファイルが改竄されていないことを確認
\r
596 // ハッシュ値は マニフェストファイルのfile要素のhash属性に記述されているものを用いる
\r
597 // マニフェストファイル内にSHA1ハッシュ値の16進数表記を直接検索しているが確率的に問題なし
\r
598 BOOL IsSxsModuleTrusted(LPCWSTR Filename)
\r
609 WIN32_FIND_DATAW wfd;
\r
611 if(pw0 = AllocateStringW(wcslen(Filename) + 1))
\r
613 wcscpy(pw0, Filename);
\r
614 if(p = wcsrchr(pw0, L'\\'))
\r
617 if(p = wcsrchr(pw0, L'\\'))
\r
620 if(pw1 = AllocateStringW(wcslen(p) + 1))
\r
624 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".cat") + 1))
\r
627 wcscat(pw2, L"manifests\\");
\r
629 if(pw3 = AllocateStringW(wcslen(pw2) + wcslen(L".manifest") + 1))
\r
632 wcscat(pw3, L".manifest");
\r
633 wcscat(pw2, L".cat");
\r
634 if(IsSxsModuleTrusted_Function(pw2, pw3, Filename))
\r
636 FreeDuplicatedString(pw3);
\r
638 FreeDuplicatedString(pw2);
\r
642 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"catalogs\\") + 1))
\r
644 if(pw3 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".manifest") + 1))
\r
647 wcscat(pw2, L"catalogs\\");
\r
649 wcscat(pw3, L"manifests\\");
\r
651 wcscat(pw3, L".manifest");
\r
652 if(pw4 = AllocateStringW(wcslen(pw2) + wcslen(L"*.cat") + 1))
\r
655 wcscat(pw4, L"*.cat");
\r
656 if((hFind = FindFirstFileW(pw4, &wfd)) != INVALID_HANDLE_VALUE)
\r
660 if(pw5 = AllocateStringW(wcslen(pw2) + wcslen(wfd.cFileName) + 1))
\r
663 wcscat(pw5, wfd.cFileName);
\r
664 if(IsSxsModuleTrusted_Function(pw5, pw3, Filename))
\r
666 FreeDuplicatedString(pw5);
\r
669 while(!bResult && FindNextFileW(hFind, &wfd));
\r
672 FreeDuplicatedString(pw4);
\r
674 FreeDuplicatedString(pw3);
\r
676 FreeDuplicatedString(pw2);
\r
679 FreeDuplicatedString(pw1);
\r
683 FreeDuplicatedString(pw0);
\r
689 BOOL IsModuleTrusted(LPCWSTR Filename)
\r
694 if(LockThreadLock())
\r
696 if(GetSHA1HashOfFile(Filename, &Hash))
\r
698 if(FindTrustedModuleSHA1Hash(&Hash))
\r
703 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_BUILTIN) && VerifyFileSignature(Filename))
\r
708 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SYSTEM_FILE) && SfcIsFileProtected(NULL, Filename))
\r
713 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SIDE_BY_SIDE) && IsSxsModuleTrusted(Filename))
\r
716 UnlockThreadLock();
\r
721 // kernel32.dllのLoadLibraryExW相当の関数
\r
722 // ドキュメントが無いため詳細は不明
\r
723 // 一部のウィルス対策ソフト(Avast!等)がLdrLoadDllをフックしているためLdrLoadDllを書き換えるべきではない
\r
724 // カーネルモードのコードに対しては効果なし
\r
725 // SeDebugPrivilegeが使用可能なユーザーに対しては効果なし
\r
726 HMODULE System_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
733 us.Length = sizeof(wchar_t) * wcslen(lpLibFileName);
\r
734 us.MaximumLength = sizeof(wchar_t) * (wcslen(lpLibFileName) + 1);
\r
735 us.Buffer = (PWSTR)lpLibFileName;
\r
736 // if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
737 if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040))
\r
739 // if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == STATUS_SUCCESS)
\r
740 if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == 0)
\r
742 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
743 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
744 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
748 // if(dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
\r
749 if(dwFlags & 0x00000040)
\r
750 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
\r
752 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
\r
753 if(hDataFile != INVALID_HANDLE_VALUE)
\r
755 if(hMapping = CreateFileMappingW(hDataFile, NULL, PAGE_READONLY, 0, 0, NULL))
\r
757 if(r = (HMODULE)MapViewOfFileEx(hMapping, FILE_MAP_READ, 0, 0, 0, NULL))
\r
759 if(p_RtlImageNtHeader(r))
\r
760 r = (HMODULE)((size_t)r | 1);
\r
763 UnmapViewOfFile(r);
\r
767 CloseHandle(hMapping);
\r
769 CloseHandle(hDataFile);
\r
773 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
774 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
775 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
779 // if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)))
\r
780 if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040)))
\r
783 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
\r
784 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | 0x00000020))
\r
785 DllFlags |= 0x00000002;
\r
786 // if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == STATUS_SUCCESS)
\r
787 if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == 0)
\r
796 void SetProcessProtectionLevel(DWORD Level)
\r
798 g_ProcessProtectionLevel = Level;
\r
801 // ファイルのSHA1ハッシュを取得
\r
802 BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash)
\r
812 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
814 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
816 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
818 Size = GetFileSize(hFile, NULL);
\r
819 if(pData = VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE))
\r
821 VirtualLock(pData, Size);
\r
822 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
824 if(CryptHashData(hHash, (BYTE*)pData, Size, 0))
\r
827 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
831 VirtualUnlock(pData, Size);
\r
832 VirtualFree(pData, Size, MEM_DECOMMIT);
\r
834 CloseHandle(hFile);
\r
836 CryptDestroyHash(hHash);
\r
838 CryptReleaseContext(hProv, 0);
\r
844 BOOL RegisterTrustedModuleSHA1Hash(void* pHash)
\r
847 BYTE NullHash[20] = {0};
\r
850 if(FindTrustedModuleSHA1Hash(pHash))
\r
855 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
857 if(memcmp(&g_TrustedSHA1HashTable[i], &NullHash, 20) == 0)
\r
859 memcpy(&g_TrustedSHA1HashTable[i], pHash, 20);
\r
870 BOOL UnregisterTrustedModuleSHA1Hash(void* pHash)
\r
873 BYTE NullHash[20] = {0};
\r
877 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
879 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
881 memcpy(&g_TrustedSHA1HashTable[i], &NullHash, 20);
\r
891 BOOL UnloadUntrustedModule()
\r
900 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
903 me.dwSize = sizeof(MODULEENTRY32);
\r
904 if(Module32First(hSnapshot, &me))
\r
909 FreeDuplicatedString(pw0);
\r
910 if(pw0 = AllocateStringW(Length))
\r
912 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
916 if(GetModuleFileNameW(me.hModule, pw0, Length) + 1 <= Length)
\r
918 Length = Length * 2;
\r
919 FreeDuplicatedString(pw0);
\r
920 pw0 = AllocateStringW(Length);
\r
926 if(!IsModuleTrusted(pw0))
\r
928 if(me.hModule != GetModuleHandleW(NULL))
\r
930 while(FreeLibrary(me.hModule))
\r
933 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
947 while(Module32Next(hSnapshot, &me));
\r
949 CloseHandle(hSnapshot);
\r
951 FreeDuplicatedString(pw0);
\r
955 // 関数ポインタを使用可能な状態に初期化
\r
956 BOOL InitializeLoadLibraryHook()
\r
961 if(!(hModule = GetModuleHandleW(L"kernel32.dll")))
\r
963 if(!(GET_FUNCTION(hModule, LoadLibraryA)))
\r
965 if(!(GET_FUNCTION(hModule, LoadLibraryW)))
\r
967 if(!(GET_FUNCTION(hModule, LoadLibraryExA)))
\r
969 if(!(GET_FUNCTION(hModule, LoadLibraryExW)))
\r
971 if(!(hModule = GetModuleHandleW(L"ntdll.dll")))
\r
973 if(!(GET_FUNCTION(hModule, LdrLoadDll)))
\r
975 if(!(GET_FUNCTION(hModule, LdrGetDllHandle)))
\r
977 if(!(GET_FUNCTION(hModule, RtlImageNtHeader)))
\r
979 if(!(hModule = LoadLibraryW(L"wintrust.dll")))
\r
981 if(!(GET_FUNCTION(hModule, CryptCATAdminCalcHashFromFileHandle)))
\r
984 ImageGetDigestStream(NULL, 0, NULL, NULL);
\r
988 // SetWindowsHookEx対策
\r
989 // DLL Injectionされた場合は上のh_LoadLibrary系関数でトラップ可能
\r
990 BOOL EnableLoadLibraryHook(BOOL bEnable)
\r
997 #ifdef USE_CODE_HOOK
\r
998 if(!SET_HOOK_FUNCTION(LoadLibraryA))
\r
1000 if(!SET_HOOK_FUNCTION(LoadLibraryW))
\r
1002 if(!SET_HOOK_FUNCTION(LoadLibraryExA))
\r
1004 if(!SET_HOOK_FUNCTION(LoadLibraryExW))
\r
1007 #ifdef USE_IAT_HOOK
\r
1008 if(!HookFunctionInIAT(p_LoadLibraryA, h_LoadLibraryA))
\r
1010 if(!HookFunctionInIAT(p_LoadLibraryW, h_LoadLibraryW))
\r
1012 if(!HookFunctionInIAT(p_LoadLibraryExA, h_LoadLibraryExA))
\r
1014 if(!HookFunctionInIAT(p_LoadLibraryExW, h_LoadLibraryExW))
\r
1021 #ifdef USE_CODE_HOOK
\r
1022 if(!BEGIN_HOOK_FUNCTION(LoadLibraryA))
\r
1024 if(!BEGIN_HOOK_FUNCTION(LoadLibraryW))
\r
1026 if(!BEGIN_HOOK_FUNCTION(LoadLibraryExA))
\r
1028 if(!BEGIN_HOOK_FUNCTION(LoadLibraryExW))
\r
1031 #ifdef USE_IAT_HOOK
\r
1032 if(!HookFunctionInIAT(h_LoadLibraryA, p_LoadLibraryA))
\r
1034 if(!HookFunctionInIAT(h_LoadLibraryW, p_LoadLibraryW))
\r
1036 if(!HookFunctionInIAT(h_LoadLibraryExA, p_LoadLibraryExA))
\r
1038 if(!HookFunctionInIAT(h_LoadLibraryExW, p_LoadLibraryExW))
\r
1045 // ReadProcessMemory、WriteProcessMemory、CreateRemoteThread対策
\r
1046 // TerminateProcessのみ許可
\r
1047 BOOL RestartProtectedProcess(LPCTSTR Keyword)
\r
1051 SID_IDENTIFIER_AUTHORITY sia = SECURITY_WORLD_SID_AUTHORITY;
\r
1053 SECURITY_DESCRIPTOR sd;
\r
1054 TCHAR* CommandLine;
\r
1055 SECURITY_ATTRIBUTES sa;
\r
1057 PROCESS_INFORMATION pi;
\r
1059 if(_tcslen(GetCommandLine()) >= _tcslen(Keyword) && _tcscmp(GetCommandLine() + _tcslen(GetCommandLine()) - _tcslen(Keyword), Keyword) == 0)
\r
1061 if(pACL = (ACL*)malloc(sizeof(ACL) + 1024))
\r
1063 if(InitializeAcl(pACL, sizeof(ACL) + 1024, ACL_REVISION))
\r
1065 if(AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID))
\r
1067 if(AddAccessAllowedAce(pACL, ACL_REVISION, PROCESS_TERMINATE, pSID))
\r
1069 if(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
\r
1071 if(SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE))
\r
1073 if(CommandLine = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(GetCommandLine()) + _tcslen(Keyword) + 1)))
\r
1075 _tcscpy(CommandLine, GetCommandLine());
\r
1076 _tcscat(CommandLine, Keyword);
\r
1077 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
1078 sa.lpSecurityDescriptor = &sd;
\r
1079 sa.bInheritHandle = FALSE;
\r
1080 GetStartupInfo(&si);
\r
1081 if(CreateProcess(NULL, CommandLine, &sa, NULL, FALSE, 0, NULL, NULL, &si, &pi))
\r
1083 CloseHandle(pi.hThread);
\r
1084 CloseHandle(pi.hProcess);
\r
1087 free(CommandLine);
\r
1100 INT_PTR CALLBACK PasswordEditControlWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
\r
1104 case EM_GETPASSWORDCHAR:
\r
1106 case EM_SETPASSWORDCHAR:
\r
1109 return CallWindowProcW(g_PasswordEditControlProc, hWnd, Msg, wParam, lParam);
\r
1114 BOOL ProtectPasswordEditControl(HWND hWnd)
\r
1117 WCHAR ClassName[MAX_PATH];
\r
1120 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1122 if(GetClassNameW(hWnd, ClassName, MAX_PATH) > 0)
\r
1124 if(_wcsicmp(ClassName, WC_EDITW) == 0)
\r
1126 Proc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
\r
1127 if(Proc != (WNDPROC)PasswordEditControlWndProc)
\r
1129 g_PasswordEditControlProc = Proc;
\r
1130 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)PasswordEditControlWndProc);
\r
1139 BOOL CALLBACK ProtectAllEditControlsEnumChildProc(HWND hwnd , LPARAM lParam)
\r
1141 ProtectPasswordEditControl(hwnd);
\r
1145 BOOL ProtectAllEditControls(HWND hWnd)
\r
1147 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1148 EnumChildWindows(hWnd, ProtectAllEditControlsEnumChildProc, 0);
\r