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

📄 hookapi.cpp

📁 注入呼出外挂窗口
💻 CPP
字号:
/*
//////////////////////////////////////////////////////////////////////////
HookApi 0.5

thanks to xIkUg ,sucsor

by 海风月影[RCT] , eIcn#live.cn
2008.04.15

//////////////////////////////////////////////////////////////////////////
//更新内容
2008.04.15  0.5

1,重新写了Stub,换了一种模式,使hook更加自由,将hookbefore和hookafter合并
HookProc的定义方式与以前有所不同:

HookProc的函数类型和原来的api一样,只是参数比原API多2个
DWORD WINAPI HookProc(DWORD RetAddr ,__pfnXXXX pfnXXXX, ...);

//参数比原始的API多2个参数
RetAddr	//调用api的返回地址
pfnXXX 	//类型为__pfnXXXX,待hook的api的声明类型,用于调用未被hook的api

详见My_LoadLibraryA
原始的LoadLibraryA的声明是:

HMODULE WINAPI LoadLibraryA( LPCSTR lpLibFileName );

那么首先定义一下hook的WINAPI的类型
typedef HMODULE (WINAPI __pfnLoadLibraryA)(LPCTSTR lpFileName);

然后hookproc的函数声明如下:
HMODULE WINAPI My_LoadLibraryA(DWORD RetAddr,
							   __pfnLoadLibraryA pfnLoadLibraryA,
							   LPCTSTR lpFileName
							   );

比原来的多了2个参数,参数位置不能颠倒,在My_LoadLibraryA中可以自由的调用未被hook的pfnLoadLibraryA
也可以调用系统的LoadLibraryA,不过要自己在hookproc中处理好重入问题

另外,也可以在My_LoadLibraryA中使用UnInstallHookApi()函数来卸载hook,用法如下:
将第二个参数__pfnLoadLibraryA pfnLoadLibraryA强制转换成PHOOKENVIRONMENT类型,使用UnInstallHookApi来卸载

例如:
UnInstallHookApi((PHOOKENVIRONMENT)pfnLoadLibraryA);


至于以前版本的HookBefore和HookAfter,完全可以在自己的HookProc里面灵活使用了


2,支持卸载hook
InstallHookApi()调用后会返回一个PHOOKENVIRONMENT类型的指针
需要卸载的时候可以使用UnInstallHookApi(PHOOKENVIRONMENT pHookEnv)来卸载

在HookProc中也可以使用UnInstallHookApi来卸载,参数传入HookProc中的第二个参数

注意:当HookProc中使用UnInstallHookApi卸载完后就不能用第二个参数来调用API了~~,切记!

2008.04.15  0.41
1,前面的deroko的LdeX86 有BUG,678b803412 会算错
	换了一个LDX32,代码更少,更容易理解

2,修复了VirtualProtect的一个小BUG


0.4以前
改动太大了,前面的就不写了
*/


#include <windows.h>
#include <stdio.h>
#include "HookApi.h"

#pragma comment(linker, "/SECTION:HookStub,RW")

#define ALLOCATE_HookStub ALLOCATE(HookStub)

#pragma code_seg("HookStub")
#pragma optimize("",off)
ALLOCATE_HookStub HOOKENVIRONMENT pEnv={0};
NAKED DWORD GetDelta()
{
	__asm
	{
		call next
next:
		pop eax
		sub eax,offset next
		ret
	}
}
NAKED void NewStub()
{
	__asm
	{	
		jmp next
back:
		_emit 0xE9
		NOP
		NOP
		NOP
		NOP
next:
		push [esp]
		push [esp]
		push eax		//保存一下Stub中唯一使用到的EAX
		call GetDelta
		lea eax,[eax+pEnv]
		mov dword ptr [esp+0xC],eax
		pop eax			//恢复EAX
		jmp back
	}
}
NAKED DWORD GetEndAddr()
{
	__asm
	{
		call next
next:
		pop eax
		sub eax,5
		ret
	}
}
#pragma optimize("",off)
#pragma code_seg()


DWORD __stdcall GetOpCodeSize(BYTE* iptr0)
{
	BYTE* iptr = iptr0;

	DWORD f = 0;

prefix:
	BYTE b = *iptr++;

	f |= table_1[b];

	if (f&C_FUCKINGTEST)
		if (((*iptr)&0x38)==0x00)   // ttt
			f=C_MODRM+C_DATAW0;       // TEST
		else
			f=C_MODRM;                // NOT,NEG,MUL,IMUL,DIV,IDIV

	if (f&C_TABLE_0F)
	{
		b = *iptr++;
		f = table_0F[b];
	}

	if (f==C_ERROR)
	{
		//printf("error in %02X\n",b);
		return C_ERROR;
	}

	if (f&C_PREFIX)
	{
		f&=~C_PREFIX;
		goto prefix;
	}

	if (f&C_DATAW0) if (b&0x01) f|=C_DATA66; else f|=C_DATA1;

	if (f&C_MODRM)
	{
		b = *iptr++;
		BYTE mod = b & 0xC0;
		BYTE rm  = b & 0x07;
		if (mod!=0xC0)
		{
			if (f&C_67)         // modrm16
			{
				if ((mod==0x00)&&(rm==0x06)) f|=C_MEM2;
				if (mod==0x40) f|=C_MEM1;
				if (mod==0x80) f|=C_MEM2;
			}
			else                // modrm32
			{
				if (mod==0x40) f|=C_MEM1;
				if (mod==0x80) f|=C_MEM4;
				if (rm==0x04) rm = (*iptr++) & 0x07;    // rm<-sib.base
				if ((rm==0x05)&&(mod==0x00)) f|=C_MEM4;
			}
		}
	} // C_MODRM

	if (f&C_MEM67)  if (f&C_67) f|=C_MEM2;  else f|=C_MEM4;
	if (f&C_DATA66) if (f&C_66) f|=C_DATA2; else f|=C_DATA4;

	if (f&C_MEM1)  iptr++;
	if (f&C_MEM2)  iptr+=2;
	if (f&C_MEM4)  iptr+=4;

	if (f&C_DATA1) iptr++;
	if (f&C_DATA2) iptr+=2;
	if (f&C_DATA4) iptr+=4;

	return iptr - iptr0;
}

PHOOKENVIRONMENT __stdcall InstallHookApi(PCHAR DllName,PCHAR ApiName,PVOID HookProc)
{
	HMODULE DllHandle;
	PVOID ApiEntry;
	int ReplaceCodeSize;
	DWORD oldpro;
	DWORD SizeOfStub;
	DWORD delta;
	DWORD RetSize =0;
	
	PHOOKENVIRONMENT pHookEnv;

	if (HookProc == NULL)
	{
		return NULL;
	}

	DllHandle = GetModuleHandle(DllName);
	if (DllHandle == NULL)
		DllHandle = LoadLibrary(DllName);
	if (DllHandle == NULL)
		return NULL;

	ApiEntry = GetProcAddress(DllHandle,ApiName);
	if (ApiEntry == NULL) return NULL;

	ReplaceCodeSize = GetOpCodeSize((BYTE*)ApiEntry);
 
	while (ReplaceCodeSize < 5)
		ReplaceCodeSize += GetOpCodeSize((BYTE*)((DWORD)ApiEntry + (DWORD)ReplaceCodeSize));

	if (ReplaceCodeSize > 16) return NULL;

	SizeOfStub = GetEndAddr()-(DWORD)&pEnv;
	
	pHookEnv = (PHOOKENVIRONMENT)VirtualAlloc(NULL,SizeOfStub,MEM_COMMIT,PAGE_READWRITE);
	memset((void*)&pEnv,0x90,sizeof(pEnv));
	CopyMemory(pHookEnv,(PVOID)&pEnv,SizeOfStub);
	CopyMemory((void*)pHookEnv,(void*)&pEnv,sizeof(pEnv.savebytes));
	CopyMemory(pHookEnv->savebytes,ApiEntry,ReplaceCodeSize);

	pHookEnv->OrgApiAddr = ApiEntry;
	pHookEnv->SizeOfReplaceCode = ReplaceCodeSize;

	pHookEnv->jmptoapi[0]=0xE9;
	*(DWORD*)(&pHookEnv->jmptoapi[1]) = (DWORD)ApiEntry + ReplaceCodeSize - ((DWORD)pHookEnv->jmptoapi + 5);

	//patch api
	if (!VirtualProtect(ApiEntry,ReplaceCodeSize,PAGE_EXECUTE_READWRITE,&oldpro))
		return FALSE;

	delta = (DWORD)pHookEnv - (DWORD)&pEnv;

	*(DWORD*)(&JMPGate[1]) = ((DWORD)NewStub + delta) - ((DWORD)ApiEntry + 5);

	WriteProcessMemory(GetCurrentProcess(), ApiEntry, JMPGate, sizeof(JMPGate),&RetSize);

	if (!VirtualProtect(ApiEntry,ReplaceCodeSize,oldpro,&oldpro))
		return FALSE;

	//写入变量
	*(DWORD*)((DWORD)NewStub + delta + 3) = (DWORD)HookProc - ((DWORD)NewStub + delta + 3 + 4);

	return pHookEnv;
}

BOOL __stdcall UnInstallHookApi(PHOOKENVIRONMENT pHookEnv)
{
	DWORD oldpro;
	DWORD RetSize;

	//如果内存不存在了,则退出
	if(IsBadReadPtr((const void*)pHookEnv,sizeof(HOOKENVIRONMENT)))
		return FALSE;

	if(!VirtualProtect(pHookEnv->OrgApiAddr,pHookEnv->SizeOfReplaceCode,PAGE_EXECUTE_READWRITE,&oldpro))
		return FALSE;
	WriteProcessMemory(GetCurrentProcess(),pHookEnv->OrgApiAddr,pHookEnv->savebytes,pHookEnv->SizeOfReplaceCode,&RetSize);

	if(!VirtualProtect(pHookEnv->OrgApiAddr,pHookEnv->SizeOfReplaceCode,oldpro,&oldpro))
		return FALSE;

	VirtualFree((LPVOID)pHookEnv,0,MEM_RELEASE);
}


//定义下面这行可以作为演示使用
//#define TEST_MAIN


#ifdef TEST_MAIN

BOOL IsMe = FALSE;

//先定义一下要hook的WINAPI
typedef HMODULE (WINAPI __pfnLoadLibraryA)(LPCTSTR lpFileName);

/*
HookProc的参数声明方式类型等和原来的api一样,只是参数比原API多2个
DWORD WINAPI HookProc(DWORD RetAddr ,__pfnXXXX pfnXXXX, ...);

//参数比原始的API多2个参数
RetAddr	//调用api的返回地址
pfnXXX 	//类型为__pfnXXXX,待hook的api的声明类型,用于调用未被hook的api

详见My_LoadLibraryA
原始的LoadLibraryA的声明是:

HMODULE WINAPI LoadLibraryA( LPCSTR lpLibFileName );

那么首先定义一下hook的WINAPI的类型
typedef HMODULE (WINAPI __pfnLoadLibraryA)(LPCTSTR lpFileName);

然后hookproc的函数声明如下:
HMODULE WINAPI My_LoadLibraryA(DWORD RetAddr,
							   __pfnLoadLibraryA pfnLoadLibraryA,
							   LPCTSTR lpFileName
							   );

比原来的多了2个参数,参数位置不能颠倒,在My_LoadLibraryA中可以自由的调用未被hook的pfnLoadLibraryA
也可以调用系统的LoadLibraryA,不过要自己在hookproc中处理好重入问题

另外,也可以在My_LoadLibraryA中使用UnInstallHookApi()函数来卸载hook,用法如下:
将第二个参数__pfnLoadLibraryA pfnLoadLibraryA强制转换成PHOOKENVIRONMENT类型,使用UnInstallHookApi来卸载

例如:
UnInstallHookApi((PHOOKENVIRONMENT)pfnLoadLibraryA);


至于以前版本的HookBefore和HookAfter,完全可以在自己的HookProc里面灵活使用了

*/

HMODULE WINAPI My_LoadLibraryA(DWORD RetAddr,
							   __pfnLoadLibraryA pfnLoadLibraryA,
							   LPCTSTR lpFileName
							   )
{
	HMODULE hLib;
	
	//需要自己处理重入和线程安全问题
	if (!IsMe)
	{
		IsMe = TRUE;
		MessageBoxA(NULL,lpFileName,"test",MB_ICONINFORMATION);
		hLib = LoadLibrary(lpFileName);//这里调用的是系统的,已经被hook过的
		IsMe = FALSE;
		//这里是卸载Hook,这里卸载完就不能用pfnLoadLibraryA来调用了
		UnInstallHookApi((PHOOKENVIRONMENT)pfnLoadLibraryA);
		return hLib;
	}
	return pfnLoadLibraryA(lpFileName);//这里调用非hook的
}


int main()
{
	DWORD RetSize =0;
	DWORD dwThreadId;
	HANDLE hThread;
	PHOOKENVIRONMENT pHookEnv;

	pHookEnv = InstallHookApi("Kernel32.dll", "LoadLibraryA", My_LoadLibraryA);
	LoadLibrary("InjectDll.dll");
	MessageBoxA(NULL,"Safe Here!!!","Very Good!!",MB_ICONINFORMATION);
	UnInstallHookApi(pHookEnv);//由于HookProc中卸载过了,所以这里的卸载就无效了
	MessageBoxA(NULL,"UnInstall Success!!!","Good!!",MB_ICONINFORMATION);
	return 0;
}

#endif

 

⌨️ 快捷键说明

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