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 #define DO_NOT_REPLACE
\r
31 #include "protectprocess.h"
\r
32 #include "mbswrapper.h"
\r
35 #pragma comment(lib, "dbghelp.lib")
\r
38 #ifdef USE_CODE_HOOK
\r
39 #if defined(_M_IX86)
\r
40 #define HOOK_JUMP_CODE_LENGTH 5
\r
41 #elif defined(_M_AMD64)
\r
42 #define HOOK_JUMP_CODE_LENGTH 14
\r
48 BYTE PatchCode[HOOK_JUMP_CODE_LENGTH];
\r
49 BYTE BackupCode[HOOK_JUMP_CODE_LENGTH];
\r
50 } HOOK_JUMP_CODE_PATCH;
\r
53 BOOL LockThreadLock();
\r
54 BOOL UnlockThreadLock();
\r
55 #ifdef USE_CODE_HOOK
\r
56 BOOL HookFunctionInCode(void* pOriginal, void* pNew, HOOK_JUMP_CODE_PATCH* pPatch, BOOL bRestore);
\r
59 BOOL HookFunctionInIAT(void* pOriginal, void* pNew);
\r
61 HANDLE LockExistingFile(LPCWSTR Filename);
\r
62 BOOL FindTrustedModuleSHA1Hash(void* pHash);
\r
63 BOOL VerifyFileSignature(LPCWSTR Filename);
\r
64 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename);
\r
65 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash);
\r
66 BOOL IsModuleTrusted(LPCWSTR Filename);
\r
69 #ifdef USE_CODE_HOOK
\r
70 #define HOOK_FUNCTION_VAR(name) _##name p_##name;HOOK_JUMP_CODE_PATCH c_##name;
\r
73 #define HOOK_FUNCTION_VAR(name) _##name p_##name;
\r
76 #define GET_FUNCTION(h, name) p_##name = (_##name)GetProcAddress(h, #name)
\r
77 // フック対象のコードを置換してフックを開始
\r
78 #define SET_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, FALSE)
\r
79 // フック対象を呼び出す前に対象のコードを復元
\r
80 #define BEGIN_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, TRUE)
\r
81 // フック対象を呼び出した後に対象のコードを置換
\r
82 #define END_HOOK_FUNCTION(name) HookFunctionInCode(p_##name, h_##name, &c_##name, FALSE)
\r
84 HOOK_FUNCTION_VAR(LoadLibraryA)
\r
85 HOOK_FUNCTION_VAR(LoadLibraryW)
\r
86 HOOK_FUNCTION_VAR(LoadLibraryExA)
\r
87 HOOK_FUNCTION_VAR(LoadLibraryExW)
\r
89 typedef NTSTATUS (NTAPI* _LdrLoadDll)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
90 typedef NTSTATUS (NTAPI* _LdrGetDllHandle)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
91 typedef PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)(PVOID);
\r
92 typedef BOOL (WINAPI* _CryptCATAdminCalcHashFromFileHandle)(HANDLE, DWORD*, BYTE*, DWORD);
\r
94 _LdrLoadDll p_LdrLoadDll;
\r
95 _LdrGetDllHandle p_LdrGetDllHandle;
\r
96 _RtlImageNtHeader p_RtlImageNtHeader;
\r
97 _CryptCATAdminCalcHashFromFileHandle p_CryptCATAdminCalcHashFromFileHandle;
\r
99 #define MAX_LOCKED_THREAD 16
\r
100 #define MAX_TRUSTED_FILENAME_TABLE 16
\r
101 #define MAX_TRUSTED_SHA1_HASH_TABLE 16
\r
103 DWORD g_ProcessProtectionLevel;
\r
104 DWORD g_LockedThread[MAX_LOCKED_THREAD];
\r
105 WCHAR* g_pTrustedFilenameTable[MAX_TRUSTED_FILENAME_TABLE];
\r
106 BYTE g_TrustedSHA1HashTable[MAX_TRUSTED_SHA1_HASH_TABLE][20];
\r
107 WNDPROC g_PasswordEditControlProc;
\r
110 // フック対象を呼び出す場合は前後でBEGIN_HOOK_FUNCTIONとEND_HOOK_FUNCTIONを実行する必要がある
\r
112 HMODULE WINAPI h_LoadLibraryA(LPCSTR lpLibFileName)
\r
115 wchar_t* pw0 = NULL;
\r
116 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
117 r = LoadLibraryExW(pw0, NULL, 0);
\r
118 FreeDuplicatedString(pw0);
\r
122 HMODULE WINAPI h_LoadLibraryW(LPCWSTR lpLibFileName)
\r
125 r = LoadLibraryExW(lpLibFileName, NULL, 0);
\r
129 HMODULE WINAPI h_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
132 wchar_t* pw0 = NULL;
\r
133 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
134 r = LoadLibraryExW(pw0, hFile, dwFlags);
\r
135 FreeDuplicatedString(pw0);
\r
139 HMODULE WINAPI h_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
150 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
151 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | 0x00000020 | 0x00000040))
\r
155 if(hModule = System_LoadLibrary(lpLibFileName, NULL, DONT_RESOLVE_DLL_REFERENCES))
\r
158 if(pw0 = AllocateStringW(Length))
\r
160 if(GetModuleFileNameW(hModule, pw0, Length) > 0)
\r
164 if(GetModuleFileNameW(hModule, pw0, Length) + 1 <= Length)
\r
166 lpLibFileName = pw0;
\r
169 Length = Length * 2;
\r
170 FreeDuplicatedString(pw0);
\r
171 pw0 = AllocateStringW(Length);
\r
175 hLock = LockExistingFile(lpLibFileName);
\r
176 FreeLibrary(hModule);
\r
178 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_LOADED) && GetModuleHandleW(lpLibFileName))
\r
185 if(IsModuleTrusted(lpLibFileName))
\r
190 r = System_LoadLibrary(lpLibFileName, hFile, dwFlags);
\r
191 FreeDuplicatedString(pw0);
\r
193 CloseHandle(hLock);
\r
199 BOOL LockThreadLock()
\r
205 ThreadId = GetCurrentThreadId();
\r
207 while(i < MAX_LOCKED_THREAD)
\r
209 if(g_LockedThread[i] == ThreadId)
\r
213 if(i >= MAX_LOCKED_THREAD)
\r
216 while(i < MAX_LOCKED_THREAD)
\r
218 if(g_LockedThread[i] == 0)
\r
220 g_LockedThread[i] = ThreadId;
\r
230 BOOL UnlockThreadLock()
\r
236 ThreadId = GetCurrentThreadId();
\r
238 while(i < MAX_LOCKED_THREAD)
\r
240 if(g_LockedThread[i] == ThreadId)
\r
242 g_LockedThread[i] = 0;
\r
251 #ifdef USE_CODE_HOOK
\r
252 BOOL HookFunctionInCode(void* pOriginal, void* pNew, HOOK_JUMP_CODE_PATCH* pPatch, BOOL bRestore)
\r
256 #if defined(_M_IX86)
\r
265 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
267 memcpy(pPatch->pCode, &pPatch->BackupCode, pPatch->CodeLength);
\r
268 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
276 pCode = (BYTE*)pOriginal;
\r
277 while(pCode[0] == 0xeb)
\r
279 memcpy(&c, pCode + 1, 1);
\r
280 pCode = pCode + 2 + c;
\r
282 if(pCode[0] == 0xe9)
\r
284 pPatch->pCode = pCode + 1;
\r
285 pPatch->CodeLength = 4;
\r
286 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
287 l = (long)pNew - ((long)pCode + 5);
\r
288 memcpy(&pPatch->PatchCode[0], &l, 4);
\r
292 pPatch->pCode = pCode;
\r
293 pPatch->CodeLength = 5;
\r
294 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
295 pPatch->PatchCode[0] = 0xe9;
\r
296 l = (long)pNew - ((long)pCode + 5);
\r
297 memcpy(&pPatch->PatchCode[1], &l, 4);
\r
300 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
302 memcpy(pPatch->pCode, &pPatch->PatchCode, pPatch->CodeLength);
\r
303 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
308 #elif defined(_M_AMD64)
\r
317 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
319 memcpy(pPatch->pCode, &pPatch->BackupCode, pPatch->CodeLength);
\r
320 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
328 pCode = (BYTE*)pOriginal;
\r
329 while(pCode[0] == 0xeb || pCode[0] == 0xe9)
\r
331 if(pCode[0] == 0xeb)
\r
333 memcpy(&c, pCode + 1, 1);
\r
334 pCode = pCode + 2 + c;
\r
338 memcpy(&l, pCode + 1, 4);
\r
339 pCode = pCode + 5 + l;
\r
342 if(pCode[0] == 0xff && pCode[1] == 0x25)
\r
344 memcpy(&l, pCode + 2, 4);
\r
345 pPatch->pCode = pCode + 6 + l;
\r
346 pPatch->CodeLength = 8;
\r
347 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
348 memcpy(&pPatch->PatchCode[0], &pNew, 8);
\r
352 pPatch->pCode = pCode;
\r
353 pPatch->CodeLength = 14;
\r
354 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
355 pPatch->PatchCode[0] = 0xff;
\r
356 pPatch->PatchCode[1] = 0x25;
\r
358 memcpy(&pPatch->PatchCode[2], &l, 4);
\r
359 memcpy(&pPatch->PatchCode[6], &pNew, 8);
\r
362 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
364 memcpy(pPatch->pCode, &pPatch->PatchCode, pPatch->CodeLength);
\r
365 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
375 #ifdef USE_IAT_HOOK
\r
376 BOOL HookFunctionInIAT(void* pOriginal, void* pNew)
\r
382 IMAGE_IMPORT_DESCRIPTOR* piid;
\r
384 IMAGE_THUNK_DATA* pitd;
\r
387 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
389 me.dwSize = sizeof(MODULEENTRY32);
\r
390 if(Module32First(hSnapshot, &me))
\r
395 if(piid = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(me.hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size))
\r
397 while(!bFound && piid->Name != 0)
\r
399 pitd = (IMAGE_THUNK_DATA*)((BYTE*)me.hModule + piid->FirstThunk);
\r
400 while(!bFound && pitd->u1.Function != 0)
\r
402 if((void*)pitd->u1.Function == pOriginal)
\r
405 if(VirtualProtect(&pitd->u1.Function, sizeof(void*), PAGE_EXECUTE_READWRITE, &Protect))
\r
407 memcpy(&pitd->u1.Function, &pNew, sizeof(void*));
\r
408 VirtualProtect(&pitd->u1.Function, sizeof(void*), Protect, &Protect);
\r
418 while(!bFound && Module32Next(hSnapshot, &me));
\r
420 CloseHandle(hSnapshot);
\r
427 HANDLE LockExistingFile(LPCWSTR Filename)
\r
431 if((hResult = CreateFileW(Filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE)
\r
437 BOOL FindTrustedModuleSHA1Hash(void* pHash)
\r
443 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
445 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
455 BOOL VerifyFileSignature_Function(LPCWSTR Filename)
\r
459 PCCERT_CONTEXT pcc;
\r
460 CERT_CHAIN_PARA ccp;
\r
461 CERT_CHAIN_CONTEXT* pccc;
\r
462 CERT_CHAIN_POLICY_PARA ccpp;
\r
463 CERT_CHAIN_POLICY_STATUS ccps;
\r
465 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
468 while(!bResult && (pcc = CertEnumCertificatesInStore(hStore, pcc)))
\r
470 ZeroMemory(&ccp, sizeof(CERT_CHAIN_PARA));
\r
471 ccp.cbSize = sizeof(CERT_CHAIN_PARA);
\r
472 if(CertGetCertificateChain(NULL, pcc, NULL, NULL, &ccp, 0, NULL, &pccc))
\r
474 ZeroMemory(&ccpp, sizeof(CERT_CHAIN_POLICY_PARA));
\r
475 ccpp.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
\r
476 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_EXPIRED)
\r
477 ccpp.dwFlags |= CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG;
\r
478 else if(g_ProcessProtectionLevel & PROCESS_PROTECTION_UNAUTHORIZED)
\r
479 ccpp.dwFlags |= CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
\r
480 ZeroMemory(&ccps, sizeof(CERT_CHAIN_POLICY_STATUS));
\r
481 ccps.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
\r
482 if(CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE, pccc, &ccpp, &ccps))
\r
484 if(ccps.dwError == ERROR_SUCCESS)
\r
490 CertFreeCertificateChain(pccc);
\r
493 while(pcc = CertEnumCertificatesInStore(hStore, pcc))
\r
496 CertCloseStore(hStore, 0);
\r
502 BOOL VerifyFileSignature(LPCWSTR Filename)
\r
505 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
506 WINTRUST_FILE_INFO wfi;
\r
509 ZeroMemory(&wfi, sizeof(WINTRUST_FILE_INFO));
\r
510 wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
\r
511 wfi.pcwszFilePath = Filename;
\r
512 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
513 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
514 wd.dwUIChoice = WTD_UI_NONE;
\r
515 wd.dwUnionChoice = WTD_CHOICE_FILE;
\r
517 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
520 bResult = VerifyFileSignature_Function(Filename);
\r
524 // ファイルの署名をカタログファイルで確認
\r
525 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename)
\r
528 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
529 WINTRUST_CATALOG_INFO wci;
\r
532 if(VerifyFileSignature(Catalog))
\r
534 ZeroMemory(&wci, sizeof(WINTRUST_CATALOG_INFO));
\r
535 wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
\r
536 wci.pcwszCatalogFilePath = Catalog;
\r
537 wci.pcwszMemberFilePath = Filename;
\r
538 if((wci.hMemberFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
540 p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, NULL, 0);
\r
541 if(wci.pbCalculatedFileHash = (BYTE*)malloc(wci.cbCalculatedFileHash))
\r
543 if(p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, wci.pbCalculatedFileHash, 0))
\r
545 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
546 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
547 wd.dwUIChoice = WTD_UI_NONE;
\r
548 wd.dwUnionChoice = WTD_CHOICE_CATALOG;
\r
549 wd.pCatalog = &wci;
\r
550 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
553 free(wci.pbCalculatedFileHash);
\r
555 CloseHandle(wci.hMemberFile);
\r
561 BOOL WINAPI GetSHA1HashOfModule_Function(DIGEST_HANDLE refdata, PBYTE pData, DWORD dwLength)
\r
563 return CryptHashData(*(HCRYPTHASH*)refdata, pData, dwLength, 0);
\r
566 // モジュールのSHA1ハッシュを取得
\r
567 // マニフェストファイルのfile要素のhash属性は実行可能ファイルの場合にImageGetDigestStreamで算出される
\r
568 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash)
\r
576 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
578 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
580 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
582 if(ImageGetDigestStream(hFile, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO, GetSHA1HashOfModule_Function, (DIGEST_HANDLE)&hHash))
\r
585 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
588 CloseHandle(hFile);
\r
590 CryptDestroyHash(hHash);
\r
592 CryptReleaseContext(hProv, 0);
\r
597 BOOL IsSxsModuleTrusted_Function(LPCWSTR Catalog, LPCWSTR Manifest, LPCWSTR Module)
\r
604 static char HexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
\r
611 if(hLock0 = LockExistingFile(Catalog))
\r
613 if(hLock1 = LockExistingFile(Manifest))
\r
615 if(VerifyFileSignatureInCatalog(Catalog, Manifest))
\r
617 if(GetSHA1HashOfModule(Module, &Hash))
\r
619 for(i = 0; i < 20; i++)
\r
621 HashHex[i * 2] = HexTable[(Hash[i] >> 4) & 0x0f];
\r
622 HashHex[i * 2 + 1] = HexTable[Hash[i] & 0x0f];
\r
624 HashHex[i * 2] = '\0';
\r
625 if((hFile = CreateFileW(Manifest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
627 Size = GetFileSize(hFile, NULL);
\r
628 if(pData = (char*)VirtualAlloc(NULL, Size + 1, MEM_COMMIT, PAGE_READWRITE))
\r
630 VirtualLock(pData, Size + 1);
\r
631 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
634 if(strstr(pData, HashHex))
\r
637 VirtualUnlock(pData, Size + 1);
\r
638 VirtualFree(pData, Size + 1, MEM_DECOMMIT);
\r
640 CloseHandle(hFile);
\r
644 CloseHandle(hLock1);
\r
646 CloseHandle(hLock0);
\r
652 // パスは"%SystemRoot%\WinSxS"以下を想定
\r
653 // 以下のファイルが存在するものとする
\r
654 // "\xxx\yyy.dll"、"\manifests\xxx.cat"、"\manifests\xxx.manifest"のセット(XPの全てのDLL、Vista以降の一部のDLL)
\r
655 // "\xxx\yyy.dll"、"\catalogs\zzz.cat"、"\manifests\xxx.manifest"のセット(Vista以降のほとんどのDLL)
\r
656 // 署名されたカタログファイルを用いてマニフェストファイルが改竄されていないことを確認
\r
657 // ハッシュ値は マニフェストファイルのfile要素のhash属性に記述されているものを用いる
\r
658 // マニフェストファイル内にSHA1ハッシュ値の16進数表記を直接検索しているが確率的に問題なし
\r
659 BOOL IsSxsModuleTrusted(LPCWSTR Filename)
\r
670 WIN32_FIND_DATAW wfd;
\r
672 if(pw0 = AllocateStringW(wcslen(Filename) + 1))
\r
674 wcscpy(pw0, Filename);
\r
675 if(p = wcsrchr(pw0, L'\\'))
\r
678 if(p = wcsrchr(pw0, L'\\'))
\r
681 if(pw1 = AllocateStringW(wcslen(p) + 1))
\r
685 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".cat") + 1))
\r
688 wcscat(pw2, L"manifests\\");
\r
690 if(pw3 = AllocateStringW(wcslen(pw2) + wcslen(L".manifest") + 1))
\r
693 wcscat(pw3, L".manifest");
\r
694 wcscat(pw2, L".cat");
\r
695 if(IsSxsModuleTrusted_Function(pw2, pw3, Filename))
\r
697 FreeDuplicatedString(pw3);
\r
699 FreeDuplicatedString(pw2);
\r
703 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"catalogs\\") + 1))
\r
705 if(pw3 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".manifest") + 1))
\r
708 wcscat(pw2, L"catalogs\\");
\r
710 wcscat(pw3, L"manifests\\");
\r
712 wcscat(pw3, L".manifest");
\r
713 if(pw4 = AllocateStringW(wcslen(pw2) + wcslen(L"*.cat") + 1))
\r
716 wcscat(pw4, L"*.cat");
\r
717 if((hFind = FindFirstFileW(pw4, &wfd)) != INVALID_HANDLE_VALUE)
\r
721 if(pw5 = AllocateStringW(wcslen(pw2) + wcslen(wfd.cFileName) + 1))
\r
724 wcscat(pw5, wfd.cFileName);
\r
725 if(IsSxsModuleTrusted_Function(pw5, pw3, Filename))
\r
727 FreeDuplicatedString(pw5);
\r
730 while(!bResult && FindNextFileW(hFind, &wfd));
\r
733 FreeDuplicatedString(pw4);
\r
735 FreeDuplicatedString(pw3);
\r
737 FreeDuplicatedString(pw2);
\r
740 FreeDuplicatedString(pw1);
\r
744 FreeDuplicatedString(pw0);
\r
750 BOOL IsModuleTrusted(LPCWSTR Filename)
\r
755 if(LockThreadLock())
\r
757 if(GetSHA1HashOfFile(Filename, &Hash))
\r
759 if(FindTrustedModuleSHA1Hash(&Hash))
\r
764 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_BUILTIN) && VerifyFileSignature(Filename))
\r
769 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SYSTEM_FILE) && SfcIsFileProtected(NULL, Filename))
\r
774 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SIDE_BY_SIDE) && IsSxsModuleTrusted(Filename))
\r
777 UnlockThreadLock();
\r
782 // kernel32.dllのLoadLibraryExW相当の関数
\r
783 // ドキュメントが無いため詳細は不明
\r
784 // 一部のウィルス対策ソフト(Avast!等)がLdrLoadDllをフックしているためLdrLoadDllを書き換えるべきではない
\r
785 // カーネルモードのコードに対しては効果なし
\r
786 // SeDebugPrivilegeが使用可能なユーザーに対しては効果なし
\r
787 HMODULE System_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
794 us.Length = sizeof(wchar_t) * (USHORT)wcslen(lpLibFileName);
\r
795 us.MaximumLength = sizeof(wchar_t) * ((USHORT)wcslen(lpLibFileName) + 1);
\r
796 us.Buffer = (PWSTR)lpLibFileName;
\r
797 // if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
798 if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040))
\r
800 // if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == STATUS_SUCCESS)
\r
801 if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == 0)
\r
803 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
804 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
805 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
809 // if(dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
\r
810 if(dwFlags & 0x00000040)
\r
811 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
\r
813 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
\r
814 if(hDataFile != INVALID_HANDLE_VALUE)
\r
816 if(hMapping = CreateFileMappingW(hDataFile, NULL, PAGE_READONLY, 0, 0, NULL))
\r
818 if(r = (HMODULE)MapViewOfFileEx(hMapping, FILE_MAP_READ, 0, 0, 0, NULL))
\r
820 if(p_RtlImageNtHeader(r))
\r
821 r = (HMODULE)((size_t)r | 1);
\r
824 UnmapViewOfFile(r);
\r
828 CloseHandle(hMapping);
\r
830 CloseHandle(hDataFile);
\r
834 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
835 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
836 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
840 // if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)))
\r
841 if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040)))
\r
844 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
\r
845 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | 0x00000020))
\r
846 DllFlags |= 0x00000002;
\r
847 // if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == STATUS_SUCCESS)
\r
848 if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == 0)
\r
857 void SetProcessProtectionLevel(DWORD Level)
\r
859 g_ProcessProtectionLevel = Level;
\r
863 BOOL GetSHA1HashOfMemory(const void* pData, DWORD Size, void* pHash)
\r
870 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
872 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
874 if(CryptHashData(hHash, (BYTE*)pData, Size, 0))
\r
877 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
880 CryptDestroyHash(hHash);
\r
882 CryptReleaseContext(hProv, 0);
\r
887 // ファイルのSHA1ハッシュを取得
\r
888 BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash)
\r
896 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
898 Size = GetFileSize(hFile, NULL);
\r
899 if(pData = VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE))
\r
901 VirtualLock(pData, Size);
\r
902 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
904 if(GetSHA1HashOfMemory(pData, Size, pHash))
\r
907 VirtualUnlock(pData, Size);
\r
908 VirtualFree(pData, Size, MEM_DECOMMIT);
\r
910 CloseHandle(hFile);
\r
916 BOOL RegisterTrustedModuleSHA1Hash(void* pHash)
\r
919 BYTE NullHash[20] = {0};
\r
922 if(FindTrustedModuleSHA1Hash(pHash))
\r
927 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
929 if(memcmp(&g_TrustedSHA1HashTable[i], &NullHash, 20) == 0)
\r
931 memcpy(&g_TrustedSHA1HashTable[i], pHash, 20);
\r
942 BOOL UnregisterTrustedModuleSHA1Hash(void* pHash)
\r
945 BYTE NullHash[20] = {0};
\r
949 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
951 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
953 memcpy(&g_TrustedSHA1HashTable[i], &NullHash, 20);
\r
963 BOOL UnloadUntrustedModule()
\r
972 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
975 me.dwSize = sizeof(MODULEENTRY32);
\r
976 if(Module32First(hSnapshot, &me))
\r
981 FreeDuplicatedString(pw0);
\r
982 if(pw0 = AllocateStringW(Length))
\r
984 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
988 if(GetModuleFileNameW(me.hModule, pw0, Length) + 1 <= Length)
\r
990 Length = Length * 2;
\r
991 FreeDuplicatedString(pw0);
\r
992 pw0 = AllocateStringW(Length);
\r
998 if(!IsModuleTrusted(pw0))
\r
1000 if(me.hModule != GetModuleHandleW(NULL))
\r
1002 while(FreeLibrary(me.hModule))
\r
1005 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
1019 while(Module32Next(hSnapshot, &me));
\r
1021 CloseHandle(hSnapshot);
\r
1023 FreeDuplicatedString(pw0);
\r
1027 // 関数ポインタを使用可能な状態に初期化
\r
1028 BOOL InitializeLoadLibraryHook()
\r
1033 if(!(hModule = GetModuleHandleW(L"kernel32.dll")))
\r
1035 if(!(GET_FUNCTION(hModule, LoadLibraryA)))
\r
1037 if(!(GET_FUNCTION(hModule, LoadLibraryW)))
\r
1039 if(!(GET_FUNCTION(hModule, LoadLibraryExA)))
\r
1041 if(!(GET_FUNCTION(hModule, LoadLibraryExW)))
\r
1043 if(!(hModule = GetModuleHandleW(L"ntdll.dll")))
\r
1045 if(!(GET_FUNCTION(hModule, LdrLoadDll)))
\r
1047 if(!(GET_FUNCTION(hModule, LdrGetDllHandle)))
\r
1049 if(!(GET_FUNCTION(hModule, RtlImageNtHeader)))
\r
1051 if(!(hModule = LoadLibraryW(L"wintrust.dll")))
\r
1053 if(!(GET_FUNCTION(hModule, CryptCATAdminCalcHashFromFileHandle)))
\r
1056 ImageGetDigestStream(NULL, 0, NULL, NULL);
\r
1060 // SetWindowsHookEx対策
\r
1061 // DLL Injectionされた場合は上のh_LoadLibrary系関数でトラップ可能
\r
1062 BOOL EnableLoadLibraryHook(BOOL bEnable)
\r
1069 #ifdef USE_CODE_HOOK
\r
1070 if(!SET_HOOK_FUNCTION(LoadLibraryA))
\r
1072 if(!SET_HOOK_FUNCTION(LoadLibraryW))
\r
1074 if(!SET_HOOK_FUNCTION(LoadLibraryExA))
\r
1076 if(!SET_HOOK_FUNCTION(LoadLibraryExW))
\r
1079 #ifdef USE_IAT_HOOK
\r
1080 if(!HookFunctionInIAT(p_LoadLibraryA, h_LoadLibraryA))
\r
1082 if(!HookFunctionInIAT(p_LoadLibraryW, h_LoadLibraryW))
\r
1084 if(!HookFunctionInIAT(p_LoadLibraryExA, h_LoadLibraryExA))
\r
1086 if(!HookFunctionInIAT(p_LoadLibraryExW, h_LoadLibraryExW))
\r
1093 #ifdef USE_CODE_HOOK
\r
1094 if(!BEGIN_HOOK_FUNCTION(LoadLibraryA))
\r
1096 if(!BEGIN_HOOK_FUNCTION(LoadLibraryW))
\r
1098 if(!BEGIN_HOOK_FUNCTION(LoadLibraryExA))
\r
1100 if(!BEGIN_HOOK_FUNCTION(LoadLibraryExW))
\r
1103 #ifdef USE_IAT_HOOK
\r
1104 if(!HookFunctionInIAT(h_LoadLibraryA, p_LoadLibraryA))
\r
1106 if(!HookFunctionInIAT(h_LoadLibraryW, p_LoadLibraryW))
\r
1108 if(!HookFunctionInIAT(h_LoadLibraryExA, p_LoadLibraryExA))
\r
1110 if(!HookFunctionInIAT(h_LoadLibraryExW, p_LoadLibraryExW))
\r
1117 // ReadProcessMemory、WriteProcessMemory、CreateRemoteThread対策
\r
1118 // TerminateProcessのみ許可
\r
1119 BOOL RestartProtectedProcess(LPCTSTR Keyword)
\r
1123 SID_IDENTIFIER_AUTHORITY sia = SECURITY_WORLD_SID_AUTHORITY;
\r
1125 SECURITY_DESCRIPTOR sd;
\r
1126 TCHAR* CommandLine;
\r
1127 SECURITY_ATTRIBUTES sa;
\r
1129 PROCESS_INFORMATION pi;
\r
1131 if(_tcslen(GetCommandLine()) >= _tcslen(Keyword) && _tcscmp(GetCommandLine() + _tcslen(GetCommandLine()) - _tcslen(Keyword), Keyword) == 0)
\r
1133 if(pACL = (ACL*)malloc(sizeof(ACL) + 1024))
\r
1135 if(InitializeAcl(pACL, sizeof(ACL) + 1024, ACL_REVISION))
\r
1137 if(AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID))
\r
1139 if(AddAccessAllowedAce(pACL, ACL_REVISION, PROCESS_TERMINATE, pSID))
\r
1141 if(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
\r
1143 if(SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE))
\r
1145 if(CommandLine = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(GetCommandLine()) + _tcslen(Keyword) + 1)))
\r
1147 _tcscpy(CommandLine, GetCommandLine());
\r
1148 _tcscat(CommandLine, Keyword);
\r
1149 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
1150 sa.lpSecurityDescriptor = &sd;
\r
1151 sa.bInheritHandle = FALSE;
\r
1152 GetStartupInfo(&si);
\r
1153 if(CreateProcess(NULL, CommandLine, &sa, NULL, FALSE, 0, NULL, NULL, &si, &pi))
\r
1155 CloseHandle(pi.hThread);
\r
1156 CloseHandle(pi.hProcess);
\r
1159 free(CommandLine);
\r
1172 INT_PTR CALLBACK PasswordEditControlWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
\r
1176 case EM_GETPASSWORDCHAR:
\r
1178 case EM_SETPASSWORDCHAR:
\r
1181 return CallWindowProcW(g_PasswordEditControlProc, hWnd, Msg, wParam, lParam);
\r
1186 BOOL ProtectPasswordEditControl(HWND hWnd)
\r
1189 WCHAR ClassName[MAX_PATH];
\r
1192 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1194 if(GetClassNameW(hWnd, ClassName, MAX_PATH) > 0)
\r
1196 if(_wcsicmp(ClassName, WC_EDITW) == 0)
\r
1198 Proc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
\r
1199 if(Proc != (WNDPROC)PasswordEditControlWndProc)
\r
1201 g_PasswordEditControlProc = Proc;
\r
1202 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)PasswordEditControlWndProc);
\r
1211 BOOL CALLBACK ProtectAllEditControlsEnumChildProc(HWND hwnd , LPARAM lParam)
\r
1213 ProtectPasswordEditControl(hwnd);
\r
1217 BOOL ProtectAllEditControls(HWND hWnd)
\r
1219 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1220 EnumChildWindows(hWnd, ProtectAllEditControlsEnumChildProc, 0);
\r