2 // Copyright (C) 2011 Suguru Kawamoto
\r
7 #define USE_CODE_HOOK
\r
8 // フック先の関数のインポートアドレステーブルを書き換える
\r
9 //#define USE_IAT_HOOK
\r
12 #include <windows.h>
\r
13 #include <ntsecapi.h>
\r
14 #include <wincrypt.h>
\r
15 #include <wintrust.h>
\r
16 #include <softpub.h>
\r
19 #include <tlhelp32.h>
\r
20 #include <imagehlp.h>
\r
22 #define DO_NOT_REPLACE
\r
23 #include "protectprocess.h"
\r
24 #include "mbswrapper.h"
\r
27 #pragma comment(lib, "dbghelp.lib")
\r
30 #ifdef USE_CODE_HOOK
\r
31 #if defined(_M_IX86)
\r
32 //#define HOOK_JUMP_CODE_LENGTH 5
\r
33 #define HOOK_JUMP_CODE_LENGTH 7
\r
34 #elif defined(_M_AMD64)
\r
35 #define HOOK_JUMP_CODE_LENGTH 14
\r
41 BYTE PatchCode[HOOK_JUMP_CODE_LENGTH];
\r
42 BYTE BackupCode[HOOK_JUMP_CODE_LENGTH];
\r
43 } HOOK_JUMP_CODE_PATCH;
\r
54 #ifdef USE_CODE_HOOK
\r
55 HOOK_JUMP_CODE_PATCH Patch;
\r
57 } HOOK_FUNCTION_INFO;
\r
59 #define HOOK_INITIALIZED 0x00000001
\r
60 #define HOOK_ENABLED 0x00000002
\r
61 #define HOOK_USE_GETMODULEHANDLE 0x00000004
\r
62 #define HOOK_USE_LOADLIBRARY 0x00000008
\r
63 #define HOOK_USE_GETPROCADDRESS 0x00000010
\r
65 typedef HMODULE (WINAPI* _LoadLibraryA)(LPCSTR);
\r
66 typedef HMODULE (WINAPI* _LoadLibraryW)(LPCWSTR);
\r
67 typedef HMODULE (WINAPI* _LoadLibraryExA)(LPCSTR, HANDLE, DWORD);
\r
68 typedef HMODULE (WINAPI* _LoadLibraryExW)(LPCWSTR, HANDLE, DWORD);
\r
70 HOOK_FUNCTION_INFO g_LoadLibraryA;
\r
71 HOOK_FUNCTION_INFO g_LoadLibraryW;
\r
72 HOOK_FUNCTION_INFO g_LoadLibraryExA;
\r
73 HOOK_FUNCTION_INFO g_LoadLibraryExW;
\r
75 typedef NTSTATUS (NTAPI* _LdrLoadDll)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
76 typedef NTSTATUS (NTAPI* _LdrGetDllHandle)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
\r
77 typedef PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)(PVOID);
\r
78 typedef BOOL (WINAPI* _CryptCATAdminCalcHashFromFileHandle)(HANDLE, DWORD*, BYTE*, DWORD);
\r
80 _LdrLoadDll p_LdrLoadDll;
\r
81 _LdrGetDllHandle p_LdrGetDllHandle;
\r
82 _RtlImageNtHeader p_RtlImageNtHeader;
\r
83 _CryptCATAdminCalcHashFromFileHandle p_CryptCATAdminCalcHashFromFileHandle;
\r
85 #define MAX_LOCKED_THREAD 16
\r
86 #define MAX_TRUSTED_FILENAME_TABLE 16
\r
87 #define MAX_TRUSTED_SHA1_HASH_TABLE 16
\r
89 DWORD g_ProcessProtectionLevel;
\r
90 DWORD g_LockedThread[MAX_LOCKED_THREAD];
\r
91 WCHAR* g_pTrustedFilenameTable[MAX_TRUSTED_FILENAME_TABLE];
\r
92 BYTE g_TrustedSHA1HashTable[MAX_TRUSTED_SHA1_HASH_TABLE][20];
\r
93 WNDPROC g_PasswordEditControlProc;
\r
95 #ifdef USE_CODE_HOOK
\r
96 BOOL HookFunctionInCode(void* pProc, void* pHook, void** ppUnhook, HOOK_JUMP_CODE_PATCH* pPatch, BOOL bRestore)
\r
100 #if defined(_M_IX86)
\r
109 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
111 memcpy(pPatch->pCode, &pPatch->BackupCode, pPatch->CodeLength);
\r
112 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
113 FlushInstructionCache(GetCurrentProcess(), pPatch->pCode, pPatch->CodeLength);
\r
121 pCode = (BYTE*)pProc;
\r
122 while(pCode[0] == 0xeb)
\r
124 memcpy(&c, pCode + 1, 1);
\r
125 pCode = pCode + 2 + c;
\r
127 if(pCode[0] == 0x8b && pCode[1] == 0xff)
\r
130 pPatch->pCode = pCode;
\r
131 pPatch->CodeLength = 7;
\r
132 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
133 pPatch->PatchCode[0] = 0xe9;
\r
134 l = (long)pHook - ((long)pCode + 5);
\r
135 memcpy(&pPatch->PatchCode[1], &l, 4);
\r
136 pPatch->PatchCode[5] = 0xeb;
\r
137 pPatch->PatchCode[6] = 0xf9;
\r
138 *ppUnhook = pCode + 7;
\r
140 else if(pCode[0] == 0xe9)
\r
142 pPatch->pCode = pCode + 1;
\r
143 pPatch->CodeLength = 4;
\r
144 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
145 l = (long)pHook - ((long)pCode + 5);
\r
146 memcpy(&pPatch->PatchCode[0], &l, 4);
\r
147 memcpy(&l, pCode + 1, 4);
\r
148 *ppUnhook = pCode + 5 + l;
\r
152 pPatch->pCode = pCode;
\r
153 pPatch->CodeLength = 5;
\r
154 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
155 pPatch->PatchCode[0] = 0xe9;
\r
156 l = (long)pHook - ((long)pCode + 5);
\r
157 memcpy(&pPatch->PatchCode[1], &l, 4);
\r
161 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
163 memcpy(pPatch->pCode, &pPatch->PatchCode, pPatch->CodeLength);
\r
164 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
165 FlushInstructionCache(GetCurrentProcess(), pPatch->pCode, pPatch->CodeLength);
\r
170 #elif defined(_M_AMD64)
\r
180 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
182 memcpy(pPatch->pCode, &pPatch->BackupCode, pPatch->CodeLength);
\r
183 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
184 FlushInstructionCache(GetCurrentProcess(), pPatch->pCode, pPatch->CodeLength);
\r
192 pCode = (BYTE*)pProc;
\r
193 if(pCode[0] == 0x48)
\r
195 while(pCode[0] == 0xeb || pCode[0] == 0xe9)
\r
197 if(pCode[0] == 0xeb)
\r
199 memcpy(&c, pCode + 1, 1);
\r
200 pCode = pCode + 2 + c;
\r
204 memcpy(&l, pCode + 1, 4);
\r
205 pCode = pCode + 5 + l;
\r
207 if(pCode[0] == 0x48)
\r
210 if(pCode[0] == 0xff && pCode[1] == 0x25)
\r
212 memcpy(&l, pCode + 2, 4);
\r
213 pPatch->pCode = pCode + 6 + l;
\r
214 pPatch->CodeLength = 8;
\r
215 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
216 memcpy(&pPatch->PatchCode[0], &pHook, 8);
\r
217 memcpy(&ll, pCode + 6 + l, 8);
\r
218 *ppUnhook = (void*)ll;
\r
222 pPatch->pCode = pCode;
\r
223 pPatch->CodeLength = 14;
\r
224 memcpy(&pPatch->BackupCode, pPatch->pCode, pPatch->CodeLength);
\r
225 pPatch->PatchCode[0] = 0xff;
\r
226 pPatch->PatchCode[1] = 0x25;
\r
228 memcpy(&pPatch->PatchCode[2], &l, 4);
\r
229 memcpy(&pPatch->PatchCode[6], &pHook, 8);
\r
233 if(VirtualProtect(pPatch->pCode, pPatch->CodeLength, PAGE_EXECUTE_READWRITE, &Protect))
\r
235 memcpy(pPatch->pCode, &pPatch->PatchCode, pPatch->CodeLength);
\r
236 VirtualProtect(pPatch->pCode, pPatch->CodeLength, Protect, &Protect);
\r
237 FlushInstructionCache(GetCurrentProcess(), pPatch->pCode, pPatch->CodeLength);
\r
247 #ifdef USE_IAT_HOOK
\r
248 BOOL HookFunctionInIAT(void* pProc, void* pHook, void** ppUnhook)
\r
254 IMAGE_IMPORT_DESCRIPTOR* piid;
\r
256 IMAGE_THUNK_DATA* pitd;
\r
259 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
261 me.dwSize = sizeof(MODULEENTRY32);
\r
262 if(Module32First(hSnapshot, &me))
\r
267 if(piid = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(me.hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size))
\r
269 while(!bFound && piid->Name != 0)
\r
271 pitd = (IMAGE_THUNK_DATA*)((BYTE*)me.hModule + piid->FirstThunk);
\r
272 while(!bFound && pitd->u1.Function != 0)
\r
274 if((void*)pitd->u1.Function == pProc)
\r
277 if(VirtualProtect(&pitd->u1.Function, sizeof(void*), PAGE_EXECUTE_READWRITE, &Protect))
\r
279 memcpy(&pitd->u1.Function, &pHook, sizeof(void*));
\r
280 VirtualProtect(&pitd->u1.Function, sizeof(void*), Protect, &Protect);
\r
291 while(!bFound && Module32Next(hSnapshot, &me));
\r
293 CloseHandle(hSnapshot);
\r
299 BOOL InitializeHookFunction(HOOK_FUNCTION_INFO* pInfo)
\r
303 if(!(pInfo->Flags & HOOK_INITIALIZED))
\r
305 if(pInfo->Flags & HOOK_USE_GETMODULEHANDLE)
\r
306 pInfo->hModule = GetModuleHandle(pInfo->ModuleName);
\r
307 if(pInfo->Flags & HOOK_USE_LOADLIBRARY)
\r
308 pInfo->hModule = LoadLibrary(pInfo->ModuleName);
\r
309 if(pInfo->Flags & HOOK_USE_GETPROCADDRESS)
\r
310 pInfo->Proc = GetProcAddress(pInfo->hModule, pInfo->ProcName);
\r
313 pInfo->Flags |= HOOK_INITIALIZED;
\r
320 void UninitializeHookFunction(HOOK_FUNCTION_INFO* pInfo)
\r
322 if(pInfo->Flags & HOOK_INITIALIZED)
\r
324 if(pInfo->Flags & HOOK_USE_LOADLIBRARY)
\r
325 FreeLibrary(pInfo->hModule);
\r
326 pInfo->Flags &= ~HOOK_INITIALIZED;
\r
330 BOOL EnableHookFunction(HOOK_FUNCTION_INFO* pInfo, BOOL bEnable)
\r
334 if(pInfo->Flags & HOOK_INITIALIZED)
\r
338 if(!(pInfo->Flags & HOOK_ENABLED))
\r
340 #ifdef USE_CODE_HOOK
\r
341 if(HookFunctionInCode(pInfo->Proc, pInfo->Hook, (void**)&pInfo->Unhook, &pInfo->Patch, FALSE))
\r
343 pInfo->Flags |= HOOK_ENABLED;
\r
347 #ifdef USE_IAT_HOOK
\r
348 if(HookFunctionInIAT(pInfo->Proc, pInfo->Hook, (void**)&pInfo->Unhook))
\r
350 pInfo->Flags |= HOOK_ENABLED;
\r
358 if(pInfo->Flags & HOOK_ENABLED)
\r
360 #ifdef USE_CODE_HOOK
\r
361 if(HookFunctionInCode(pInfo->Proc, pInfo->Hook, (void**)&pInfo->Unhook, &pInfo->Patch, TRUE))
\r
363 pInfo->Flags &= ~HOOK_ENABLED;
\r
367 #ifdef USE_IAT_HOOK
\r
368 if(HookFunctionInIAT(pInfo->Hook, pInfo->Proc, (void**)&pInfo->Unhook))
\r
370 pInfo->Flags &= ~HOOK_ENABLED;
\r
380 BOOL LockThreadLock()
\r
386 ThreadId = GetCurrentThreadId();
\r
388 while(i < MAX_LOCKED_THREAD)
\r
390 if(g_LockedThread[i] == ThreadId)
\r
394 if(i >= MAX_LOCKED_THREAD)
\r
397 while(i < MAX_LOCKED_THREAD)
\r
399 if(g_LockedThread[i] == 0)
\r
401 g_LockedThread[i] = ThreadId;
\r
411 BOOL UnlockThreadLock()
\r
417 ThreadId = GetCurrentThreadId();
\r
419 while(i < MAX_LOCKED_THREAD)
\r
421 if(g_LockedThread[i] == ThreadId)
\r
423 g_LockedThread[i] = 0;
\r
433 HANDLE LockExistingFile(LPCWSTR Filename)
\r
437 if((hResult = CreateFileW(Filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE)
\r
443 BOOL FindTrustedModuleSHA1Hash(void* pHash)
\r
449 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
451 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
461 BOOL VerifyFileSignature_Function(LPCWSTR Filename)
\r
465 PCCERT_CONTEXT pcc;
\r
466 CERT_CHAIN_PARA ccp;
\r
467 CERT_CHAIN_CONTEXT* pccc;
\r
468 CERT_CHAIN_POLICY_PARA ccpp;
\r
469 CERT_CHAIN_POLICY_STATUS ccps;
\r
471 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
474 while(!bResult && (pcc = CertEnumCertificatesInStore(hStore, pcc)))
\r
476 ZeroMemory(&ccp, sizeof(CERT_CHAIN_PARA));
\r
477 ccp.cbSize = sizeof(CERT_CHAIN_PARA);
\r
478 if(CertGetCertificateChain(NULL, pcc, NULL, NULL, &ccp, 0, NULL, &pccc))
\r
480 ZeroMemory(&ccpp, sizeof(CERT_CHAIN_POLICY_PARA));
\r
481 ccpp.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
\r
482 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_EXPIRED)
\r
483 ccpp.dwFlags |= CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG;
\r
484 else if(g_ProcessProtectionLevel & PROCESS_PROTECTION_UNAUTHORIZED)
\r
485 ccpp.dwFlags |= CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
\r
486 ZeroMemory(&ccps, sizeof(CERT_CHAIN_POLICY_STATUS));
\r
487 ccps.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
\r
488 if(CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE, pccc, &ccpp, &ccps))
\r
490 if(ccps.dwError == ERROR_SUCCESS)
\r
496 CertFreeCertificateChain(pccc);
\r
499 while(pcc = CertEnumCertificatesInStore(hStore, pcc))
\r
502 CertCloseStore(hStore, 0);
\r
508 BOOL VerifyFileSignature(LPCWSTR Filename)
\r
511 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
512 WINTRUST_FILE_INFO wfi;
\r
515 ZeroMemory(&wfi, sizeof(WINTRUST_FILE_INFO));
\r
516 wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
\r
517 wfi.pcwszFilePath = Filename;
\r
518 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
519 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
520 wd.dwUIChoice = WTD_UI_NONE;
\r
521 wd.dwUnionChoice = WTD_CHOICE_FILE;
\r
523 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
526 bResult = VerifyFileSignature_Function(Filename);
\r
530 // ファイルの署名をカタログファイルで確認
\r
531 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename)
\r
534 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
535 WINTRUST_CATALOG_INFO wci;
\r
538 if(VerifyFileSignature(Catalog))
\r
540 ZeroMemory(&wci, sizeof(WINTRUST_CATALOG_INFO));
\r
541 wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
\r
542 wci.pcwszCatalogFilePath = Catalog;
\r
543 wci.pcwszMemberFilePath = Filename;
\r
544 if((wci.hMemberFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
546 p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, NULL, 0);
\r
547 if(wci.pbCalculatedFileHash = (BYTE*)malloc(wci.cbCalculatedFileHash))
\r
549 if(p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, wci.pbCalculatedFileHash, 0))
\r
551 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
552 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
553 wd.dwUIChoice = WTD_UI_NONE;
\r
554 wd.dwUnionChoice = WTD_CHOICE_CATALOG;
\r
555 wd.pCatalog = &wci;
\r
556 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
559 free(wci.pbCalculatedFileHash);
\r
561 CloseHandle(wci.hMemberFile);
\r
567 BOOL WINAPI GetSHA1HashOfModule_Function(DIGEST_HANDLE refdata, PBYTE pData, DWORD dwLength)
\r
569 return CryptHashData(*(HCRYPTHASH*)refdata, pData, dwLength, 0);
\r
572 // モジュールのSHA1ハッシュを取得
\r
573 // マニフェストファイルのfile要素のhash属性は実行可能ファイルの場合にImageGetDigestStreamで算出される
\r
574 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash)
\r
582 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
584 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
586 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
588 if(ImageGetDigestStream(hFile, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO, GetSHA1HashOfModule_Function, (DIGEST_HANDLE)&hHash))
\r
591 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
594 CloseHandle(hFile);
\r
596 CryptDestroyHash(hHash);
\r
598 CryptReleaseContext(hProv, 0);
\r
603 BOOL IsSxsModuleTrusted_Function(LPCWSTR Catalog, LPCWSTR Manifest, LPCWSTR Module)
\r
610 static char HexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
\r
617 if(hLock0 = LockExistingFile(Catalog))
\r
619 if(hLock1 = LockExistingFile(Manifest))
\r
621 if(VerifyFileSignatureInCatalog(Catalog, Manifest))
\r
623 if(GetSHA1HashOfModule(Module, &Hash))
\r
625 for(i = 0; i < 20; i++)
\r
627 HashHex[i * 2] = HexTable[(Hash[i] >> 4) & 0x0f];
\r
628 HashHex[i * 2 + 1] = HexTable[Hash[i] & 0x0f];
\r
630 HashHex[i * 2] = '\0';
\r
631 if((hFile = CreateFileW(Manifest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
633 Size = GetFileSize(hFile, NULL);
\r
634 if(pData = (char*)VirtualAlloc(NULL, Size + 1, MEM_COMMIT, PAGE_READWRITE))
\r
636 VirtualLock(pData, Size + 1);
\r
637 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
640 if(strstr(pData, HashHex))
\r
643 VirtualUnlock(pData, Size + 1);
\r
644 VirtualFree(pData, Size + 1, MEM_DECOMMIT);
\r
646 CloseHandle(hFile);
\r
650 CloseHandle(hLock1);
\r
652 CloseHandle(hLock0);
\r
658 // パスは"%SystemRoot%\WinSxS"以下を想定
\r
659 // 以下のファイルが存在するものとする
\r
660 // "\xxx\yyy.dll"、"\manifests\xxx.cat"、"\manifests\xxx.manifest"のセット(XPの全てのDLL、Vista以降の一部のDLL)
\r
661 // "\xxx\yyy.dll"、"\catalogs\zzz.cat"、"\manifests\xxx.manifest"のセット(Vista以降のほとんどのDLL)
\r
662 // 署名されたカタログファイルを用いてマニフェストファイルが改竄されていないことを確認
\r
663 // ハッシュ値は マニフェストファイルのfile要素のhash属性に記述されているものを用いる
\r
664 // マニフェストファイル内にSHA1ハッシュ値の16進数表記を直接検索しているが確率的に問題なし
\r
665 BOOL IsSxsModuleTrusted(LPCWSTR Filename)
\r
676 WIN32_FIND_DATAW wfd;
\r
678 if(pw0 = AllocateStringW(wcslen(Filename) + 1))
\r
680 wcscpy(pw0, Filename);
\r
681 if(p = wcsrchr(pw0, L'\\'))
\r
684 if(p = wcsrchr(pw0, L'\\'))
\r
687 if(pw1 = AllocateStringW(wcslen(p) + 1))
\r
691 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".cat") + 1))
\r
694 wcscat(pw2, L"manifests\\");
\r
696 if(pw3 = AllocateStringW(wcslen(pw2) + wcslen(L".manifest") + 1))
\r
699 wcscat(pw3, L".manifest");
\r
700 wcscat(pw2, L".cat");
\r
701 if(IsSxsModuleTrusted_Function(pw2, pw3, Filename))
\r
703 FreeDuplicatedString(pw3);
\r
705 FreeDuplicatedString(pw2);
\r
709 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"catalogs\\") + 1))
\r
711 if(pw3 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".manifest") + 1))
\r
714 wcscat(pw2, L"catalogs\\");
\r
716 wcscat(pw3, L"manifests\\");
\r
718 wcscat(pw3, L".manifest");
\r
719 if(pw4 = AllocateStringW(wcslen(pw2) + wcslen(L"*.cat") + 1))
\r
722 wcscat(pw4, L"*.cat");
\r
723 if((hFind = FindFirstFileW(pw4, &wfd)) != INVALID_HANDLE_VALUE)
\r
727 if(pw5 = AllocateStringW(wcslen(pw2) + wcslen(wfd.cFileName) + 1))
\r
730 wcscat(pw5, wfd.cFileName);
\r
731 if(IsSxsModuleTrusted_Function(pw5, pw3, Filename))
\r
733 FreeDuplicatedString(pw5);
\r
736 while(!bResult && FindNextFileW(hFind, &wfd));
\r
739 FreeDuplicatedString(pw4);
\r
741 FreeDuplicatedString(pw3);
\r
743 FreeDuplicatedString(pw2);
\r
746 FreeDuplicatedString(pw1);
\r
750 FreeDuplicatedString(pw0);
\r
756 BOOL IsModuleTrusted(LPCWSTR Filename)
\r
761 if(LockThreadLock())
\r
763 if(GetSHA1HashOfFile(Filename, &Hash))
\r
765 if(FindTrustedModuleSHA1Hash(&Hash))
\r
770 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_BUILTIN) && VerifyFileSignature(Filename))
\r
775 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SYSTEM_FILE) && SfcIsFileProtected(NULL, Filename))
\r
780 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SIDE_BY_SIDE) && IsSxsModuleTrusted(Filename))
\r
783 UnlockThreadLock();
\r
790 HMODULE WINAPI h_LoadLibraryA(LPCSTR lpLibFileName)
\r
793 wchar_t* pw0 = NULL;
\r
794 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
795 r = LoadLibraryExW(pw0, NULL, 0);
\r
796 FreeDuplicatedString(pw0);
\r
800 HMODULE WINAPI h_LoadLibraryW(LPCWSTR lpLibFileName)
\r
803 r = LoadLibraryExW(lpLibFileName, NULL, 0);
\r
807 HMODULE WINAPI h_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
810 wchar_t* pw0 = NULL;
\r
811 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
812 r = LoadLibraryExW(pw0, hFile, dwFlags);
\r
813 FreeDuplicatedString(pw0);
\r
817 HMODULE WINAPI h_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
828 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
829 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | 0x00000020 | 0x00000040))
\r
833 if(hModule = System_LoadLibrary(lpLibFileName, NULL, DONT_RESOLVE_DLL_REFERENCES))
\r
836 if(pw0 = AllocateStringW(Length))
\r
838 if(GetModuleFileNameW(hModule, pw0, Length) > 0)
\r
842 if(GetModuleFileNameW(hModule, pw0, Length) + 1 <= Length)
\r
844 lpLibFileName = pw0;
\r
847 Length = Length * 2;
\r
848 FreeDuplicatedString(pw0);
\r
849 pw0 = AllocateStringW(Length);
\r
853 hLock = LockExistingFile(lpLibFileName);
\r
854 FreeLibrary(hModule);
\r
856 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_LOADED) && GetModuleHandleW(lpLibFileName))
\r
863 if(IsModuleTrusted(lpLibFileName))
\r
868 r = System_LoadLibrary(lpLibFileName, hFile, dwFlags);
\r
869 FreeDuplicatedString(pw0);
\r
871 CloseHandle(hLock);
\r
875 // kernel32.dllのLoadLibraryExW相当の関数
\r
876 // ドキュメントが無いため詳細は不明
\r
877 // 一部のウィルス対策ソフト(Avast!等)がLdrLoadDllをフックしているためLdrLoadDllを書き換えるべきではない
\r
878 // カーネルモードのコードに対しては効果なし
\r
879 // SeDebugPrivilegeが使用可能なユーザーに対しては効果なし
\r
880 HMODULE System_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
887 us.Length = sizeof(wchar_t) * (USHORT)wcslen(lpLibFileName);
\r
888 us.MaximumLength = sizeof(wchar_t) * ((USHORT)wcslen(lpLibFileName) + 1);
\r
889 us.Buffer = (PWSTR)lpLibFileName;
\r
890 // if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
891 if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040))
\r
893 // if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == STATUS_SUCCESS)
\r
894 if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == 0)
\r
896 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
897 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
898 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
902 // if(dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
\r
903 if(dwFlags & 0x00000040)
\r
904 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
\r
906 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
\r
907 if(hDataFile != INVALID_HANDLE_VALUE)
\r
909 if(hMapping = CreateFileMappingW(hDataFile, NULL, PAGE_READONLY, 0, 0, NULL))
\r
911 if(r = (HMODULE)MapViewOfFileEx(hMapping, FILE_MAP_READ, 0, 0, 0, NULL))
\r
913 if(p_RtlImageNtHeader(r))
\r
914 r = (HMODULE)((size_t)r | 1);
\r
917 UnmapViewOfFile(r);
\r
921 CloseHandle(hMapping);
\r
923 CloseHandle(hDataFile);
\r
927 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
928 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
929 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
933 // if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)))
\r
934 if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040)))
\r
937 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
\r
938 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | 0x00000020))
\r
939 DllFlags |= 0x00000002;
\r
940 // if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == STATUS_SUCCESS)
\r
941 if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == 0)
\r
950 void SetProcessProtectionLevel(DWORD Level)
\r
952 g_ProcessProtectionLevel = Level;
\r
956 BOOL GetSHA1HashOfMemory(const void* pData, DWORD Size, void* pHash)
\r
963 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
965 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
967 if(CryptHashData(hHash, (BYTE*)pData, Size, 0))
\r
970 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
973 CryptDestroyHash(hHash);
\r
975 CryptReleaseContext(hProv, 0);
\r
980 // ファイルのSHA1ハッシュを取得
\r
981 BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash)
\r
989 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
991 Size = GetFileSize(hFile, NULL);
\r
992 if(pData = VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE))
\r
994 VirtualLock(pData, Size);
\r
995 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
997 if(GetSHA1HashOfMemory(pData, Size, pHash))
\r
1000 VirtualUnlock(pData, Size);
\r
1001 VirtualFree(pData, Size, MEM_DECOMMIT);
\r
1003 CloseHandle(hFile);
\r
1009 BOOL RegisterTrustedModuleSHA1Hash(void* pHash)
\r
1012 BYTE NullHash[20] = {0};
\r
1015 if(FindTrustedModuleSHA1Hash(pHash))
\r
1020 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
1022 if(memcmp(&g_TrustedSHA1HashTable[i], &NullHash, 20) == 0)
\r
1024 memcpy(&g_TrustedSHA1HashTable[i], pHash, 20);
\r
1035 BOOL UnregisterTrustedModuleSHA1Hash(void* pHash)
\r
1038 BYTE NullHash[20] = {0};
\r
1042 while(i < MAX_TRUSTED_SHA1_HASH_TABLE)
\r
1044 if(memcmp(&g_TrustedSHA1HashTable[i], pHash, 20) == 0)
\r
1046 memcpy(&g_TrustedSHA1HashTable[i], &NullHash, 20);
\r
1055 // 信頼できないDLLをアンロード
\r
1056 BOOL UnloadUntrustedModule()
\r
1065 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
1068 me.dwSize = sizeof(MODULEENTRY32);
\r
1069 if(Module32First(hSnapshot, &me))
\r
1073 Length = MAX_PATH;
\r
1074 FreeDuplicatedString(pw0);
\r
1075 if(pw0 = AllocateStringW(Length))
\r
1077 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
1081 if(GetModuleFileNameW(me.hModule, pw0, Length) + 1 <= Length)
\r
1083 Length = Length * 2;
\r
1084 FreeDuplicatedString(pw0);
\r
1085 pw0 = AllocateStringW(Length);
\r
1091 if(!IsModuleTrusted(pw0))
\r
1093 if(me.hModule != GetModuleHandleW(NULL))
\r
1095 while(FreeLibrary(me.hModule))
\r
1098 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
1112 while(Module32Next(hSnapshot, &me));
\r
1114 CloseHandle(hSnapshot);
\r
1116 FreeDuplicatedString(pw0);
\r
1120 // 関数ポインタを使用可能な状態に初期化
\r
1121 BOOL InitializeLoadLibraryHook()
\r
1126 memset(&g_LoadLibraryA, 0, sizeof(HOOK_FUNCTION_INFO));
\r
1127 g_LoadLibraryA.Flags = HOOK_USE_GETMODULEHANDLE | HOOK_USE_GETPROCADDRESS;
\r
1128 g_LoadLibraryA.ModuleName = _T("kernel32.dll");
\r
1129 g_LoadLibraryA.ProcName = "LoadLibraryA";
\r
1130 g_LoadLibraryA.Hook = (FARPROC)h_LoadLibraryA;
\r
1131 if(!InitializeHookFunction(&g_LoadLibraryA))
\r
1133 memset(&g_LoadLibraryW, 0, sizeof(HOOK_FUNCTION_INFO));
\r
1134 g_LoadLibraryW.Flags = HOOK_USE_GETMODULEHANDLE | HOOK_USE_GETPROCADDRESS;
\r
1135 g_LoadLibraryW.ModuleName = _T("kernel32.dll");
\r
1136 g_LoadLibraryW.ProcName = "LoadLibraryW";
\r
1137 g_LoadLibraryW.Hook = (FARPROC)h_LoadLibraryW;
\r
1138 if(!InitializeHookFunction(&g_LoadLibraryW))
\r
1140 memset(&g_LoadLibraryExA, 0, sizeof(HOOK_FUNCTION_INFO));
\r
1141 g_LoadLibraryExA.Flags = HOOK_USE_GETMODULEHANDLE | HOOK_USE_GETPROCADDRESS;
\r
1142 g_LoadLibraryExA.ModuleName = _T("kernel32.dll");
\r
1143 g_LoadLibraryExA.ProcName = "LoadLibraryExA";
\r
1144 g_LoadLibraryExA.Hook = (FARPROC)h_LoadLibraryExA;
\r
1145 if(!InitializeHookFunction(&g_LoadLibraryExA))
\r
1147 memset(&g_LoadLibraryExW, 0, sizeof(HOOK_FUNCTION_INFO));
\r
1148 g_LoadLibraryExW.Flags = HOOK_USE_GETMODULEHANDLE | HOOK_USE_GETPROCADDRESS;
\r
1149 g_LoadLibraryExW.ModuleName = _T("kernel32.dll");
\r
1150 g_LoadLibraryExW.ProcName = "LoadLibraryExW";
\r
1151 g_LoadLibraryExW.Hook = (FARPROC)h_LoadLibraryExW;
\r
1152 if(!InitializeHookFunction(&g_LoadLibraryExW))
\r
1154 if(!(hModule = GetModuleHandleW(L"ntdll.dll")))
\r
1156 if(!(p_LdrLoadDll = (_LdrLoadDll)GetProcAddress(hModule, "LdrLoadDll")))
\r
1158 if(!(p_LdrGetDllHandle = (_LdrGetDllHandle)GetProcAddress(hModule, "LdrGetDllHandle")))
\r
1160 if(!(p_RtlImageNtHeader = (_RtlImageNtHeader)GetProcAddress(hModule, "RtlImageNtHeader")))
\r
1162 if(!(hModule = LoadLibraryW(L"wintrust.dll")))
\r
1164 if(!(p_CryptCATAdminCalcHashFromFileHandle = (_CryptCATAdminCalcHashFromFileHandle)GetProcAddress(hModule, "CryptCATAdminCalcHashFromFileHandle")))
\r
1167 ImageGetDigestStream(NULL, 0, NULL, NULL);
\r
1171 // SetWindowsHookEx対策
\r
1172 // DLL Injectionされた場合は上のh_LoadLibrary系関数でトラップ可能
\r
1173 BOOL EnableLoadLibraryHook(BOOL bEnable)
\r
1177 if(!EnableHookFunction(&g_LoadLibraryA, bEnable))
\r
1179 if(!EnableHookFunction(&g_LoadLibraryW, bEnable))
\r
1181 if(!EnableHookFunction(&g_LoadLibraryExA, bEnable))
\r
1183 if(!EnableHookFunction(&g_LoadLibraryExW, bEnable))
\r
1188 // ReadProcessMemory、WriteProcessMemory、CreateRemoteThread対策
\r
1189 // TerminateProcessのみ許可
\r
1190 BOOL RestartProtectedProcess(LPCTSTR Keyword)
\r
1194 SID_IDENTIFIER_AUTHORITY sia = SECURITY_WORLD_SID_AUTHORITY;
\r
1196 SECURITY_DESCRIPTOR sd;
\r
1197 TCHAR* CommandLine;
\r
1198 SECURITY_ATTRIBUTES sa;
\r
1200 PROCESS_INFORMATION pi;
\r
1202 if(_tcslen(GetCommandLine()) >= _tcslen(Keyword) && _tcscmp(GetCommandLine() + _tcslen(GetCommandLine()) - _tcslen(Keyword), Keyword) == 0)
\r
1204 if(pACL = (ACL*)malloc(sizeof(ACL) + 1024))
\r
1206 if(InitializeAcl(pACL, sizeof(ACL) + 1024, ACL_REVISION))
\r
1208 if(AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID))
\r
1210 if(AddAccessAllowedAce(pACL, ACL_REVISION, PROCESS_TERMINATE, pSID))
\r
1212 if(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
\r
1214 if(SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE))
\r
1216 if(CommandLine = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(GetCommandLine()) + _tcslen(Keyword) + 1)))
\r
1218 _tcscpy(CommandLine, GetCommandLine());
\r
1219 _tcscat(CommandLine, Keyword);
\r
1220 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
1221 sa.lpSecurityDescriptor = &sd;
\r
1222 sa.bInheritHandle = FALSE;
\r
1223 GetStartupInfo(&si);
\r
1224 if(CreateProcess(NULL, CommandLine, &sa, NULL, FALSE, 0, NULL, NULL, &si, &pi))
\r
1226 CloseHandle(pi.hThread);
\r
1227 CloseHandle(pi.hProcess);
\r
1230 free(CommandLine);
\r
1243 INT_PTR CALLBACK PasswordEditControlWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
\r
1247 case EM_GETPASSWORDCHAR:
\r
1249 case EM_SETPASSWORDCHAR:
\r
1252 return CallWindowProcW(g_PasswordEditControlProc, hWnd, Msg, wParam, lParam);
\r
1257 BOOL ProtectPasswordEditControl(HWND hWnd)
\r
1260 WCHAR ClassName[MAX_PATH];
\r
1263 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1265 if(GetClassNameW(hWnd, ClassName, MAX_PATH) > 0)
\r
1267 if(_wcsicmp(ClassName, WC_EDITW) == 0)
\r
1269 Proc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
\r
1270 if(Proc != (WNDPROC)PasswordEditControlWndProc)
\r
1272 g_PasswordEditControlProc = Proc;
\r
1273 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)PasswordEditControlWndProc);
\r
1282 BOOL CALLBACK ProtectAllEditControlsEnumChildProc(HWND hwnd , LPARAM lParam)
\r
1284 ProtectPasswordEditControl(hwnd);
\r
1288 BOOL ProtectAllEditControls(HWND hWnd)
\r
1290 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_PASSWORD_EDIT)
\r
1291 EnumChildWindows(hWnd, ProtectAllEditControlsEnumChildProc, 0);
\r