1 #include "HookImportFunction.h"
2 #include <tlhelp32.h>
3 
4 
5 // These code come from: http://dev.csdn.net/article/2/2786.shtm
6 // I fixed a bug in it and improved it to hook all the modules of a program.
7 
8 #define MakePtr(cast, ptr, AddValue) (cast)((size_t)(ptr)+(size_t)(AddValue))
9 
GetNamedImportDescriptor(HMODULE hModule,LPCSTR szImportModule)10 static PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportModule)
11 {
12 	PIMAGE_DOS_HEADER pDOSHeader;
13 	PIMAGE_NT_HEADERS pNTHeader;
14 	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
15 
16 	if ((szImportModule == NULL) || (hModule == NULL))
17 		return NULL;
18 	pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
19 	if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) || (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)) {
20 		return NULL;
21 	}
22 	pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
23 	if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) || (pNTHeader->Signature != IMAGE_NT_SIGNATURE))
24 		return NULL;
25 	if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
26 		return NULL;
27 	pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
28 	while (pImportDesc->Name) {
29 		PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name);
30 //		if (_stricmp(szCurrMod, szImportModule) == 0)
31 		if (lstrcmpi(szCurrMod, szImportModule) == 0)
32 			break;
33 		pImportDesc++;
34 	}
35 	if (pImportDesc->Name == (DWORD)0)
36 		return NULL;
37 	return pImportDesc;
38 }
39 
IsNT()40 static BOOL IsNT()
41 {
42 	OSVERSIONINFO stOSVI;
43 	BOOL bRet;
44 
45 	memset(&stOSVI, 0, sizeof(OSVERSIONINFO));
46 	stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
47 	bRet = GetVersionEx(&stOSVI);
48 	if (FALSE == bRet) return FALSE;
49 	return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId);
50 }
51 
HookImportFunction(HMODULE hModule,LPCSTR szImportModule,LPCSTR szFunc,PROC paHookFuncs,PROC * paOrigFuncs)52 static BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs)
53 {
54 	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
55 	PIMAGE_THUNK_DATA pOrigThunk;
56 	PIMAGE_THUNK_DATA pRealThunk;
57 
58 	if (!IsNT() && ((size_t)hModule >= 0x80000000))
59 		return FALSE;
60 	pImportDesc = GetNamedImportDescriptor(hModule, szImportModule);
61 	if (pImportDesc == NULL)
62 		return FALSE;
63 	pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk);
64 	pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk);
65 	while (pOrigThunk->u1.Function) {
66 		if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
67 			PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData);
68 			BOOL bDoHook;
69 			// When hook EditPlus, read pByName->Name[0] will case this dll terminate, so call IsBadReadPtr() here.
70 			if (IsBadReadPtr(pByName, sizeof(IMAGE_IMPORT_BY_NAME))) {
71 				pOrigThunk++;
72 				pRealThunk++;
73 				continue;
74 			}
75 			if ('\0' == pByName->Name[0]) {
76 				pOrigThunk++;
77 				pRealThunk++;
78 				continue;
79 			}
80 			bDoHook = FALSE;
81 //			if ((szFunc[0] == pByName->Name[0]) && (_strcmpi(szFunc, (char*)pByName->Name) == 0)) {
82 			if ((szFunc[0] == pByName->Name[0]) && (lstrcmpi(szFunc, (char*)pByName->Name) == 0)) {
83 				if (paHookFuncs)
84 					bDoHook = TRUE;
85 			}
86 			if (bDoHook) {
87 				MEMORY_BASIC_INFORMATION mbi_thunk;
88 				DWORD dwOldProtect;
89 				if( VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
90 					return FALSE;
91 				if( !VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect) )
92 					return FALSE;
93 				if (paOrigFuncs)
94 					*paOrigFuncs = (PROC)InterlockedExchangePointer((PVOID)&(pRealThunk->u1.Function), paHookFuncs);
95 				else
96 					InterlockedExchangePointer((PVOID)&(pRealThunk->u1.Function), paHookFuncs);
97 
98 				VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);
99 				return TRUE;
100 			}
101 		}
102 		pOrigThunk++;
103 		pRealThunk++;
104 	}
105 	return FALSE;
106 }
107 
HookAPI(LPCSTR szImportModule,LPCSTR szFunc,PROC paHookFuncs,PROC * paOrigFuncs)108 BOOL HookAPI(LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs)
109 {
110 	HANDLE hSnapshot;
111 	MODULEENTRY32 me;
112 	BOOL bOk;
113 	DWORD err;
114 
115 	ZeroMemory(&me,sizeof(me));
116 	me.dwSize=sizeof(me);
117 
118 	if ((szImportModule == NULL) || (szFunc == NULL)) {
119 		return FALSE;
120 	}
121 
122 	do {
123 		hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
124 		if(hSnapshot != INVALID_HANDLE_VALUE) break;
125 		err = GetLastError();
126 		if(err == ERROR_BAD_LENGTH) Sleep(100);
127 	} while(err == ERROR_BAD_LENGTH);
128 
129 	if(hSnapshot == INVALID_HANDLE_VALUE) return FALSE;
130 
131 	bOk = Module32First(hSnapshot, &me);
132 	while (bOk) {
133 		HookImportFunction(me.hModule, szImportModule, szFunc, paHookFuncs, paOrigFuncs);
134 		bOk = Module32Next(hSnapshot, &me);
135 	}
136 	CloseHandle(hSnapshot);
137 	return TRUE;
138 }
139