C++ 在Ring3下的通用API HOOK

原文转自:http://www.cnblogs.com/AniX/archive/2010/10/26/1861693.html  代码部分我做过整理

说道API HOOK ,这已经是老掉牙的技术了,但是它的实用性却是不能忽视的。虽然在网上这类的文章很多,但大多数的实现方法是将一个函数的前5字节直接改为 jmp XXXX 。这种方法虽然简单可行,但是不通用,因为一些特殊函数的前5字节不是完整的,如果直接修改,就会截断指令,导致出错。以前在一个论坛上看到过一个用反汇编引擎实现的通用例子,感觉想法很好,于是自己也写了一个。其中用到了一个头文件LDasm.h(里面实际就是一个轻量级的反汇编引擎,网上可以下载到)。

 

第一个函数用于对指定API进行HOOK,并返回一个进入原函数的代理函数地址。

#include "stdafx.h"
#include "LDasm.h"
#include <windows.h>

DWORD proxyFunction;
void* HookFunc(char* ModuleName,char* FuncName,void* NewFunc)
{
	void* proxyFunction = 0;
	unsigned char* OpCode = 0;
	ULONG BackupLength = 0;
	unsigned char JmpCode[6]={0x68,0x00,0x00,0x00,0x00,0xc3};
	unsigned char JmpBackCode[6]={0x68,0x00,0x00,0x00,0x00,0xc3};
	/*
	原代码用的是GetModuleHandle(ModuleName);这要成功的
	前提是:只有欲获取的模块已映射到调用该函数的进程内,才会正确得到模块句柄。
	常用模块映射函数:LoadLibrary(..)
	*/
	HMODULE hMod = GetModuleHandle(ModuleName);
	void* sourFunc = GetProcAddress(hMod,FuncName);

	if(!sourFunc)
		return NULL;

	*(ULONG*)(&JmpCode[1])=(ULONG)NewFunc;

	while(BackupLength<6)
	{
		BackupLength += SizeOfCode((void*)((ULONG)sourFunc+BackupLength),&OpCode);
	}

	proxyFunction = VirtualAlloc(NULL,BackupLength + 6,MEM_RESERVE| MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	if (!proxyFunction)
		return NULL;

	*(ULONG*)((ULONG)JmpBackCode + 1) = (ULONG)sourFunc + BackupLength;
	RtlCopyMemory(proxyFunction,sourFunc,BackupLength);
	RtlCopyMemory((PVOID)((ULONG)proxyFunction + BackupLength),JmpBackCode, 6);
	FlushInstructionCache((HANDLE) - 1,proxyFunction,BackupLength + 6);
	DWORD OldProtect = 0;
	VirtualProtect(sourFunc, 6,PAGE_EXECUTE_READWRITE, &OldProtect);
	RtlCopyMemory(sourFunc,JmpCode, 6);
	VirtualProtect(sourFunc, 6,OldProtect, &OldProtect);
	FlushInstructionCache((HANDLE) -1,sourFunc, 6);
	return proxyFunction;
}

int audit()
{
	static int cnt;
	DWORD Lab1Offset;

	__asm
	{
		mov eax,Lab1;
		mov Lab1Offset,eax;
	}
	DWORD OldProtect = 0;
	VirtualProtect((void*)Lab1Offset, 4,PAGE_EXECUTE_READWRITE, &OldProtect);

	cnt++;
	//跳转前要绕过_chkesp
	__asm
	{
		pop edi;
		pop esi;
		pop ebx;
		mov esp,ebp;
		pop ebp;
	}

	__asm
	{
		mov eax,proxyFunction;
		mov ebx,Lab1;
		mov [ebx],eax;
		_emit 0x68;
Lab1:
		_emit 0x90;
		_emit 0x90;
		_emit 0x90;
		_emit 0x90;
		ret;
	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	proxyFunction = (DWORD)HookFunc("user32.dll","MessageBoxA",audit);

	MessageBox(NULL,"","",MB_OK);
	return 0;
}


你可能感兴趣的:(windows)