⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apihook.cpp

📁 这是一本学习 window编程的很好的参考教材
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		// Functions with address above lpMaximumApplicationAddress require
		// special processing (Windows 9x only)
		//
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		sm_pvMaxAppAddr = si.lpMaximumApplicationAddress;
	} // if
   
	if (m_pfnOrig > sm_pvMaxAppAddr) 
	{
		//
		// The address is in a shared DLL; the address needs fixing up 
		//
		PBYTE pb = (PBYTE) m_pfnOrig;
		if (pb[0] == cPushOpCode) 
		{
			//
			// Skip over the PUSH op code and grab the real address
			//
			PVOID pv = * (PVOID*) &pb[1];
			m_pfnOrig = (PROC) pv;
		} // if
	} // if
}


//---------------------------------------------------------------------------
// ~CHookedFunction
//  
//
//---------------------------------------------------------------------------
CHookedFunction::~CHookedFunction()
{
	UnHookImport();
}


PCSTR CHookedFunction::Get_CalleeModName() const
{
	return const_cast<PCSTR>(m_szCalleeModName);
}

PCSTR CHookedFunction::Get_FuncName() const
{
	return const_cast<PCSTR>(m_szFuncName);
}

PROC CHookedFunction::Get_pfnHook() const
{
	return m_pfnHook;
}

PROC CHookedFunction::Get_pfnOrig() const
{
	return m_pfnOrig;
}

//---------------------------------------------------------------------------
// HookImport
//  
// Set up a new hook function
//---------------------------------------------------------------------------
BOOL CHookedFunction::HookImport()
{
	m_bHooked = DoHook(TRUE, m_pfnOrig, m_pfnHook);
	return m_bHooked;
}

//---------------------------------------------------------------------------
// UnHookImport
//  
// Restore the original API handler
//---------------------------------------------------------------------------
BOOL CHookedFunction::UnHookImport()
{
	if (m_bHooked)
		m_bHooked = !DoHook(FALSE, m_pfnHook, m_pfnOrig);
	return !m_bHooked;
}

//---------------------------------------------------------------------------
// ReplaceInAllModules
//  
// Replace the address of a imported function entry  in all modules
//---------------------------------------------------------------------------
BOOL CHookedFunction::ReplaceInAllModules(
	BOOL  bHookOrRestore,
	PCSTR pszCalleeModName, 
	PROC  pfnCurrent, 
	PROC  pfnNew
	) 
{
	BOOL bResult = FALSE;

	if ((NULL != pfnCurrent) && (NULL != pfnNew))
	{
		BOOL                bReplace  = FALSE;
		CExeModuleInstance  *pProcess = NULL;
		CTaskManager        taskManager; 
		CModuleInstance     *pModule;
		//
		// Retrieves information about current process and modules. 
		// The taskManager dynamically decides whether to use ToolHelp 
		// library or PSAPI
		//
		taskManager.PopulateProcess(::GetCurrentProcessId(), TRUE);
		pProcess = taskManager.GetProcessById(::GetCurrentProcessId());
		if (NULL != pProcess)
		{
			// Enumerates all modules loaded by (pProcess) process
			for (int i = 0; i < pProcess->GetModuleCount(); i++)
			{
				pModule = pProcess->GetModuleByIndex(i);
				bReplace = 
					(pModule->Get_Module() != ModuleFromAddress(CApiHookMgr::MyLoadLibraryA)); 

				// We don't hook functions in our own modules
				if (bReplace)
					// Hook this function in this module
					bResult = ReplaceInOneModule(
						pszCalleeModName, 
						pfnCurrent, 
						pfnNew, 
						pModule->Get_Module()
						) || bResult;

			} // for
			// Hook this function in the executable as well
			bResult = ReplaceInOneModule(
				pszCalleeModName, 
				pfnCurrent, 
				pfnNew, 
				pProcess->Get_Module()
				) || bResult;
		} // if
	} // if
	return bResult;
}


//---------------------------------------------------------------------------
// ReplaceInOneModule
//  
// Replace the address of the function in the IAT of a specific module
//---------------------------------------------------------------------------
BOOL CHookedFunction::ReplaceInOneModule(
	PCSTR   pszCalleeModName, 
	PROC    pfnCurrent, 
	PROC    pfnNew, 
	HMODULE hmodCaller
	) 
{
	BOOL bResult = FALSE;
	__try
	{
		ULONG ulSize;
		// Get the address of the module's import section
		PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 
			(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
			hmodCaller, 
			TRUE, 
			IMAGE_DIRECTORY_ENTRY_IMPORT, 
			&ulSize
			);
		// Does this module has import section ?
		if (pImportDesc == NULL)
			__leave;  
		// Loop through all descriptors and
		// find the import descriptor containing references to callee's functions
		while (pImportDesc->Name)
		{
			PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
			if (stricmp(pszModName, pszCalleeModName) == 0) 
				break;   // Found
			pImportDesc++;
		} // while
		// Does this module import any functions from this callee ?
		if (pImportDesc->Name == 0)
			__leave;  
		// Get caller's IAT 
		PIMAGE_THUNK_DATA pThunk = 
			(PIMAGE_THUNK_DATA)( (PBYTE) hmodCaller + pImportDesc->FirstThunk );
		// Replace current function address with new one
		while (pThunk->u1.Function)
		{
			// Get the address of the function address
			PROC* ppfn = (PROC*) &pThunk->u1.Function;
			// Is this the function we're looking for?
			BOOL bFound = (*ppfn == pfnCurrent);
			// Is this Windows 9x
			if (!bFound && (*ppfn > sm_pvMaxAppAddr)) 
			{
				PBYTE pbInFunc = (PBYTE) *ppfn;
				// Is this a wrapper (debug thunk) represented by PUSH instruction?
				if (pbInFunc[0] == cPushOpCode) 
				{
					ppfn = (PROC*) &pbInFunc[1];
					// Is this the function we're looking for?
					bFound = (*ppfn == pfnCurrent);
				} // if
			} // if

			if (bFound) 
			{
				MEMORY_BASIC_INFORMATION mbi;
				::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
				// In order to provide writable access to this part of the 
				// memory we need to change the memory protection
				if (FALSE == ::VirtualProtect(
					mbi.BaseAddress,
					mbi.RegionSize,
					PAGE_READWRITE,
					&mbi.Protect)
					)
					__leave;
				// Hook the function.
                *ppfn = *pfnNew;
				bResult = TRUE;
				// Restore the protection back
                DWORD dwOldProtect;
				::VirtualProtect(
					mbi.BaseAddress,
					mbi.RegionSize,
					mbi.Protect,
					&dwOldProtect
					);
				break;
			} // if
			pThunk++;
		} // while
	}
	__finally
	{
		// do nothing
	}
	// This function is not in the caller's import section
	return bResult;
}

//---------------------------------------------------------------------------
// DoHook
//  
// Perform actual replacing of function pointers
//---------------------------------------------------------------------------
BOOL CHookedFunction::DoHook(
	BOOL bHookOrRestore,
	PROC pfnCurrent, 
	PROC pfnNew
	)
{
	// Hook this function in all currently loaded modules
	return ReplaceInAllModules(
		bHookOrRestore, 
		m_szCalleeModName, 
		pfnCurrent, 
		pfnNew
		);
}

//
// Indicates whether the hooked function is mandatory one
//
BOOL CHookedFunction::IsMandatory()
{
	BOOL bResult = FALSE;
	API_FUNC_ID apiFuncId;
	for (int i = 0; i < NUMBER_OF_MANDATORY_API_FUNCS; i++)
	{
		apiFuncId = MANDATORY_API_FUNCS[i];
		if ( (0==stricmp(apiFuncId.szCalleeModName, m_szCalleeModName)) &&
		     (0==stricmp(apiFuncId.szFuncName, m_szFuncName)) )
		{
			bResult = TRUE;
			break;
		} // if
	} // for

	return bResult;
}

//---------------------------------------------------------------------------
// 
// class CHookedFunctions 
//
//---------------------------------------------------------------------------

CHookedFunctions::CHookedFunctions(CApiHookMgr* pApiHookMgr):
	m_pApiHookMgr(pApiHookMgr)
{

}

CHookedFunctions::~CHookedFunctions()
{

}


//---------------------------------------------------------------------------
// GetHookedFunction
//  
// Return the address of an CHookedFunction object
//---------------------------------------------------------------------------
CHookedFunction* CHookedFunctions::GetHookedFunction(
	HMODULE hmodOriginal, 
	PCSTR   pszFuncName
	)
{
	char szFileName[MAX_PATH];
	::GetModuleFileName(hmodOriginal, szFileName, MAX_PATH);
	// We must extract only the name and the extension
	ExtractModuleFileName(szFileName);

	return GetHookedFunction(szFileName, pszFuncName);
}

//---------------------------------------------------------------------------
// GetFunctionNameFromExportSection
//  
// Return the name of the function from EAT by its ordinal value
//---------------------------------------------------------------------------
BOOL CHookedFunctions::GetFunctionNameFromExportSection(
	HMODULE hmodOriginal,
	DWORD   dwFuncOrdinalNum,
	PSTR    pszFuncName
	) 
{
	BOOL bResult = FALSE;
	// Make sure we return a valid string (atleast an empty one)
	strcpy(pszFuncName, "\0");
	__try
	{
		ULONG ulSize;
		// Get the address of the module's export section
		PIMAGE_EXPORT_DIRECTORY pExportDir = 
			(PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
			hmodOriginal, 
			TRUE, 
			IMAGE_DIRECTORY_ENTRY_EXPORT, 
			&ulSize
			);
		// Does this module has export section ?
		if (pExportDir == NULL)
			__leave;  
		// Get the name of the DLL
		PSTR pszDllName = reinterpret_cast<PSTR>( pExportDir->Name + (DWORD)hmodOriginal);
		// Get the starting ordinal value. By default is 1, but
		// is not required to be so
		DWORD dwFuncNumber = pExportDir->Base;
		// The number of entries in the EAT
		DWORD dwNumberOfExported = pExportDir->NumberOfFunctions;
		// Get the address of the ENT
		PDWORD pdwFunctions = (PDWORD)( pExportDir->AddressOfFunctions + (DWORD)hmodOriginal);
		//  Get the export ordinal table
		PWORD pwOrdinals = (PWORD)(pExportDir->AddressOfNameOrdinals + (DWORD)hmodOriginal);
		// Get the address of the array with all names
		DWORD *pszFuncNames =	(DWORD *)(pExportDir->AddressOfNames + (DWORD)hmodOriginal);

		PSTR pszExpFunName;

		// Walk through all of the entries and try to locate the
		// one we are looking for
		for (long i = 0; i < dwNumberOfExported; i++, pdwFunctions++)
		{
			DWORD entryPointRVA = *pdwFunctions;
			if ( entryPointRVA == 0 )   // Skip over gaps in exported function
				continue;               // ordinals (the entrypoint is 0 for
										// these functions).
			// See if this function has an associated name exported for it.
			for ( unsigned j=0; j < pExportDir->NumberOfNames; j++ )
			{
				// Note that pwOrdinals[x] return values starting form 0.. (not from 1)
				if ( pwOrdinals[j] == i  )
				{
					pszExpFunName = (PSTR)(pszFuncNames[j] + (DWORD)hmodOriginal);
					// Is this the same ordinal value ?
					// Notice that we need to add 1 to pwOrdinals[j] to get actual 
					// number
					if (dwFuncOrdinalNum == pwOrdinals[j] + 1)
					{
						if ((pszExpFunName != NULL) && (strlen(pszExpFunName) > 0))
							strcpy(pszFuncName, pszExpFunName);
						__leave;
					}
				}
			}
		} // for
	}
	__finally
	{
		// do nothing
	}
	// This function is not in the caller's import section
	return bResult;
}

//---------------------------------------------------------------------------
// GetFunctionNameByOrdinal
//  
// Return the name of the function by its ordinal value
//---------------------------------------------------------------------------
void CHookedFunctions::GetFunctionNameByOrdinal(
	PCSTR   pszCalleeModName, 
	DWORD   dwFuncOrdinalNum,
	PSTR    pszFuncName
	)
{
	HMODULE hmodOriginal = ::GetModuleHandle(pszCalleeModName);
	// Take the name from the export section of the DLL
	GetFunctionNameFromExportSection(hmodOriginal, dwFuncOrdinalNum, pszFuncName);
}



//---------------------------------------------------------------------------
// GetHookedFunction
//  
// Return the address of an CHookedFunction object
//---------------------------------------------------------------------------
CHookedFunction* CHookedFunctions::GetHookedFunction( 
	PCSTR   pszCalleeModName, 
	PCSTR   pszFuncName
	)
{
	CHookedFunction* pHook = NULL;
	char szFuncName[MAX_PATH];
	//
	// Prevent accessing invalid pointers and examine values 
	// for APIs exported by ordinal
	//
	if ( (pszFuncName) && 
	     ((DWORD)pszFuncName > 0xFFFF) && 
		 strlen(pszFuncName) ) 
	{
		strcpy(szFuncName, pszFuncName);
	} // if
	else
	{
		GetFunctionNameByOrdinal(pszCalleeModName, (DWORD)pszFuncName, szFuncName);
	}
	// Search in the map only if we have found the name of the requested function
	if (strlen(szFuncName) > 0)
	{
		char szKey[MAX_PATH];
		sprintf(
			szKey, 
			"<%s><%s>", 
			pszCalleeModName,
			szFuncName
			);
		// iterators can be used to check if an entry is in the map
		CHookedFunctions::const_iterator citr = find( szKey );
		if ( citr != end() )
			pHook = citr->second;
	} // if

	return pHook;
}



//---------------------------------------------------------------------------
// AddHook
//  
// Add a new object to the container
//---------------------------------------------------------------------------
BOOL CHookedFunctions::AddHook(CHookedFunction* pHook)
{
	BOOL bResult = FALSE;
	if (NULL != pHook)
	{
		char szKey[MAX_PATH];
		sprintf(
			szKey, 
			"<%s><%s>", 
			pHook->Get_CalleeModName(),
			pHook->Get_FuncName()
			);
		// Find where szKey is or should be
		CHookedFunctions::iterator lb = lower_bound(szKey);
		//
		// when an "add" is performed, insert() is more efficient
		// than operator[].
		// For more details see -item 24 page 109 "Effective STL" by Meyers
		//
		// Adds pair(pszKey, pObject) to the map
		insert( lb, value_type(szKey, pHook) );
		//
		// added to the map
		//
		bResult = TRUE;
	} // if
	return bResult;
}

//---------------------------------------------------------------------------
// RemoveHook
//  
// Remove exising object pointer from the container
//---------------------------------------------------------------------------
BOOL CHookedFunctions::RemoveHook(CHookedFunction* pHook)
{
	BOOL bResult = FALSE;
	try
	{
		if (NULL != pHook)
		{
			char szKey[MAX_PATH];
			sprintf(
				szKey, 
				"<%s><%s>", 
				pHook->Get_CalleeModName(),
				pHook->Get_FuncName()
				);
			//
			// Find where szKey is located 
			//
			CHookedFunctions::iterator itr = find(szKey);
			if (itr != end())
			{
				delete itr->second;
				erase(itr);
			}
			bResult = TRUE;
		} // if
	}
	catch (...)
	{
		bResult = FALSE;
	}
	return bResult;
}
//----------------------End of file -----------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -