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 START_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_MD5_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_TrustedMD5HashTable[MAX_TRUSTED_MD5_HASH_TABLE][20];
\r
105 // フック対象を呼び出す場合は前後でSTART_HOOK_FUNCTIONとEND_HOOK_FUNCTIONを実行する必要がある
\r
107 HMODULE WINAPI h_LoadLibraryA(LPCSTR lpLibFileName)
\r
110 wchar_t* pw0 = NULL;
\r
111 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
112 r = LoadLibraryExW(pw0, NULL, 0);
\r
113 FreeDuplicatedString(pw0);
\r
117 HMODULE WINAPI h_LoadLibraryW(LPCWSTR lpLibFileName)
\r
120 r = LoadLibraryExW(lpLibFileName, NULL, 0);
\r
124 HMODULE WINAPI h_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
127 wchar_t* pw0 = NULL;
\r
128 if(pw0 = DuplicateAtoW(lpLibFileName, -1))
\r
129 r = LoadLibraryExW(pw0, hFile, dwFlags);
\r
130 FreeDuplicatedString(pw0);
\r
134 HMODULE WINAPI h_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
145 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
146 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | 0x00000020 | 0x00000040))
\r
150 if(hModule = System_LoadLibrary(lpLibFileName, NULL, DONT_RESOLVE_DLL_REFERENCES))
\r
153 if(pw0 = AllocateStringW(Length))
\r
155 if(GetModuleFileNameW(hModule, pw0, Length) > 0)
\r
159 if(GetModuleFileNameW(hModule, pw0, Length) + 1 <= Length)
\r
161 lpLibFileName = pw0;
\r
164 Length = Length * 2;
\r
165 FreeDuplicatedString(pw0);
\r
166 pw0 = AllocateStringW(Length);
\r
170 hLock = LockExistingFile(lpLibFileName);
\r
171 FreeLibrary(hModule);
\r
173 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_LOADED) && GetModuleHandleW(lpLibFileName))
\r
180 if(IsModuleTrusted(lpLibFileName))
\r
185 r = System_LoadLibrary(lpLibFileName, hFile, dwFlags);
\r
186 FreeDuplicatedString(pw0);
\r
188 CloseHandle(hLock);
\r
194 BOOL LockThreadLock()
\r
200 ThreadId = GetCurrentThreadId();
\r
202 while(i < MAX_LOCKED_THREAD)
\r
204 if(g_LockedThread[i] == ThreadId)
\r
208 if(i >= MAX_LOCKED_THREAD)
\r
211 while(i < MAX_LOCKED_THREAD)
\r
213 if(g_LockedThread[i] == 0)
\r
215 g_LockedThread[i] = ThreadId;
\r
225 BOOL UnlockThreadLock()
\r
231 ThreadId = GetCurrentThreadId();
\r
233 while(i < MAX_LOCKED_THREAD)
\r
235 if(g_LockedThread[i] == ThreadId)
\r
237 g_LockedThread[i] = 0;
\r
246 #ifdef USE_CODE_HOOK
\r
247 BOOL HookFunctionInCode(void* pOriginal, void* pNew, void* pBackupCode, BOOL bRestore)
\r
252 BYTE JumpCode[HOOK_JUMP_CODE_LENGTH] = {0xe9, 0x00, 0x00, 0x00, 0x00};
\r
254 Relative = (size_t)pNew - (size_t)pOriginal - HOOK_JUMP_CODE_LENGTH;
\r
255 memcpy(&JumpCode[1], &Relative, 4);
\r
259 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
261 memcpy(pOriginal, pBackupCode, HOOK_JUMP_CODE_LENGTH);
\r
262 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
269 memcpy(pBackupCode, pOriginal, HOOK_JUMP_CODE_LENGTH);
\r
270 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
272 memcpy(pOriginal, &JumpCode, HOOK_JUMP_CODE_LENGTH);
\r
273 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
277 #elif defined(_AMD64_)
\r
278 BYTE JumpCode[HOOK_JUMP_CODE_LENGTH] = {0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
280 Absolute = (size_t)pOriginal;
\r
281 memcpy(&JumpCode[6], &Absolute, 8);
\r
285 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
287 memcpy(pOriginal, pBackupCode, HOOK_JUMP_CODE_LENGTH);
\r
288 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
295 memcpy(pBackupCode, pOriginal, HOOK_JUMP_CODE_LENGTH);
\r
296 if(VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, PAGE_EXECUTE_READWRITE, &Protect))
\r
298 memcpy(pOriginal, &JumpCode, HOOK_JUMP_CODE_LENGTH);
\r
299 VirtualProtect(pOriginal, HOOK_JUMP_CODE_LENGTH, Protect, &Protect);
\r
308 #ifdef USE_IAT_HOOK
\r
309 BOOL HookFunctionInIAT(void* pOriginal, void* pNew)
\r
315 IMAGE_IMPORT_DESCRIPTOR* piid;
\r
317 IMAGE_THUNK_DATA* pitd;
\r
320 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
322 me.dwSize = sizeof(MODULEENTRY32);
\r
323 if(Module32First(hSnapshot, &me))
\r
328 if(piid = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToData(me.hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size))
\r
330 while(!bFound && piid->Name != 0)
\r
332 pitd = (IMAGE_THUNK_DATA*)((BYTE*)me.hModule + piid->FirstThunk);
\r
333 while(!bFound && pitd->u1.Function != 0)
\r
335 if((void*)pitd->u1.Function == pOriginal)
\r
338 if(VirtualProtect(&pitd->u1.Function, sizeof(void*), PAGE_EXECUTE_READWRITE, &Protect))
\r
340 memcpy(&pitd->u1.Function, &pNew, sizeof(void*));
\r
341 VirtualProtect(&pitd->u1.Function, sizeof(void*), Protect, &Protect);
\r
351 while(!bFound && Module32Next(hSnapshot, &me));
\r
353 CloseHandle(hSnapshot);
\r
360 HANDLE LockExistingFile(LPCWSTR Filename)
\r
364 if((hResult = CreateFileW(Filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE)
\r
370 BOOL FindTrustedModuleSHA1Hash(void* pHash)
\r
376 while(i < MAX_TRUSTED_MD5_HASH_TABLE)
\r
378 if(memcmp(&g_TrustedMD5HashTable[i], pHash, 20) == 0)
\r
388 BOOL VerifyFileSignature_Function(LPCWSTR Filename)
\r
392 PCCERT_CONTEXT pcc;
\r
393 CERT_CHAIN_PARA ccp;
\r
394 CERT_CHAIN_CONTEXT* pccc;
\r
395 CERT_CHAIN_POLICY_PARA ccpp;
\r
396 CERT_CHAIN_POLICY_STATUS ccps;
\r
398 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
401 while(!bResult && (pcc = CertEnumCertificatesInStore(hStore, pcc)))
\r
403 ZeroMemory(&ccp, sizeof(CERT_CHAIN_PARA));
\r
404 ccp.cbSize = sizeof(CERT_CHAIN_PARA);
\r
405 if(CertGetCertificateChain(NULL, pcc, NULL, NULL, &ccp, 0, NULL, &pccc))
\r
407 ZeroMemory(&ccpp, sizeof(CERT_CHAIN_POLICY_PARA));
\r
408 ccpp.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
\r
409 if(g_ProcessProtectionLevel & PROCESS_PROTECTION_EXPIRED)
\r
410 ccpp.dwFlags |= CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG;
\r
411 else if(g_ProcessProtectionLevel & PROCESS_PROTECTION_UNAUTHORIZED)
\r
412 ccpp.dwFlags |= CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
\r
413 ZeroMemory(&ccps, sizeof(CERT_CHAIN_POLICY_STATUS));
\r
414 ccps.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
\r
415 if(CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE, pccc, &ccpp, &ccps))
\r
417 if(ccps.dwError == ERROR_SUCCESS)
\r
423 CertFreeCertificateChain(pccc);
\r
426 while(pcc = CertEnumCertificatesInStore(hStore, pcc))
\r
429 CertCloseStore(hStore, 0);
\r
435 BOOL VerifyFileSignature(LPCWSTR Filename)
\r
438 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
439 WINTRUST_FILE_INFO wfi;
\r
442 ZeroMemory(&wfi, sizeof(WINTRUST_FILE_INFO));
\r
443 wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
\r
444 wfi.pcwszFilePath = Filename;
\r
445 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
446 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
447 wd.dwUIChoice = WTD_UI_NONE;
\r
448 wd.dwUnionChoice = WTD_CHOICE_FILE;
\r
450 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
453 bResult = VerifyFileSignature_Function(Filename);
\r
457 // ファイルの署名をカタログファイルで確認
\r
458 BOOL VerifyFileSignatureInCatalog(LPCWSTR Catalog, LPCWSTR Filename)
\r
461 GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;
\r
462 WINTRUST_CATALOG_INFO wci;
\r
465 if(VerifyFileSignature(Catalog))
\r
467 ZeroMemory(&wci, sizeof(WINTRUST_CATALOG_INFO));
\r
468 wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
\r
469 wci.pcwszCatalogFilePath = Catalog;
\r
470 wci.pcwszMemberFilePath = Filename;
\r
471 if((wci.hMemberFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
473 p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, NULL, 0);
\r
474 if(wci.pbCalculatedFileHash = (BYTE*)malloc(wci.cbCalculatedFileHash))
\r
476 if(p_CryptCATAdminCalcHashFromFileHandle(wci.hMemberFile, &wci.cbCalculatedFileHash, wci.pbCalculatedFileHash, 0))
\r
478 ZeroMemory(&wd, sizeof(WINTRUST_DATA));
\r
479 wd.cbStruct = sizeof(WINTRUST_DATA);
\r
480 wd.dwUIChoice = WTD_UI_NONE;
\r
481 wd.dwUnionChoice = WTD_CHOICE_CATALOG;
\r
482 wd.pCatalog = &wci;
\r
483 if(WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &g, &wd) == ERROR_SUCCESS)
\r
486 free(wci.pbCalculatedFileHash);
\r
488 CloseHandle(wci.hMemberFile);
\r
494 BOOL WINAPI GetSHA1HashOfModule_Function(DIGEST_HANDLE refdata, PBYTE pData, DWORD dwLength)
\r
496 return CryptHashData(*(HCRYPTHASH*)refdata, pData, dwLength, 0);
\r
499 // モジュールのSHA1ハッシュを取得
\r
500 // マニフェストファイルのfile要素のhash属性は実行可能ファイルの場合にImageGetDigestStreamで算出される
\r
501 BOOL GetSHA1HashOfModule(LPCWSTR Filename, void* pHash)
\r
509 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
511 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
513 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
515 if(ImageGetDigestStream(hFile, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO, GetSHA1HashOfModule_Function, (DIGEST_HANDLE)&hHash))
\r
518 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
521 CloseHandle(hFile);
\r
523 CryptDestroyHash(hHash);
\r
525 CryptReleaseContext(hProv, 0);
\r
530 BOOL IsSxsModuleTrusted_Function(LPCWSTR Catalog, LPCWSTR Manifest, LPCWSTR Module)
\r
537 static char HexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
\r
544 if(hLock0 = LockExistingFile(Catalog))
\r
546 if(hLock1 = LockExistingFile(Manifest))
\r
548 if(VerifyFileSignatureInCatalog(Catalog, Manifest))
\r
550 if(GetSHA1HashOfModule(Module, &Hash))
\r
552 for(i = 0; i < 20; i++)
\r
554 HashHex[i * 2] = HexTable[(Hash[i] >> 4) & 0x0f];
\r
555 HashHex[i * 2 + 1] = HexTable[Hash[i] & 0x0f];
\r
557 HashHex[i * 2] = '\0';
\r
558 if((hFile = CreateFileW(Manifest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
\r
560 Size = GetFileSize(hFile, NULL);
\r
561 if(pData = (char*)VirtualAlloc(NULL, Size + 1, MEM_COMMIT, PAGE_READWRITE))
\r
563 VirtualLock(pData, Size + 1);
\r
564 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
567 if(strstr(pData, HashHex))
\r
570 VirtualUnlock(pData, Size + 1);
\r
571 VirtualFree(pData, Size + 1, MEM_DECOMMIT);
\r
573 CloseHandle(hFile);
\r
577 CloseHandle(hLock1);
\r
579 CloseHandle(hLock0);
\r
585 // パスは"%SystemRoot%\WinSxS"以下を想定
\r
586 // 以下のファイルが存在するものとする
\r
587 // "\xxx\yyy.dll"、"\manifests\xxx.cat"、"\manifests\xxx.manifest"のセット(XPの全てのDLL、Vista以降の一部のDLL)
\r
588 // "\xxx\yyy.dll"、"\catalogs\zzz.cat"、"\manifests\xxx.manifest"のセット(Vista以降のほとんどのDLL)
\r
589 // 署名されたカタログファイルを用いてマニフェストファイルが改竄されていないことを確認
\r
590 // ハッシュ値は マニフェストファイルのfile要素のhash属性に記述されているものを用いる
\r
591 // マニフェストファイル内にSHA1ハッシュ値の16進数表記を直接検索しているが確率的に問題なし
\r
592 BOOL IsSxsModuleTrusted(LPCWSTR Filename)
\r
603 WIN32_FIND_DATAW wfd;
\r
605 if(pw0 = AllocateStringW(wcslen(Filename) + 1))
\r
607 wcscpy(pw0, Filename);
\r
608 if(p = wcsrchr(pw0, L'\\'))
\r
611 if(p = wcsrchr(pw0, L'\\'))
\r
614 if(pw1 = AllocateStringW(wcslen(p) + 1))
\r
618 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".cat") + 1))
\r
621 wcscat(pw2, L"manifests\\");
\r
623 if(pw3 = AllocateStringW(wcslen(pw2) + wcslen(L".manifest") + 1))
\r
626 wcscat(pw3, L".manifest");
\r
627 wcscat(pw2, L".cat");
\r
628 if(IsSxsModuleTrusted_Function(pw2, pw3, Filename))
\r
630 FreeDuplicatedString(pw3);
\r
632 FreeDuplicatedString(pw2);
\r
636 if(pw2 = AllocateStringW(wcslen(pw0) + wcslen(L"catalogs\\") + 1))
\r
638 if(pw3 = AllocateStringW(wcslen(pw0) + wcslen(L"manifests\\") + wcslen(pw1) + wcslen(L".manifest") + 1))
\r
641 wcscat(pw2, L"catalogs\\");
\r
643 wcscat(pw3, L"manifests\\");
\r
645 wcscat(pw3, L".manifest");
\r
646 if(pw4 = AllocateStringW(wcslen(pw2) + wcslen(L"*.cat") + 1))
\r
649 wcscat(pw4, L"*.cat");
\r
650 if((hFind = FindFirstFileW(pw4, &wfd)) != INVALID_HANDLE_VALUE)
\r
654 if(pw5 = AllocateStringW(wcslen(pw2) + wcslen(wfd.cFileName) + 1))
\r
657 wcscat(pw5, wfd.cFileName);
\r
658 if(IsSxsModuleTrusted_Function(pw5, pw3, Filename))
\r
660 FreeDuplicatedString(pw5);
\r
663 while(!bResult && FindNextFileW(hFind, &wfd));
\r
666 FreeDuplicatedString(pw4);
\r
668 FreeDuplicatedString(pw3);
\r
670 FreeDuplicatedString(pw2);
\r
673 FreeDuplicatedString(pw1);
\r
677 FreeDuplicatedString(pw0);
\r
683 BOOL IsModuleTrusted(LPCWSTR Filename)
\r
688 if(LockThreadLock())
\r
690 if(GetSHA1HashOfFile(Filename, &Hash))
\r
692 if(FindTrustedModuleSHA1Hash(&Hash))
\r
697 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_BUILTIN) && VerifyFileSignature(Filename))
\r
702 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SIDE_BY_SIDE) && IsSxsModuleTrusted(Filename))
\r
707 if((g_ProcessProtectionLevel & PROCESS_PROTECTION_SYSTEM_FILE) && SfcIsFileProtected(NULL, Filename))
\r
710 UnlockThreadLock();
\r
715 // kernel32.dllのLoadLibraryExW相当の関数
\r
716 // ドキュメントが無いため詳細は不明
\r
717 // 一部のウィルス対策ソフト(Avast!等)がLdrLoadDllをフックしているためLdrLoadDllを書き換えるべきではない
\r
718 // カーネルモードのコードに対しては効果なし
\r
719 // SeDebugPrivilegeが使用可能なユーザーに対しては効果なし
\r
720 HMODULE System_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
\r
727 us.Length = sizeof(wchar_t) * wcslen(lpLibFileName);
\r
728 us.MaximumLength = sizeof(wchar_t) * (wcslen(lpLibFileName) + 1);
\r
729 us.Buffer = (PWSTR)lpLibFileName;
\r
730 // if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
\r
731 if(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040))
\r
733 // if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == STATUS_SUCCESS)
\r
734 if(p_LdrGetDllHandle(NULL, NULL, &us, &r) == 0)
\r
736 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
737 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
738 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
742 // if(dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
\r
743 if(dwFlags & 0x00000040)
\r
744 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
\r
746 hDataFile = CreateFileW(lpLibFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
\r
747 if(hDataFile != INVALID_HANDLE_VALUE)
\r
749 if(hMapping = CreateFileMappingW(hDataFile, NULL, PAGE_READONLY, 0, 0, NULL))
\r
751 if(r = (HMODULE)MapViewOfFileEx(hMapping, FILE_MAP_READ, 0, 0, 0, NULL))
\r
753 if(p_RtlImageNtHeader(r))
\r
754 r = (HMODULE)((size_t)r | 1);
\r
757 UnmapViewOfFile(r);
\r
761 CloseHandle(hMapping);
\r
763 CloseHandle(hDataFile);
\r
767 // dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
\r
768 dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE | 0x00000040);
\r
769 dwFlags |= DONT_RESOLVE_DLL_REFERENCES;
\r
773 // if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)))
\r
774 if(!(dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 0x00000040)))
\r
777 // if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
\r
778 if(dwFlags & (DONT_RESOLVE_DLL_REFERENCES | 0x00000020))
\r
779 DllFlags |= 0x00000002;
\r
780 // if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == STATUS_SUCCESS)
\r
781 if(p_LdrLoadDll(NULL, &DllFlags, &us, &r) == 0)
\r
790 void SetProcessProtectionLevel(DWORD Level)
\r
792 g_ProcessProtectionLevel = Level;
\r
795 // ファイルのSHA1ハッシュを取得
\r
796 BOOL GetSHA1HashOfFile(LPCWSTR Filename, void* pHash)
\r
806 if(CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0) || CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
808 if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
\r
810 if((hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
\r
812 Size = GetFileSize(hFile, NULL);
\r
813 if(pData = VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE))
\r
815 VirtualLock(pData, Size);
\r
816 if(ReadFile(hFile, pData, Size, &dw, NULL))
\r
818 if(CryptHashData(hHash, (BYTE*)pData, Size, 0))
\r
821 if(CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pHash, &dw, 0))
\r
825 VirtualUnlock(pData, Size);
\r
826 VirtualFree(pData, Size, MEM_DECOMMIT);
\r
828 CloseHandle(hFile);
\r
830 CryptDestroyHash(hHash);
\r
832 CryptReleaseContext(hProv, 0);
\r
838 BOOL RegisterTrustedModuleSHA1Hash(void* pHash)
\r
841 BYTE NullHash[20] = {0};
\r
844 if(FindTrustedModuleSHA1Hash(pHash))
\r
849 while(i < MAX_TRUSTED_MD5_HASH_TABLE)
\r
851 if(memcmp(&g_TrustedMD5HashTable[i], &NullHash, 20) == 0)
\r
853 memcpy(&g_TrustedMD5HashTable[i], pHash, 20);
\r
864 BOOL UnregisterTrustedModuleSHA1Hash(void* pHash)
\r
867 BYTE NullHash[20] = {0};
\r
871 while(i < MAX_TRUSTED_MD5_HASH_TABLE)
\r
873 if(memcmp(&g_TrustedMD5HashTable[i], pHash, 20) == 0)
\r
875 memcpy(&g_TrustedMD5HashTable[i], &NullHash, 20);
\r
885 BOOL UnloadUntrustedModule()
\r
894 if((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId())) != INVALID_HANDLE_VALUE)
\r
897 me.dwSize = sizeof(MODULEENTRY32);
\r
898 if(Module32First(hSnapshot, &me))
\r
903 FreeDuplicatedString(pw0);
\r
904 if(pw0 = AllocateStringW(Length))
\r
906 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
910 if(GetModuleFileNameW(me.hModule, pw0, Length) + 1 <= Length)
\r
912 Length = Length * 2;
\r
913 FreeDuplicatedString(pw0);
\r
914 pw0 = AllocateStringW(Length);
\r
920 if(!IsModuleTrusted(pw0))
\r
922 if(me.hModule != GetModuleHandleW(NULL))
\r
924 while(FreeLibrary(me.hModule))
\r
927 if(GetModuleFileNameW(me.hModule, pw0, Length) > 0)
\r
941 while(Module32Next(hSnapshot, &me));
\r
943 CloseHandle(hSnapshot);
\r
945 FreeDuplicatedString(pw0);
\r
949 // 関数ポインタを使用可能な状態に初期化
\r
950 BOOL InitializeLoadLibraryHook()
\r
955 if(!(hModule = GetModuleHandleW(L"kernel32.dll")))
\r
957 if(!(GET_FUNCTION(hModule, LoadLibraryA)))
\r
959 if(!(GET_FUNCTION(hModule, LoadLibraryW)))
\r
961 if(!(GET_FUNCTION(hModule, LoadLibraryExA)))
\r
963 if(!(GET_FUNCTION(hModule, LoadLibraryExW)))
\r
965 if(!(hModule = GetModuleHandleW(L"ntdll.dll")))
\r
967 if(!(GET_FUNCTION(hModule, LdrLoadDll)))
\r
969 if(!(GET_FUNCTION(hModule, LdrGetDllHandle)))
\r
971 if(!(GET_FUNCTION(hModule, RtlImageNtHeader)))
\r
973 if(!(hModule = LoadLibraryW(L"wintrust.dll")))
\r
975 if(!(GET_FUNCTION(hModule, CryptCATAdminCalcHashFromFileHandle)))
\r
980 // SetWindowsHookEx対策
\r
981 // DLL Injectionされた場合は上のh_LoadLibrary系関数でトラップ可能
\r
982 BOOL EnableLoadLibraryHook(BOOL bEnable)
\r
989 #ifdef USE_CODE_HOOK
\r
990 if(!SET_HOOK_FUNCTION(LoadLibraryA))
\r
992 if(!SET_HOOK_FUNCTION(LoadLibraryW))
\r
994 if(!SET_HOOK_FUNCTION(LoadLibraryExA))
\r
996 if(!SET_HOOK_FUNCTION(LoadLibraryExW))
\r
999 #ifdef USE_IAT_HOOK
\r
1000 if(!HookFunctionInIAT(p_LoadLibraryA, h_LoadLibraryA))
\r
1002 if(!HookFunctionInIAT(p_LoadLibraryW, h_LoadLibraryW))
\r
1004 if(!HookFunctionInIAT(p_LoadLibraryExA, h_LoadLibraryExA))
\r
1006 if(!HookFunctionInIAT(p_LoadLibraryExW, h_LoadLibraryExW))
\r
1013 #ifdef USE_CODE_HOOK
\r
1014 if(!END_HOOK_FUNCTION(LoadLibraryA))
\r
1016 if(!END_HOOK_FUNCTION(LoadLibraryW))
\r
1018 if(!END_HOOK_FUNCTION(LoadLibraryExA))
\r
1020 if(!END_HOOK_FUNCTION(LoadLibraryExW))
\r
1023 #ifdef USE_IAT_HOOK
\r
1024 if(!HookFunctionInIAT(h_LoadLibraryA, p_LoadLibraryA))
\r
1026 if(!HookFunctionInIAT(h_LoadLibraryW, p_LoadLibraryW))
\r
1028 if(!HookFunctionInIAT(h_LoadLibraryExA, p_LoadLibraryExA))
\r
1030 if(!HookFunctionInIAT(h_LoadLibraryExW, p_LoadLibraryExW))
\r
1037 // ReadProcessMemory、WriteProcessMemory、CreateRemoteThread対策
\r
1038 // TerminateProcessのみ許可
\r
1039 BOOL RestartProtectedProcess(LPCTSTR Keyword)
\r
1043 SID_IDENTIFIER_AUTHORITY sia = SECURITY_WORLD_SID_AUTHORITY;
\r
1045 SECURITY_DESCRIPTOR sd;
\r
1046 TCHAR* CommandLine;
\r
1047 SECURITY_ATTRIBUTES sa;
\r
1049 PROCESS_INFORMATION pi;
\r
1051 if(_tcslen(GetCommandLine()) >= _tcslen(Keyword) && _tcscmp(GetCommandLine() + _tcslen(GetCommandLine()) - _tcslen(Keyword), Keyword) == 0)
\r
1053 if(pACL = (ACL*)malloc(sizeof(ACL) + 1024))
\r
1055 if(InitializeAcl(pACL, sizeof(ACL) + 1024, ACL_REVISION))
\r
1057 if(AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID))
\r
1059 if(AddAccessAllowedAce(pACL, ACL_REVISION, PROCESS_TERMINATE, pSID))
\r
1061 if(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
\r
1063 if(SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE))
\r
1065 if(CommandLine = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(GetCommandLine()) + _tcslen(Keyword) + 1)))
\r
1067 _tcscpy(CommandLine, GetCommandLine());
\r
1068 _tcscat(CommandLine, Keyword);
\r
1069 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
1070 sa.lpSecurityDescriptor = &sd;
\r
1071 sa.bInheritHandle = FALSE;
\r
1072 GetStartupInfo(&si);
\r
1073 if(CreateProcess(NULL, CommandLine, &sa, NULL, FALSE, 0, NULL, NULL, &si, &pi))
\r
1075 CloseHandle(pi.hThread);
\r
1076 CloseHandle(pi.hProcess);
\r
1079 free(CommandLine);
\r